123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- const Router = require('@koa/router');
- const lark = require('@larksuiteoapi/node-sdk');
- const config = require('../config');
- const request = require('../utils/request');
- const util = require('../utils/util');
- const router = new Router({ prefix: '/robot' });
- /**
- * 飞书机器人服务接口
- * 主要用于发送飞书消息、创建知识库
- */
- // 获取租户token
- async function getTenantToken() {
- try {
- if (!config.FEISHU_APP_ID || !config.FEISHU_APP_SECRET) return '';
- const response = await request.post(
- 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
- JSON.stringify({
- app_id: config.FEISHU_APP_ID,
- app_secret: config.FEISHU_APP_SECRET,
- }),
- );
- const res = JSON.parse(response.data);
- if (res.code !== 0) return '';
- return res.tenant_access_token;
- } catch (error) {
- return '';
- }
- }
- // 获取租户token
- router.get('/getTenantToken', async (ctx) => {
- const token = await getTenantToken();
- if (!token) return util.fail(ctx, '获取飞书token失败');
- util.success(ctx, { token });
- });
- // 发送卡片消息
- router.post('/sendMessage', async (ctx) => {
- const token = await getTenantToken();
- if (!token) return util.fail(ctx, '获取飞书token失败');
- const { msgType, content, receiveId, templateId, variables, appId, appSecret } = ctx.request.body;
- if (!msgType || (msgType !== 'text' && msgType !== 'interactive')) {
- return ctx.throw(400, '消息类型错误,仅支持text和interactive');
- }
- if (msgType === 'text') {
- if (!content) return ctx.throw(400, '发送内容不能为空');
- } else {
- if (!templateId) {
- return ctx.throw(400, '发送模板不能为空');
- }
- }
- if (!receiveId) {
- return ctx.throw(400, '接收群组ID不能为空');
- }
- if (!appId || !appSecret) {
- return ctx.throw(400, '请先配置飞书appId或appSecret');
- }
- const client = new lark.Client({
- appId,
- appSecret,
- disableTokenCache: true,
- });
- if (msgType === 'text') {
- const res = await client.im.message.create(
- {
- params: {
- receive_id_type: 'chat_id',
- },
- data: {
- receive_id: receiveId,
- content: JSON.stringify({ text: content }),
- msg_type: 'text',
- },
- },
- lark.withTenantToken(token),
- );
- if (res.code === 0) {
- util.success(ctx, '发送成功');
- } else {
- util.fail(ctx, res.msg);
- }
- } else {
- const res = await client.im.message.createByCard(
- {
- params: {
- receive_id_type: 'chat_id', //chat_id
- },
- data: {
- receive_id: receiveId,
- msg_type: msgType,
- template_id: templateId,
- template_variable: variables || {},
- },
- },
- lark.withTenantToken(token),
- );
- if (res.code === 0) {
- util.success(ctx, '发送成功');
- } else {
- util.fail(ctx, res.msg);
- }
- }
- });
- // 获取机器人所在群列表
- router.get('/chat/groups', async (ctx) => {
- const token = await getTenantToken();
- if (!token) return util.fail(ctx, '获取飞书token失败');
- try {
- const response = await request.get('https://open.feishu.cn/open-apis/im/v1/chats', '', {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- });
- const res = JSON.parse(response.data);
- if (res.code === 0) {
- util.success(ctx, res.data);
- } else {
- util.fail(ctx, res.msg);
- }
- } catch (error) {
- util.fail(ctx, error);
- }
- });
- // 创建知识库副本
- router.post('/createNode', async (ctx) => {
- const token = await getTenantToken();
- if (!token) return util.fail(ctx, '获取飞书token失败');
- const { spaceId, nodeToken, title } = ctx.request.body;
- if (!spaceId || isNaN(spaceId) || !nodeToken) {
- return ctx.throw(400, '空间ID或节点token不能为空');
- }
- if (!title) {
- return ctx.throw(400, '知识库标题不能为空');
- }
- try {
- const response = await request.post(
- `https://open.feishu.cn/open-apis/wiki/v2/spaces/${spaceId}/nodes/${nodeToken}/copy`,
- JSON.stringify({
- target_space_id: parseInt(spaceId),
- target_parent_token: nodeToken,
- title,
- }),
- {
- headers: {
- Authorization: `Bearer ${token}`,
- 'Content-Type': 'application/json',
- },
- },
- );
- const res = JSON.parse(response.data);
- if (res.code === 0) {
- util.success(ctx, res.data);
- } else {
- util.fail(ctx, res.msg);
- }
- } catch (error) {
- util.fail(ctx, error);
- }
- });
- module.exports = router;
|