diff --git a/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx b/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx index 80899a77..d1254cc2 100644 --- a/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx +++ b/client/web/plugins/com.msgbyte.integration/src/IntegrationPanel.tsx @@ -2,7 +2,13 @@ import React, { useCallback, useState } from 'react'; import { Avatar, Button, Input, UserName } from '@capital/component'; import styled from 'styled-components'; import type { OpenAppInfo } from 'types'; -import { useAsyncRequest, postRequest } from '@capital/common'; +import { + useAsyncRequest, + postRequest, + showErrorToasts, + useGroupIdContext, + showSuccessToasts, +} from '@capital/common'; const Tip = styled.div` color: #999; @@ -37,18 +43,29 @@ const AppInfoCard = styled.div({ const IntegrationPanel: React.FC = React.memo(() => { const [appId, setAppId] = useState(''); const [openAppInfo, setOpenAppInfo] = useState(null); + const groupId = useGroupIdContext(); const [{ loading }, handleQueryApp] = useAsyncRequest(async () => { const { data } = await postRequest('/openapi/app/get', { appId, }); + if (!data) { + showErrorToasts('没找到该应用'); + return; + } + setOpenAppInfo(data); }, [appId]); - const handleAddBotIntoGroup = useCallback(() => { - console.log('TODO', appId); - }, [appId]); + const [{ loading: addBotLoading }, handleAddBotIntoGroup] = + useAsyncRequest(async () => { + await postRequest('/openapi/integration/addBotUser', { + appId, + groupId, + }); + showSuccessToasts(); + }, [appId]); return (
@@ -90,7 +107,12 @@ const IntegrationPanel: React.FC = React.memo(() => {
{openAppInfo.capability.includes('bot') && ( - )} diff --git a/server/services/openapi/bot.service.ts b/server/services/openapi/bot.service.ts index 7c2fa8f9..10fae1df 100644 --- a/server/services/openapi/bot.service.ts +++ b/server/services/openapi/bot.service.ts @@ -21,7 +21,7 @@ class OpenBotService extends TcService { params: { appId: 'string', }, - visibility: 'private', + visibility: 'public', }); this.registerAuthWhitelist(['/openapi/bot/login']); diff --git a/server/services/openapi/integration.service.ts b/server/services/openapi/integration.service.ts new file mode 100644 index 00000000..ef843827 --- /dev/null +++ b/server/services/openapi/integration.service.ts @@ -0,0 +1,83 @@ +import { call, DataNotFoundError, TcContext } from 'tailchat-server-sdk'; +import { TcService, config } from 'tailchat-server-sdk'; +import { isValidStr } from '../../lib/utils'; +import type { OpenApp } from '../../models/openapi/app'; + +/** + * 第三方应用集成 + */ +class OpenAppIntegrationService extends TcService { + get serviceName(): string { + return 'openapi.integration'; + } + + onInit(): void { + if (!config.enableOpenapi) { + return; + } + + this.registerAction('addBotUser', this.addBotUser, { + params: { + appId: 'string', + groupId: 'string', + }, + }); + } + + /** + * 在群组中添加机器人用户 + */ + async addBotUser( + ctx: TcContext<{ + appId: string; + groupId: string; + }> + ) { + const appId = ctx.params.appId; + const groupId = ctx.params.groupId; + const t = ctx.meta.t; + + const openapp: OpenApp = await ctx.call('openapi.app.get', { + appId, + }); + + if (!openapp) { + throw new DataNotFoundError(); + } + + if (!openapp.capability.includes('bot')) { + throw new Error(t('该应用的机器人服务尚未开通')); + } + + const botAccount: any = await ctx.call( + 'openapi.bot.getOrCreateBotAccount', + { + appId, + } + ); + + const userId = botAccount.userId; + if (!isValidStr(userId)) { + throw new Error(t('无法获取到机器人ID')); + } + + await ctx.call( + 'group.joinGroup', + { + groupId, + }, + { + meta: { + userId, + }, + } + ); + + await call(ctx).addGroupSystemMessage( + String(groupId), + `${ctx.meta.user.nickname} 在群组中添加了机器人 ${botAccount.nickname}` + ); + } +} + +export default OpenAppIntegrationService;