@zhin.js/adapter-wecom 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +624 -0
- package/README.md +80 -216
- package/adapters/wecom.js +34 -0
- package/adapters/wecom.ts +39 -0
- package/{skills/wecom → agent}/PERMITS.md +1 -1
- package/agent/tools/get_dept_users.ts +16 -0
- package/agent/tools/get_user.ts +15 -0
- package/agent/tools/list_departments.ts +16 -0
- package/agent/tools/send_text.ts +17 -0
- package/commands/endpoint/add/[id].js +3 -0
- package/commands/endpoint/add/[id].ts +3 -0
- package/commands/endpoint/list.js +3 -0
- package/commands/endpoint/list.ts +3 -0
- package/commands/endpoint/remove/[id].js +3 -0
- package/commands/endpoint/remove/[id].ts +3 -0
- package/lib/client.d.ts +12 -0
- package/lib/client.js +2 -0
- package/lib/endpoint.d.ts +55 -37
- package/lib/endpoint.js +247 -516
- package/lib/index.d.ts +6 -15
- package/lib/index.js +6 -115
- package/lib/media-upload.d.ts +23 -0
- package/lib/media-upload.js +58 -0
- package/lib/platform-permit.d.ts +2 -4
- package/lib/platform-permit.js +5 -11
- package/lib/protocol.d.ts +102 -0
- package/lib/protocol.js +268 -0
- package/lib/side-event-dispatch.d.ts +4 -0
- package/lib/side-event-dispatch.js +63 -0
- package/lib/webhook.d.ts +14 -0
- package/lib/webhook.js +86 -0
- package/lib/wecom-endpoint-commands.d.ts +1 -0
- package/lib/wecom-endpoint-commands.js +19 -0
- package/lib/wecom-runtime-state.d.ts +1 -0
- package/lib/wecom-runtime-state.js +6 -0
- package/package.json +64 -16
- package/plugin.js +19 -0
- package/schema.json +96 -0
- package/src/client.ts +16 -0
- package/src/endpoint.ts +311 -559
- package/src/index.ts +52 -131
- package/src/media-upload.ts +79 -0
- package/src/platform-permit.ts +6 -11
- package/src/protocol.ts +379 -0
- package/src/side-event-dispatch.ts +70 -0
- package/src/webhook.ts +130 -0
- package/src/wecom-endpoint-commands.ts +20 -0
- package/src/wecom-runtime-state.ts +7 -0
- package/lib/adapter.d.ts +0 -15
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js +0 -20
- package/lib/adapter.js.map +0 -1
- package/lib/endpoint.d.ts.map +0 -1
- package/lib/endpoint.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/platform-permit.d.ts.map +0 -1
- package/lib/platform-permit.js.map +0 -1
- package/lib/types.d.ts +0 -48
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -5
- package/lib/types.js.map +0 -1
- package/plugin.yml +0 -3
- package/src/adapter.ts +0 -26
- package/src/types.ts +0 -51
- /package/{skills/wecom/SKILL.md → agent/skills/wecom.md} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { buildNotice, buildSystem, senderFromId } from '@zhin.js/core';
|
|
2
|
+
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
+
import { resolveChatType } from './protocol.js';
|
|
4
|
+
function mapWecomEventParts(eventName) {
|
|
5
|
+
switch (eventName) {
|
|
6
|
+
case 'subscribe':
|
|
7
|
+
return { scene_type: 'friend', sub_type: 'increase' };
|
|
8
|
+
case 'unsubscribe':
|
|
9
|
+
return { scene_type: 'friend', sub_type: 'decrease' };
|
|
10
|
+
case 'enter_agent':
|
|
11
|
+
return null;
|
|
12
|
+
default:
|
|
13
|
+
return { scene_type: 'wecom', sub_type: eventName || 'unknown' };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function receiveWecomSideEvent(emit, endpointKey, configId, msg, logger) {
|
|
17
|
+
if (msg.MsgType !== 'event')
|
|
18
|
+
return false;
|
|
19
|
+
const eventName = msg.Event ?? 'unknown';
|
|
20
|
+
if (eventName === 'enter_agent') {
|
|
21
|
+
void emit('system.receive', buildSystem(msg, {
|
|
22
|
+
$id: `wecom:enter_agent:${msg.FromUserName}:${msg.CreateTime ?? Date.now()}`,
|
|
23
|
+
$adapter: 'wecom',
|
|
24
|
+
$endpoint: configId,
|
|
25
|
+
$type: 'system',
|
|
26
|
+
$scene_id: msg.FromUserName,
|
|
27
|
+
$scene_type: 'wecom',
|
|
28
|
+
$sub_type: 'enter_agent',
|
|
29
|
+
$timestamp: msg.CreateTime ?? Date.now(),
|
|
30
|
+
})).catch((err) => {
|
|
31
|
+
logger.warn(formatCompact({
|
|
32
|
+
op: 'wecom_system_side_event_failed',
|
|
33
|
+
endpoint: configId,
|
|
34
|
+
event: eventName,
|
|
35
|
+
error: err instanceof Error ? err.message : String(err),
|
|
36
|
+
}));
|
|
37
|
+
});
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const parts = mapWecomEventParts(eventName);
|
|
41
|
+
if (!parts)
|
|
42
|
+
return false;
|
|
43
|
+
const sceneType = resolveChatType(msg.FromUserName);
|
|
44
|
+
void emit('notice.receive', buildNotice(msg, {
|
|
45
|
+
$id: `wecom:${eventName}:${msg.FromUserName}:${msg.CreateTime ?? Date.now()}`,
|
|
46
|
+
$adapter: 'wecom',
|
|
47
|
+
$endpoint: configId,
|
|
48
|
+
$type: 'notice',
|
|
49
|
+
$scene_id: msg.FromUserName,
|
|
50
|
+
$scene_type: parts.scene_type === 'friend' ? parts.scene_type : sceneType,
|
|
51
|
+
$sub_type: parts.sub_type,
|
|
52
|
+
$actor: senderFromId(msg.FromUserName),
|
|
53
|
+
$timestamp: msg.CreateTime ?? Date.now(),
|
|
54
|
+
})).catch((err) => {
|
|
55
|
+
logger.warn(formatCompact({
|
|
56
|
+
op: 'wecom_side_event_failed',
|
|
57
|
+
endpoint: configId,
|
|
58
|
+
event: eventName,
|
|
59
|
+
error: err instanceof Error ? err.message : String(err),
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
}
|
package/lib/webhook.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom webhook HTTP: URL verification (GET) + encrypted inbound (POST).
|
|
3
|
+
*/
|
|
4
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
|
+
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
6
|
+
import { type ResolvedWecomConfig, type WecomMessage } from './protocol.js';
|
|
7
|
+
export interface WecomWebhookHandler {
|
|
8
|
+
readonly config: ResolvedWecomConfig;
|
|
9
|
+
readonly isOpen: boolean;
|
|
10
|
+
admit(msg: WecomMessage): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function registerWecomWebhookRoutes(http: HttpHost, handler: WecomWebhookHandler): HttpRouteRegistration[];
|
|
13
|
+
export declare function handleWecomVerificationRequest(_request: IncomingMessage, response: ServerResponse, url: URL, handler: WecomWebhookHandler): void;
|
|
14
|
+
export declare function handleWecomWebhookRequest(request: IncomingMessage, response: ServerResponse, url: URL, handler: WecomWebhookHandler): Promise<void>;
|
package/lib/webhook.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
2
|
+
import { decryptMessage, extractEncryptFromXml, normalizeEchostrParam, parseXmlMessage, queryParam, readTextBody, verifySignature, } from './protocol.js';
|
|
3
|
+
const logger = getLogger('wecom');
|
|
4
|
+
export function registerWecomWebhookRoutes(http, handler) {
|
|
5
|
+
const path = handler.config.webhookPath;
|
|
6
|
+
return [
|
|
7
|
+
http.route('GET', path, (request, response, url) => {
|
|
8
|
+
handleWecomVerificationRequest(request, response, url, handler);
|
|
9
|
+
}, { summary: 'WeCom URL verification', tags: ['wecom'] }),
|
|
10
|
+
http.route('POST', path, async (request, response, url) => {
|
|
11
|
+
await handleWecomWebhookRequest(request, response, url, handler);
|
|
12
|
+
}, { summary: 'WeCom inbound webhook', tags: ['wecom'] }),
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
export function handleWecomVerificationRequest(_request, response, url, handler) {
|
|
16
|
+
try {
|
|
17
|
+
const msgSignature = queryParam(url.searchParams.get('msg_signature'));
|
|
18
|
+
const timestamp = queryParam(url.searchParams.get('timestamp'));
|
|
19
|
+
const nonce = queryParam(url.searchParams.get('nonce'));
|
|
20
|
+
const echostr = normalizeEchostrParam(queryParam(url.searchParams.get('echostr')));
|
|
21
|
+
const { token, encodingAESKey, corpId } = handler.config;
|
|
22
|
+
if (!msgSignature || !timestamp || !nonce || !echostr) {
|
|
23
|
+
response.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
24
|
+
response.end('Missing required query parameters');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!verifySignature(token, timestamp, nonce, echostr, msgSignature)) {
|
|
28
|
+
logger.warn(formatCompact({ op: 'verify', ok: false, error: 'invalid signature' }));
|
|
29
|
+
response.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
30
|
+
response.end('Forbidden');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const decrypted = decryptMessage(echostr, encodingAESKey, corpId);
|
|
34
|
+
if (!decrypted) {
|
|
35
|
+
response.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
36
|
+
response.end('Decryption failed');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
40
|
+
response.end(decrypted);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
logger.error('URL verification error:', error);
|
|
44
|
+
response.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
45
|
+
response.end('Internal Server Error');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export async function handleWecomWebhookRequest(request, response, url, handler) {
|
|
49
|
+
try {
|
|
50
|
+
const msgSignature = queryParam(url.searchParams.get('msg_signature'));
|
|
51
|
+
const timestamp = queryParam(url.searchParams.get('timestamp'));
|
|
52
|
+
const nonce = queryParam(url.searchParams.get('nonce'));
|
|
53
|
+
const { token, encodingAESKey, corpId } = handler.config;
|
|
54
|
+
const rawBody = await readTextBody(request);
|
|
55
|
+
const encrypted = extractEncryptFromXml(rawBody);
|
|
56
|
+
if (!encrypted) {
|
|
57
|
+
logger.warn(formatCompact({ op: 'webhook', ok: false, error: 'no Encrypt field' }));
|
|
58
|
+
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
59
|
+
response.end('success');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!verifySignature(token, timestamp, nonce, encrypted, msgSignature)) {
|
|
63
|
+
logger.warn(formatCompact({ op: 'webhook', ok: false, error: 'invalid signature' }));
|
|
64
|
+
response.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
65
|
+
response.end('Forbidden');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const decryptedXml = decryptMessage(encrypted, encodingAESKey, corpId);
|
|
69
|
+
if (!decryptedXml) {
|
|
70
|
+
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
71
|
+
response.end('success');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const message = parseXmlMessage(decryptedXml);
|
|
75
|
+
if (message && handler.isOpen) {
|
|
76
|
+
handler.admit(message);
|
|
77
|
+
}
|
|
78
|
+
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
79
|
+
response.end('success');
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
logger.error('Webhook error:', error);
|
|
83
|
+
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
84
|
+
response.end('success');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const wecomEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `wecom.endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
3
|
+
* commands/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
|
+
*/
|
|
5
|
+
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
|
+
import { defineCommand } from 'zhin.js/command';
|
|
7
|
+
import { wecomRuntimeStateToken } from './wecom-runtime-state.js';
|
|
8
|
+
export const wecomEndpointCommands = createEndpointCommands({
|
|
9
|
+
adapterKey: 'wecom',
|
|
10
|
+
adapterDisplayName: 'WeCom',
|
|
11
|
+
fields: [
|
|
12
|
+
{ key: 'corpId', required: true, env: true, description: '企业 corpId' },
|
|
13
|
+
{ key: 'agentSecret', required: true, env: true, description: '应用 secret' },
|
|
14
|
+
{ key: 'token', required: true, env: true, description: '回调 token' },
|
|
15
|
+
{ key: 'encodingAESKey', required: true, env: true, description: '回调加解密 key' },
|
|
16
|
+
],
|
|
17
|
+
running: (use) => use(wecomRuntimeStateToken).endpoints.values(),
|
|
18
|
+
describeEntry: (entry) => `corpId: ${String(entry.corpId)}`,
|
|
19
|
+
}, defineCommand);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const wecomRuntimeStateToken: import("zhin.js").Token<import("@zhin.js/adapter").EndpointRuntimeState>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
+
* 由 plugin.ts setup() provide,adapter create 与 `wecom.endpoint` 命令共享(同一 owner generation)。
|
|
4
|
+
*/
|
|
5
|
+
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
|
+
export const wecomRuntimeStateToken = defineEndpointRuntimeStateToken('wecom');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-wecom",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Zhin.js adapter for
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Zhin.js WeCom (企业微信) adapter for Plugin Runtime (HTTP webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
@@ -33,27 +33,54 @@
|
|
|
33
33
|
"type": "git",
|
|
34
34
|
"directory": "plugins/adapters/wecom"
|
|
35
35
|
},
|
|
36
|
-
"
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"
|
|
40
|
-
"@zhin.js/host-
|
|
41
|
-
"zhin.js": "
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@zhin.js/adapter": "1.1.12",
|
|
38
|
+
"@zhin.js/core": "1.1.35",
|
|
39
|
+
"@zhin.js/feature-kit": "1.1.0",
|
|
40
|
+
"@zhin.js/host-http": "1.1.0",
|
|
41
|
+
"@zhin.js/im-contract": "1.1.0",
|
|
42
|
+
"@zhin.js/logger": "1.1.0"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
|
-
"
|
|
45
|
-
"zhin.js": "
|
|
45
|
+
"zod": "^4.0.0",
|
|
46
|
+
"@zhin.js/adapter": "^1.1.12",
|
|
47
|
+
"@zhin.js/agent": "^1.1.23",
|
|
48
|
+
"@zhin.js/command": "^1.1.0",
|
|
49
|
+
"@zhin.js/core": "^1.1.35",
|
|
50
|
+
"@zhin.js/host-http": "^1.1.0",
|
|
51
|
+
"@zhin.js/permission": "^1.1.0",
|
|
52
|
+
"zhin.js": "^1.1.0"
|
|
46
53
|
},
|
|
47
54
|
"peerDependenciesMeta": {
|
|
48
|
-
"@zhin.js/
|
|
49
|
-
"optional":
|
|
55
|
+
"@zhin.js/agent": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"@zhin.js/command": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"zhin.js": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"zod": {
|
|
65
|
+
"optional": true
|
|
50
66
|
}
|
|
51
67
|
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/node": "^26.1.2",
|
|
70
|
+
"typescript": "^6.0.3",
|
|
71
|
+
"vitest": "^4.1.10",
|
|
72
|
+
"zod": "^4.4.3",
|
|
73
|
+
"@zhin.js/agent": "1.1.23",
|
|
74
|
+
"zhin.js": "1.1.0"
|
|
75
|
+
},
|
|
52
76
|
"files": [
|
|
77
|
+
"adapters",
|
|
78
|
+
"commands",
|
|
79
|
+
"plugin.js",
|
|
80
|
+
"schema.json",
|
|
53
81
|
"src",
|
|
54
82
|
"lib",
|
|
55
|
-
"
|
|
56
|
-
"plugin.yml",
|
|
83
|
+
"agent",
|
|
57
84
|
"README.md",
|
|
58
85
|
"CHANGELOG.md"
|
|
59
86
|
],
|
|
@@ -61,9 +88,30 @@
|
|
|
61
88
|
"access": "public",
|
|
62
89
|
"registry": "https://registry.npmjs.org"
|
|
63
90
|
},
|
|
91
|
+
"engines": {
|
|
92
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
93
|
+
},
|
|
94
|
+
"zhin": {
|
|
95
|
+
"protocol": 1,
|
|
96
|
+
"type": "plugin",
|
|
97
|
+
"entry": "./plugin.js",
|
|
98
|
+
"engine": "^1.0.0",
|
|
99
|
+
"runtime": "trusted",
|
|
100
|
+
"features": [
|
|
101
|
+
{
|
|
102
|
+
"package": "@zhin.js/adapter",
|
|
103
|
+
"api": "^1.0.0"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"package": "@zhin.js/command",
|
|
107
|
+
"api": "^1.0.0"
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"plugins": []
|
|
111
|
+
},
|
|
64
112
|
"scripts": {
|
|
65
|
-
"build": "
|
|
113
|
+
"build": "tsc",
|
|
66
114
|
"clean": "rimraf lib",
|
|
67
|
-
"
|
|
115
|
+
"test": "NODE_OPTIONS=--experimental-strip-types vitest run --root ../../.. plugins/adapters/wecom/tests"
|
|
68
116
|
}
|
|
69
117
|
}
|
package/plugin.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { createEndpointRuntimeState } from 'zhin.js/adapter';
|
|
3
|
+
import { definePlugin } from 'zhin.js';
|
|
4
|
+
import { permissionHostToken } from '@zhin.js/permission';
|
|
5
|
+
import { checkWecomPlatformPermit } from "./lib/platform-permit.js";
|
|
6
|
+
import { wecomRuntimeStateToken } from "./lib/wecom-runtime-state.js";
|
|
7
|
+
export default definePlugin({
|
|
8
|
+
name: 'wecom',
|
|
9
|
+
metadata: {
|
|
10
|
+
displayName: 'WeCom (企业微信) Adapter',
|
|
11
|
+
},
|
|
12
|
+
setup(context) {
|
|
13
|
+
context.resources.provide(wecomRuntimeStateToken, createEndpointRuntimeState());
|
|
14
|
+
if (context.resources.has(permissionHostToken)) {
|
|
15
|
+
const host = context.resources.use(permissionHostToken);
|
|
16
|
+
return host.registerPlatform('wecom', checkWecomPlatformPermit);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
});
|
package/schema.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"properties": {
|
|
6
|
+
"webhookPath": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"default": "/wecom/callback"
|
|
9
|
+
},
|
|
10
|
+
"apiBaseUrl": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"default": "https://qyapi.weixin.qq.com"
|
|
13
|
+
},
|
|
14
|
+
"master": {
|
|
15
|
+
"type": [
|
|
16
|
+
"string",
|
|
17
|
+
"number"
|
|
18
|
+
],
|
|
19
|
+
"description": "框架 master(WeCom userid;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
20
|
+
},
|
|
21
|
+
"trusted": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"items": {
|
|
24
|
+
"type": [
|
|
25
|
+
"string",
|
|
26
|
+
"number"
|
|
27
|
+
],
|
|
28
|
+
"description": "Trusted WeCom userid"
|
|
29
|
+
},
|
|
30
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
31
|
+
},
|
|
32
|
+
"endpoints": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
35
|
+
"items": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"additionalProperties": true,
|
|
38
|
+
"properties": {
|
|
39
|
+
"master": {
|
|
40
|
+
"type": [
|
|
41
|
+
"string",
|
|
42
|
+
"number"
|
|
43
|
+
],
|
|
44
|
+
"description": "本 endpoint 的框架 master(WeCom userid);覆盖顶层 master"
|
|
45
|
+
},
|
|
46
|
+
"trusted": {
|
|
47
|
+
"type": "array",
|
|
48
|
+
"items": {
|
|
49
|
+
"type": [
|
|
50
|
+
"string",
|
|
51
|
+
"number"
|
|
52
|
+
],
|
|
53
|
+
"description": "Trusted WeCom userid"
|
|
54
|
+
},
|
|
55
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
56
|
+
},
|
|
57
|
+
"corpId": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "WeCom corp ID"
|
|
60
|
+
},
|
|
61
|
+
"agentSecret": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "WeCom agent secret"
|
|
64
|
+
},
|
|
65
|
+
"token": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "WeCom callback token"
|
|
68
|
+
},
|
|
69
|
+
"encodingAESKey": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"description": "WeCom encoding AES key"
|
|
72
|
+
},
|
|
73
|
+
"id": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "WeCom bot name"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"required": [
|
|
79
|
+
"id",
|
|
80
|
+
"corpId",
|
|
81
|
+
"agentSecret",
|
|
82
|
+
"token",
|
|
83
|
+
"encodingAESKey"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"commandPrefix": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"default": "",
|
|
90
|
+
"description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"required": [
|
|
94
|
+
"endpoints"
|
|
95
|
+
]
|
|
96
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineEndpointClient } from 'zhin.js/adapter';
|
|
2
|
+
import type { WecomClient } from './endpoint.js';
|
|
3
|
+
import type { WecomMessage } from './protocol.js';
|
|
4
|
+
|
|
5
|
+
export type WecomClientEventMap = Record<string, WecomMessage>;
|
|
6
|
+
|
|
7
|
+
declare module '@zhin.js/feature-kit' {
|
|
8
|
+
interface AdapterClientRegistry {
|
|
9
|
+
readonly wecom: {
|
|
10
|
+
readonly client: WecomClient;
|
|
11
|
+
readonly events: WecomClientEventMap;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const wecomClient = defineEndpointClient<WecomClient, WecomClientEventMap>('wecom');
|