This commit is contained in:
2026-04-25 16:36:34 +08:00
commit db90e7579b
1876 changed files with 189777 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
{
"label": "third party integration",
"label.zh-CN": "第三方集成",
"name": "com.msgbyte.integration",
"url": "/plugins/com.msgbyte.integration/index.js",
"version": "0.0.0",
"author": "moonrailgun",
"description": "Used to integrate third-party applications in groups",
"description.zh-CN": "用于在群组中集成第三方应用",
"requireRestart": true
}

View File

@@ -0,0 +1,16 @@
{
"name": "@plugins/com.msgbyte.integration",
"main": "src/index.tsx",
"version": "0.0.0",
"description": "用于在群组中集成第三方应用",
"private": true,
"scripts": {
"sync:declaration": "tailchat declaration github"
},
"dependencies": {},
"devDependencies": {
"@types/styled-components": "^5.1.26",
"react": "18.2.0",
"styled-components": "^5.3.6"
}
}

View File

@@ -0,0 +1,135 @@
import React, { useState } from 'react';
import { Avatar, Button, Input, UserName } from '@capital/component';
import styled from 'styled-components';
import type { OpenAppInfo } from 'types';
import {
useAsyncRequest,
postRequest,
showErrorToasts,
useGroupIdContext,
showSuccessToasts,
} from '@capital/common';
import { Translate } from './translate';
const Tip = styled.div`
color: #999;
margin-bottom: 10px;
`;
const Row = styled.div`
display: flex;
`;
const AppInfoCard = styled.div({
backgroundColor: 'rgba(0, 0, 0, 0.1)',
borderRadius: 3,
padding: 10,
marginTop: 10,
'.app-info': {
flex: 1,
marginLeft: 10,
'.title': {
fontSize: 18,
fontWeight: 'bold',
},
'.action': {
marginTop: 10,
},
},
});
const IntegrationPanel: React.FC = React.memo(() => {
const [appId, setAppId] = useState('');
const [openAppInfo, setOpenAppInfo] = useState<OpenAppInfo | null>(null);
const groupId = useGroupIdContext();
const [{ loading }, handleQueryApp] = useAsyncRequest(async () => {
const { data } = await postRequest('/openapi/app/get', {
appId,
});
if (!data) {
showErrorToasts(Translate.notFoundApp);
return;
}
setOpenAppInfo(data);
}, [appId]);
const [{ loading: addBotLoading }, handleAddBotIntoGroup] =
useAsyncRequest(async () => {
await postRequest('/openapi/integration/addBotUser', {
appId,
groupId,
});
showSuccessToasts();
}, [appId]);
return (
<div>
<Tip>{Translate.onlyAllowManualAddition}</Tip>
<Row>
<Input
placeholder={Translate.appId}
value={appId}
onChange={(e) => setAppId(e.target.value)}
/>
<Button
type="primary"
disabled={!appId}
loading={loading}
onClick={handleQueryApp}
>
{Translate.search}
</Button>
</Row>
{openAppInfo && (
<div>
<AppInfoCard>
<Row>
<Avatar
size={56}
src={openAppInfo.appIcon}
name={openAppInfo.appName}
/>
<div className="app-info">
<div>{openAppInfo.appName}</div>
<div>{openAppInfo.appDesc}</div>
<Row>
<div>{Translate.developer}:</div>
<UserName userId={openAppInfo.owner} />
</Row>
<div className="action">
{openAppInfo.capability.includes('bot') ? (
<Button
type="primary"
size="small"
loading={addBotLoading}
onClick={handleAddBotIntoGroup}
>
{Translate.addBot}
</Button>
) : (
<Button type="primary" size="small" disabled={true}>
{Translate.cannotAddBot}
</Button>
)}
</div>
</div>
</Row>
</AppInfoCard>
</div>
)}
</div>
);
});
IntegrationPanel.displayName = 'IntegrationPanel';
export default IntegrationPanel;

View File

@@ -0,0 +1,14 @@
import { Loadable, regCustomPanel } from '@capital/common';
import { Translate } from './translate';
const PLUGIN_NAME = '第三方集成';
console.log(`Plugin ${PLUGIN_NAME} is loaded`);
regCustomPanel({
position: 'groupdetail',
name: 'com.msgbyte.integration/groupdetail',
icon: '',
label: Translate.groupdetail,
render: Loadable(() => import('./IntegrationPanel')),
});

View File

@@ -0,0 +1,36 @@
import { localTrans } from '@capital/common';
export const Translate = {
groupdetail: localTrans({
'zh-CN': '集成',
'en-US': 'Integration',
}),
notFoundApp: localTrans({
'zh-CN': '没找到该应用',
'en-US': 'Not found application',
}),
onlyAllowManualAddition: localTrans({
'zh-CN': '目前仅支持通过应用ID手动添加',
'en-US': 'Currently only supports manual addition via app ID',
}),
appId: localTrans({
'zh-CN': '应用ID',
'en-US': 'Application ID',
}),
search: localTrans({
'zh-CN': '查询',
'en-US': 'Search',
}),
developer: localTrans({
'zh-CN': '开发者',
'en-US': 'Developer',
}),
addBot: localTrans({
'zh-CN': '添加应用机器人到群组',
'en-US': 'Add app bot to group',
}),
cannotAddBot: localTrans({
'zh-CN': '该应用机器人没有开放聊天功能',
'en-US': 'This application does not enable chat feature',
}),
};

View File

@@ -0,0 +1,11 @@
export type OpenAppCapability = 'bot' | 'webpage' | 'oauth';
export interface OpenAppInfo {
_id: string;
owner: string;
appId: string;
appName: string;
appDesc: string;
appIcon: string;
capability: OpenAppCapability[];
}

View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"esModuleInterop": true,
"jsx": "react",
"importsNotUsedAsValues": "error",
"paths": {
"@capital/*": ["../../src/plugin/*"],
}
}
}