@zhin.js/adapter-telegram 7.0.3 → 7.0.5
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 +79 -0
- package/adapters/telegram.js +2 -2
- package/adapters/telegram.ts +2 -2
- package/lib/endpoint.js +26 -23
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/platform-permit.d.ts +2 -3
- package/lib/platform-permit.js +3 -13
- package/lib/protocol.d.ts +3 -3
- package/lib/protocol.js +5 -5
- package/lib/telegram-agent-deps.d.ts +2 -2
- package/lib/telegram-agent-deps.js +7 -7
- package/package.json +17 -16
- package/plugin.js +6 -4
- package/schema.json +41 -5
- package/src/endpoint.ts +27 -24
- package/src/index.ts +0 -1
- package/src/platform-permit.ts +4 -11
- package/src/protocol.ts +7 -7
- package/src/telegram-agent-deps.ts +8 -8
- /package/commands/endpoint/add/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/add/{[name].ts → [id].ts} +0 -0
- /package/commands/endpoint/remove/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name].ts → [id].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 7.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
|
|
8
|
+
|
|
9
|
+
All adapter platform-permit checkers now accept PermissionSubject
|
|
10
|
+
(duck-typed from Message/CommandSession) instead of Message directly.
|
|
11
|
+
registerPlatformPermitChecker is replaced by host.registerPlatform in
|
|
12
|
+
the adapter plugin setup. activity-feedback service updated for new
|
|
13
|
+
PermissionHost integration.
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [6f9c366]
|
|
16
|
+
- Updated dependencies [373a56b]
|
|
17
|
+
- Updated dependencies [0de46a8]
|
|
18
|
+
- Updated dependencies [c106ecc]
|
|
19
|
+
- Updated dependencies [ca92e03]
|
|
20
|
+
- Updated dependencies [b0f37ae]
|
|
21
|
+
- Updated dependencies [ba08a2f]
|
|
22
|
+
- Updated dependencies [b08f7fe]
|
|
23
|
+
- Updated dependencies [daffd4c]
|
|
24
|
+
- Updated dependencies [36c7400]
|
|
25
|
+
- Updated dependencies [a9fa72e]
|
|
26
|
+
- Updated dependencies [c8de3ef]
|
|
27
|
+
- Updated dependencies [60f0fc8]
|
|
28
|
+
- Updated dependencies [574c990]
|
|
29
|
+
- Updated dependencies [d096f16]
|
|
30
|
+
- Updated dependencies [3f29623]
|
|
31
|
+
- Updated dependencies [2916852]
|
|
32
|
+
- Updated dependencies [d047869]
|
|
33
|
+
- Updated dependencies [162fa34]
|
|
34
|
+
- Updated dependencies [e62561e]
|
|
35
|
+
- Updated dependencies [3eeeb46]
|
|
36
|
+
- Updated dependencies [85d0f82]
|
|
37
|
+
- Updated dependencies [61bfc1c]
|
|
38
|
+
- Updated dependencies [04bad47]
|
|
39
|
+
- Updated dependencies [e40b048]
|
|
40
|
+
- Updated dependencies [5a5b1bb]
|
|
41
|
+
- Updated dependencies [f1708c3]
|
|
42
|
+
- Updated dependencies [d254a81]
|
|
43
|
+
- Updated dependencies [7123c47]
|
|
44
|
+
- Updated dependencies [05befc1]
|
|
45
|
+
- Updated dependencies [0663b6a]
|
|
46
|
+
- Updated dependencies [f28f9b3]
|
|
47
|
+
- Updated dependencies [9f340f7]
|
|
48
|
+
- Updated dependencies [e53444f]
|
|
49
|
+
- Updated dependencies [5eedd26]
|
|
50
|
+
- Updated dependencies [92b0dd7]
|
|
51
|
+
- Updated dependencies [f919b6f]
|
|
52
|
+
- Updated dependencies [098e411]
|
|
53
|
+
- Updated dependencies [e1b7c01]
|
|
54
|
+
- Updated dependencies [9b94f87]
|
|
55
|
+
- Updated dependencies [a7df753]
|
|
56
|
+
- @zhin.js/agent@1.1.5
|
|
57
|
+
- @zhin.js/host-http@1.0.8
|
|
58
|
+
- @zhin.js/permission@1.0.1
|
|
59
|
+
- @zhin.js/im-contract@1.0.3
|
|
60
|
+
- @zhin.js/adapter@1.1.7
|
|
61
|
+
- @zhin.js/plugin-runtime@1.1.5
|
|
62
|
+
- @zhin.js/command@1.0.9
|
|
63
|
+
- @zhin.js/core@1.5.4
|
|
64
|
+
- zhin.js@6.0.4
|
|
65
|
+
|
|
66
|
+
## 7.0.4
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- f8c7a54: fix: im
|
|
71
|
+
- Updated dependencies [f8c7a54]
|
|
72
|
+
- @zhin.js/logger@1.0.76
|
|
73
|
+
- @zhin.js/host-http@1.0.7
|
|
74
|
+
- @zhin.js/adapter@1.1.6
|
|
75
|
+
- @zhin.js/agent@1.1.4
|
|
76
|
+
- @zhin.js/command@1.0.8
|
|
77
|
+
- @zhin.js/core@1.5.3
|
|
78
|
+
- @zhin.js/im-contract@1.0.2
|
|
79
|
+
- @zhin.js/plugin-runtime@1.1.4
|
|
80
|
+
- zhin.js@6.0.3
|
|
81
|
+
|
|
3
82
|
## 7.0.3
|
|
4
83
|
|
|
5
84
|
### Patch Changes
|
package/adapters/telegram.js
CHANGED
|
@@ -21,8 +21,8 @@ export default defineAdapter({
|
|
|
21
21
|
create(context) {
|
|
22
22
|
const config = resolveTelegramConfig(context.config);
|
|
23
23
|
// 注册到插件运行时状态(telegram.endpoint list 的"运行中"数据源)
|
|
24
|
-
context.use(telegramRuntimeStateToken).endpoints.set(config.
|
|
25
|
-
|
|
24
|
+
context.use(telegramRuntimeStateToken).endpoints.set(config.id, {
|
|
25
|
+
id: config.id,
|
|
26
26
|
mode: config.mode,
|
|
27
27
|
});
|
|
28
28
|
return new TelegramEndpoint({
|
package/adapters/telegram.ts
CHANGED
|
@@ -26,8 +26,8 @@ export default defineAdapter<TelegramAdapterConfig>({
|
|
|
26
26
|
create(context) {
|
|
27
27
|
const config = resolveTelegramConfig(context.config);
|
|
28
28
|
// 注册到插件运行时状态(telegram.endpoint list 的"运行中"数据源)
|
|
29
|
-
context.use(telegramRuntimeStateToken).endpoints.set(config.
|
|
30
|
-
|
|
29
|
+
context.use(telegramRuntimeStateToken).endpoints.set(config.id, {
|
|
30
|
+
id: config.id,
|
|
31
31
|
mode: config.mode,
|
|
32
32
|
});
|
|
33
33
|
return new TelegramEndpoint({
|
package/lib/endpoint.js
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { readFile } from 'node:fs/promises';
|
|
5
5
|
import { formatLegacyMessageRef, nativeConversationId, parseLegacyMessageReference, } from '@zhin.js/im-contract';
|
|
6
|
-
import { formatCompact,
|
|
6
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
7
7
|
import { runTelegramPollLoop } from './polling.js';
|
|
8
8
|
import { normalizeTelegramChatMember } from './platform-permit.js';
|
|
9
9
|
import { botApiUrl, buildWebhookUrl, formatCallbackContent, formatCallbackSegments, formatInboundContent, formatInboundSegments, formatOutboundPlan, resolveTelegramChannelType, senderDisplayName, telegramInboundConversation, } from './protocol.js';
|
|
10
10
|
import { registerTelegramAgentEndpoint } from './telegram-agent-deps.js';
|
|
11
11
|
import { registerTelegramWebhookRoutes } from './webhook.js';
|
|
12
|
-
const logger = getLogger('telegram');
|
|
13
12
|
const CHAT_MEMBER_CACHE_TTL_MS = 60_000;
|
|
14
13
|
const CHAT_MEMBER_CACHE_MAX = 2_000;
|
|
15
14
|
/**
|
|
@@ -18,6 +17,7 @@ const CHAT_MEMBER_CACHE_MAX = 2_000;
|
|
|
18
17
|
* 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
|
|
19
18
|
*/
|
|
20
19
|
export class TelegramEndpoint {
|
|
20
|
+
#logger;
|
|
21
21
|
#options;
|
|
22
22
|
#fetch;
|
|
23
23
|
#pollAbort;
|
|
@@ -34,6 +34,7 @@ export class TelegramEndpoint {
|
|
|
34
34
|
recall: (messageId) => this.recallMessage(messageId),
|
|
35
35
|
});
|
|
36
36
|
constructor(options) {
|
|
37
|
+
this.#logger = getAdapterLogger('telegram', options.config.id);
|
|
37
38
|
this.#options = options;
|
|
38
39
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
39
40
|
}
|
|
@@ -58,7 +59,7 @@ export class TelegramEndpoint {
|
|
|
58
59
|
return;
|
|
59
60
|
this.#started = true;
|
|
60
61
|
try {
|
|
61
|
-
this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.
|
|
62
|
+
this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.id, this);
|
|
62
63
|
const me = await this.callApi('getMe');
|
|
63
64
|
this.#botUserId = me.id;
|
|
64
65
|
this.#botUsername = me.username;
|
|
@@ -70,9 +71,9 @@ export class TelegramEndpoint {
|
|
|
70
71
|
const webhook = this.#options.config.webhook;
|
|
71
72
|
if (!webhook.secretToken) {
|
|
72
73
|
// 未配 secretToken 时 webhook 无鉴权:任何人知道 path 即可注入假 update。
|
|
73
|
-
logger.warn(formatCompact({
|
|
74
|
+
this.#logger.warn(formatCompact({
|
|
74
75
|
op: 'webhook_no_secret',
|
|
75
|
-
endpoint: this.#options.config.
|
|
76
|
+
endpoint: this.#options.config.id,
|
|
76
77
|
path: webhook.path,
|
|
77
78
|
hint: 'set webhook.secretToken to authenticate Telegram callbacks',
|
|
78
79
|
}));
|
|
@@ -83,9 +84,9 @@ export class TelegramEndpoint {
|
|
|
83
84
|
allowed_updates: this.#options.config.allowedUpdates,
|
|
84
85
|
...(webhook.secretToken ? { secret_token: webhook.secretToken } : {}),
|
|
85
86
|
});
|
|
86
|
-
logger.info(formatCompact({
|
|
87
|
+
this.#logger.info(formatCompact({
|
|
87
88
|
op: 'connect',
|
|
88
|
-
endpoint: this.#options.config.
|
|
89
|
+
endpoint: this.#options.config.id,
|
|
89
90
|
mode: 'webhook',
|
|
90
91
|
path: webhook.path,
|
|
91
92
|
username: me.username,
|
|
@@ -95,16 +96,16 @@ export class TelegramEndpoint {
|
|
|
95
96
|
await this.callApi('deleteWebhook', { drop_pending_updates: false });
|
|
96
97
|
this.#pollAbort = new AbortController();
|
|
97
98
|
this.#pollPromise = runTelegramPollLoop(this, this.#pollAbort.signal);
|
|
98
|
-
logger.info(formatCompact({
|
|
99
|
+
this.#logger.info(formatCompact({
|
|
99
100
|
op: 'connect',
|
|
100
|
-
endpoint: this.#options.config.
|
|
101
|
+
endpoint: this.#options.config.id,
|
|
101
102
|
mode: 'polling',
|
|
102
103
|
username: me.username,
|
|
103
104
|
}));
|
|
104
105
|
}
|
|
105
106
|
catch (error) {
|
|
106
107
|
await this.stop();
|
|
107
|
-
logger.error('Failed to connect Telegram bot:', error);
|
|
108
|
+
this.#logger.error('Failed to connect Telegram bot:', error);
|
|
108
109
|
throw error;
|
|
109
110
|
}
|
|
110
111
|
}
|
|
@@ -129,7 +130,7 @@ export class TelegramEndpoint {
|
|
|
129
130
|
this.#unregisterAgent = undefined;
|
|
130
131
|
this.#chatMemberCache.clear();
|
|
131
132
|
this.#started = false;
|
|
132
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
133
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
133
134
|
}
|
|
134
135
|
async send({ conversation, payload }) {
|
|
135
136
|
const plan = formatOutboundPlan(conversation.id, payload);
|
|
@@ -189,7 +190,7 @@ export class TelegramEndpoint {
|
|
|
189
190
|
return;
|
|
190
191
|
const conversation = telegramInboundConversation(String(this.#options.id), msg.chat);
|
|
191
192
|
void this.#admitWithSenderRole(msg, conversation).catch((err) => {
|
|
192
|
-
logger.warn(formatCompact({
|
|
193
|
+
this.#logger.warn(formatCompact({
|
|
193
194
|
op: 'telegram_gateway_receive_failed',
|
|
194
195
|
target: `${conversation.kind}:${conversation.id}`,
|
|
195
196
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -205,18 +206,20 @@ export class TelegramEndpoint {
|
|
|
205
206
|
message: { conversation, id: String(msg.message_id) },
|
|
206
207
|
content: formatInboundContent(msg),
|
|
207
208
|
segments: formatInboundSegments(msg),
|
|
208
|
-
sender:
|
|
209
|
+
sender: {
|
|
210
|
+
id: String(msg.from?.id ?? ''),
|
|
211
|
+
name: senderDisplayName(msg.from) || undefined,
|
|
212
|
+
...(permit?.role ? { roles: [permit.role] } : {}),
|
|
213
|
+
},
|
|
214
|
+
endpointId: this.#options.config.id,
|
|
215
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
209
216
|
metadata: Object.freeze({
|
|
210
|
-
endpoint: this.#options.config.name,
|
|
211
|
-
// Preserve Telegram's native value below, but publish the canonical
|
|
212
|
-
// scene kind so every Runtime consumer sees the same conversation type.
|
|
213
217
|
channelType: resolveTelegramChannelType(msg.chat.type),
|
|
214
218
|
chatType: msg.chat.type,
|
|
215
219
|
userId: msg.from?.id,
|
|
216
220
|
date: msg.date,
|
|
217
221
|
...(permit?.role ? { senderRole: permit.role } : {}),
|
|
218
222
|
...(permit?.permissions.length ? { senderPermissions: [...permit.permissions] } : {}),
|
|
219
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
220
223
|
}),
|
|
221
224
|
});
|
|
222
225
|
}
|
|
@@ -285,26 +288,26 @@ export class TelegramEndpoint {
|
|
|
285
288
|
admitCallback(query) {
|
|
286
289
|
if (!this.#open)
|
|
287
290
|
return;
|
|
288
|
-
const
|
|
291
|
+
const endpointKey = String(this.#options.id);
|
|
289
292
|
const msg = query.message;
|
|
290
293
|
// 无挂载消息的 callback(如 inline 模式)退化为 sender 私聊会话
|
|
291
294
|
const conversation = msg
|
|
292
|
-
? telegramInboundConversation(
|
|
293
|
-
: telegramInboundConversation(
|
|
295
|
+
? telegramInboundConversation(endpointKey, msg.chat)
|
|
296
|
+
: telegramInboundConversation(endpointKey, { id: query.from.id, type: 'private' });
|
|
294
297
|
void this.#options.gateway.receive({
|
|
295
298
|
conversation,
|
|
296
299
|
message: { conversation, id: query.id },
|
|
297
300
|
content: formatCallbackContent(query),
|
|
298
301
|
segments: formatCallbackSegments(query),
|
|
299
|
-
sender: senderDisplayName(query.from),
|
|
302
|
+
sender: { id: String(query.from?.id ?? ''), name: senderDisplayName(query.from) || undefined },
|
|
303
|
+
endpointId: this.#options.config.id,
|
|
300
304
|
metadata: Object.freeze({
|
|
301
|
-
endpoint: this.#options.config.name,
|
|
302
305
|
eventType: 'callback_query',
|
|
303
306
|
payload: query.data,
|
|
304
307
|
sourceMessageId: msg ? String(msg.message_id) : undefined,
|
|
305
308
|
}),
|
|
306
309
|
}).catch((err) => {
|
|
307
|
-
logger.warn(formatCompact({
|
|
310
|
+
this.#logger.warn(formatCompact({
|
|
308
311
|
op: 'telegram_gateway_receive_failed',
|
|
309
312
|
target: `${conversation.kind}:${conversation.id}`,
|
|
310
313
|
error: err instanceof Error ? err.message : String(err),
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { TelegramEndpoint, type TelegramEndpointOptions, type TelegramFetch, } from './endpoint.js';
|
|
2
2
|
export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath, resolveTelegramConfig, senderDisplayName, type ResolvedTelegramConfig, type TelegramAdapterConfig, type TelegramCallbackQuery, type TelegramChat, type TelegramChatMember, type TelegramMessage, type TelegramOutboundAction, type TelegramOutboundPlan, type TelegramOutboundUpload, type TelegramUpdate, type TelegramUser, type TelegramWireSegment, } from './protocol.js';
|
|
3
3
|
export { getTelegramAgentDeps, registerTelegramAgentEndpoint, setTelegramAgentDeps, type TelegramAgentDeps, type TelegramAgentEndpoint, } from './telegram-agent-deps.js';
|
|
4
|
-
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit,
|
|
4
|
+
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, telegramGroupPermitResolver, } from './platform-permit.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { TelegramEndpoint, } from './endpoint.js';
|
|
2
2
|
export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath, resolveTelegramConfig, senderDisplayName, } from './protocol.js';
|
|
3
3
|
export { getTelegramAgentDeps, registerTelegramAgentEndpoint, setTelegramAgentDeps, } from './telegram-agent-deps.js';
|
|
4
|
-
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit,
|
|
4
|
+
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, telegramGroupPermitResolver, } from './platform-permit.js';
|
package/lib/platform-permit.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Telegram platform permit — ChatMember 状态 + 细粒度权限
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
5
|
export declare function platformPermit(perm: string): string;
|
|
6
6
|
export declare function telegramGroupPermitResolver(logicalPerm: string): string;
|
|
7
7
|
export declare function normalizeTelegramChatMember(member: {
|
|
@@ -14,5 +14,4 @@ export declare function normalizeTelegramChatMember(member: {
|
|
|
14
14
|
role?: string;
|
|
15
15
|
permissions: string[];
|
|
16
16
|
};
|
|
17
|
-
export declare function checkTelegramPlatformPermit(perm: string,
|
|
18
|
-
export declare function registerTelegramPlatformPermitChecker(): () => void;
|
|
17
|
+
export declare function checkTelegramPlatformPermit(perm: string, subject: PermissionSubject): boolean;
|
package/lib/platform-permit.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Telegram platform permit — ChatMember 状态 + 细粒度权限
|
|
3
|
-
*/
|
|
4
|
-
import { registerPlatformPermitChecker } from '@zhin.js/core';
|
|
5
1
|
const ADAPTER = 'telegram';
|
|
6
2
|
export function platformPermit(perm) {
|
|
7
3
|
return `platform(${ADAPTER},${perm})`;
|
|
@@ -34,12 +30,9 @@ export function normalizeTelegramChatMember(member) {
|
|
|
34
30
|
}
|
|
35
31
|
return { role: 'member', permissions };
|
|
36
32
|
}
|
|
37
|
-
function
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
export function checkTelegramPlatformPermit(perm, message) {
|
|
42
|
-
const { role, permissions } = senderPermits(message);
|
|
33
|
+
export function checkTelegramPlatformPermit(perm, subject) {
|
|
34
|
+
const role = subject.sender?.role?.[0];
|
|
35
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
43
36
|
const has = (t) => permissions.includes(t);
|
|
44
37
|
switch (perm) {
|
|
45
38
|
case 'chat_creator':
|
|
@@ -56,6 +49,3 @@ export function checkTelegramPlatformPermit(perm, message) {
|
|
|
56
49
|
return false;
|
|
57
50
|
}
|
|
58
51
|
}
|
|
59
|
-
export function registerTelegramPlatformPermitChecker() {
|
|
60
|
-
return registerPlatformPermitChecker(ADAPTER, checkTelegramPlatformPermit);
|
|
61
|
-
}
|
package/lib/protocol.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Segment } from '@zhin.js/core/runtime';
|
|
|
7
7
|
import type { ConversationKind, ConversationRef } from '@zhin.js/im-contract';
|
|
8
8
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
9
9
|
export interface TelegramAdapterConfig {
|
|
10
|
-
readonly
|
|
10
|
+
readonly id?: string;
|
|
11
11
|
readonly token?: string;
|
|
12
12
|
/** Default true. `false` selects webhook mode (requires httpHostToken). */
|
|
13
13
|
readonly polling?: boolean;
|
|
@@ -29,7 +29,7 @@ export interface TelegramAdapterConfig {
|
|
|
29
29
|
}
|
|
30
30
|
export interface ResolvedTelegramConfig {
|
|
31
31
|
readonly context: 'telegram';
|
|
32
|
-
readonly
|
|
32
|
+
readonly id: string;
|
|
33
33
|
readonly token: string;
|
|
34
34
|
readonly mode: 'polling' | 'webhook';
|
|
35
35
|
readonly allowedUpdates: readonly string[];
|
|
@@ -243,7 +243,7 @@ export declare function resolveTelegramChannelType(chatType: TelegramChat['type'
|
|
|
243
243
|
* 入站归一化 → ConversationRef:Telegram 无 guild/群组容器层级,
|
|
244
244
|
* kind 直取 chat.type(private/group/supergroup/channel),无 parent。
|
|
245
245
|
*/
|
|
246
|
-
export declare function telegramInboundConversation(
|
|
246
|
+
export declare function telegramInboundConversation(endpointKey: string, chat: Pick<TelegramChat, 'id' | 'type'>): ConversationRef;
|
|
247
247
|
export declare function senderDisplayName(user?: TelegramUser): string;
|
|
248
248
|
/** Build inbound text for MessageGateway.receive. */
|
|
249
249
|
export declare function formatInboundContent(msg: TelegramMessage): string;
|
package/lib/protocol.js
CHANGED
|
@@ -14,8 +14,8 @@ export function resolveTelegramConfig(config = {}) {
|
|
|
14
14
|
if (!token) {
|
|
15
15
|
throw new TypeError('Telegram adapter requires token (plugins.<key>.token or endpoints with context: telegram)');
|
|
16
16
|
}
|
|
17
|
-
const
|
|
18
|
-
|| (typeof entry?.
|
|
17
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
18
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
19
19
|
|| process.env.TELEGRAM_BOT_NAME
|
|
20
20
|
|| 'telegram-bot';
|
|
21
21
|
const polling = config.polling ?? entry?.polling;
|
|
@@ -39,7 +39,7 @@ export function resolveTelegramConfig(config = {}) {
|
|
|
39
39
|
: undefined;
|
|
40
40
|
return {
|
|
41
41
|
context: 'telegram',
|
|
42
|
-
|
|
42
|
+
id,
|
|
43
43
|
token,
|
|
44
44
|
mode,
|
|
45
45
|
allowedUpdates: [...allowedUpdates],
|
|
@@ -88,9 +88,9 @@ export function resolveTelegramChannelType(chatType) {
|
|
|
88
88
|
* 入站归一化 → ConversationRef:Telegram 无 guild/群组容器层级,
|
|
89
89
|
* kind 直取 chat.type(private/group/supergroup/channel),无 parent。
|
|
90
90
|
*/
|
|
91
|
-
export function telegramInboundConversation(
|
|
91
|
+
export function telegramInboundConversation(endpointKey, chat) {
|
|
92
92
|
return {
|
|
93
|
-
endpoint: { id:
|
|
93
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
94
94
|
kind: resolveTelegramChannelType(chat.type),
|
|
95
95
|
id: String(chat.id),
|
|
96
96
|
};
|
|
@@ -20,9 +20,9 @@ export interface TelegramAgentEndpoint {
|
|
|
20
20
|
}>;
|
|
21
21
|
}
|
|
22
22
|
export interface TelegramAgentDeps {
|
|
23
|
-
getEndpoint: (
|
|
23
|
+
getEndpoint: (endpointKey: string) => TelegramAgentEndpoint;
|
|
24
24
|
}
|
|
25
|
-
export declare function registerTelegramAgentEndpoint(
|
|
25
|
+
export declare function registerTelegramAgentEndpoint(endpointKey: string, endpoint: TelegramAgentEndpoint): () => void;
|
|
26
26
|
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
27
27
|
export declare function setTelegramAgentDeps(deps: TelegramAgentDeps | null): void;
|
|
28
28
|
export declare function getTelegramAgentDeps(): TelegramAgentDeps;
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const endpoints = new Map();
|
|
6
6
|
let override = null;
|
|
7
|
-
export function registerTelegramAgentEndpoint(
|
|
8
|
-
endpoints.set(
|
|
7
|
+
export function registerTelegramAgentEndpoint(endpointKey, endpoint) {
|
|
8
|
+
endpoints.set(endpointKey, endpoint);
|
|
9
9
|
return () => {
|
|
10
|
-
if (endpoints.get(
|
|
11
|
-
endpoints.delete(
|
|
10
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
+
endpoints.delete(endpointKey);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -20,10 +20,10 @@ export function getTelegramAgentDeps() {
|
|
|
20
20
|
if (override)
|
|
21
21
|
return override;
|
|
22
22
|
return {
|
|
23
|
-
getEndpoint(
|
|
24
|
-
const registered = endpoints.get(
|
|
23
|
+
getEndpoint(endpointKey) {
|
|
24
|
+
const registered = endpoints.get(endpointKey);
|
|
25
25
|
if (!registered)
|
|
26
|
-
throw new Error(`Endpoint ${
|
|
26
|
+
throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
27
27
|
return registered;
|
|
28
28
|
},
|
|
29
29
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-telegram",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.5",
|
|
4
4
|
"description": "Zhin.js Telegram Bot API adapter for Plugin Runtime (long-poll getUpdates)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -32,21 +32,22 @@
|
|
|
32
32
|
"directory": "plugins/adapters/telegram"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@zhin.js/adapter": "1.1.
|
|
36
|
-
"@zhin.js/command": "1.0.
|
|
37
|
-
"@zhin.js/core": "1.5.
|
|
38
|
-
"@zhin.js/host-http": "1.0.
|
|
39
|
-
"@zhin.js/im-contract": "1.0.
|
|
40
|
-
"@zhin.js/logger": "1.0.
|
|
41
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
35
|
+
"@zhin.js/adapter": "1.1.7",
|
|
36
|
+
"@zhin.js/command": "1.0.9",
|
|
37
|
+
"@zhin.js/core": "1.5.4",
|
|
38
|
+
"@zhin.js/host-http": "1.0.8",
|
|
39
|
+
"@zhin.js/im-contract": "1.0.3",
|
|
40
|
+
"@zhin.js/logger": "1.0.76",
|
|
41
|
+
"@zhin.js/plugin-runtime": "1.1.5"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"zod": "^4.0.0",
|
|
45
|
-
"@zhin.js/adapter": "1.1.
|
|
46
|
-
"@zhin.js/agent": "1.1.
|
|
47
|
-
"@zhin.js/core": "1.5.
|
|
48
|
-
"@zhin.js/
|
|
49
|
-
"zhin.js": "
|
|
45
|
+
"@zhin.js/adapter": "1.1.7",
|
|
46
|
+
"@zhin.js/agent": "1.1.5",
|
|
47
|
+
"@zhin.js/core": "1.5.4",
|
|
48
|
+
"@zhin.js/permission": "1.0.1",
|
|
49
|
+
"@zhin.js/plugin-runtime": "1.1.5",
|
|
50
|
+
"zhin.js": "6.0.4"
|
|
50
51
|
},
|
|
51
52
|
"peerDependenciesMeta": {
|
|
52
53
|
"zhin.js": {
|
|
@@ -64,9 +65,9 @@
|
|
|
64
65
|
"typescript": "^6.0.3",
|
|
65
66
|
"vitest": "^4.1.10",
|
|
66
67
|
"zod": "^4.4.3",
|
|
67
|
-
"@zhin.js/agent": "1.1.
|
|
68
|
-
"@zhin.js/host-http": "1.0.
|
|
69
|
-
"zhin.js": "6.0.
|
|
68
|
+
"@zhin.js/agent": "1.1.5",
|
|
69
|
+
"@zhin.js/host-http": "1.0.8",
|
|
70
|
+
"zhin.js": "6.0.4"
|
|
70
71
|
},
|
|
71
72
|
"files": [
|
|
72
73
|
"adapters",
|
package/plugin.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { createEndpointRuntimeState } from '@zhin.js/adapter';
|
|
3
3
|
import { definePlugin } from '@zhin.js/plugin-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { permissionHostToken } from '@zhin.js/permission';
|
|
5
|
+
import { checkTelegramPlatformPermit } from "./lib/platform-permit.js";
|
|
5
6
|
import { telegramRuntimeStateToken } from "./lib/telegram-runtime-state.js";
|
|
6
7
|
export default definePlugin({
|
|
7
8
|
name: 'telegram',
|
|
@@ -9,9 +10,10 @@ export default definePlugin({
|
|
|
9
10
|
displayName: 'Telegram Bot API Adapter',
|
|
10
11
|
},
|
|
11
12
|
setup(context) {
|
|
12
|
-
// 运行中 endpoint 注册表(telegram.endpoint list 的"运行中"数据源)
|
|
13
13
|
context.resources.provide(telegramRuntimeStateToken, createEndpointRuntimeState());
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (context.resources.has(permissionHostToken)) {
|
|
15
|
+
const host = context.resources.use(permissionHostToken);
|
|
16
|
+
return host.registerPlatform('telegram', checkTelegramPlatformPermit);
|
|
17
|
+
}
|
|
16
18
|
},
|
|
17
19
|
});
|
package/schema.json
CHANGED
|
@@ -40,24 +40,60 @@
|
|
|
40
40
|
"type": "string",
|
|
41
41
|
"default": "https://api.telegram.org"
|
|
42
42
|
},
|
|
43
|
+
"master": {
|
|
44
|
+
"type": [
|
|
45
|
+
"string",
|
|
46
|
+
"number"
|
|
47
|
+
],
|
|
48
|
+
"description": "框架 master(Telegram user id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
49
|
+
},
|
|
50
|
+
"trusted": {
|
|
51
|
+
"type": "array",
|
|
52
|
+
"items": {
|
|
53
|
+
"type": [
|
|
54
|
+
"string",
|
|
55
|
+
"number"
|
|
56
|
+
],
|
|
57
|
+
"description": "Trusted Telegram user id"
|
|
58
|
+
},
|
|
59
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
60
|
+
},
|
|
43
61
|
"endpoints": {
|
|
44
62
|
"type": "array",
|
|
45
|
-
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(
|
|
63
|
+
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
46
64
|
"items": {
|
|
47
65
|
"type": "object",
|
|
48
66
|
"additionalProperties": true,
|
|
49
67
|
"properties": {
|
|
50
|
-
"
|
|
51
|
-
"type":
|
|
52
|
-
|
|
68
|
+
"master": {
|
|
69
|
+
"type": [
|
|
70
|
+
"string",
|
|
71
|
+
"number"
|
|
72
|
+
],
|
|
73
|
+
"description": "本 endpoint 的框架 master(Telegram user id);覆盖顶层 master"
|
|
74
|
+
},
|
|
75
|
+
"trusted": {
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": {
|
|
78
|
+
"type": [
|
|
79
|
+
"string",
|
|
80
|
+
"number"
|
|
81
|
+
],
|
|
82
|
+
"description": "Trusted Telegram user id"
|
|
83
|
+
},
|
|
84
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
53
85
|
},
|
|
54
86
|
"token": {
|
|
55
87
|
"type": "string",
|
|
56
88
|
"description": "Telegram bot token"
|
|
89
|
+
},
|
|
90
|
+
"id": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"description": "Telegram bot name"
|
|
57
93
|
}
|
|
58
94
|
},
|
|
59
95
|
"required": [
|
|
60
|
-
"
|
|
96
|
+
"id",
|
|
61
97
|
"token"
|
|
62
98
|
]
|
|
63
99
|
}
|
package/src/endpoint.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
parseLegacyMessageReference,
|
|
12
12
|
type ConversationRef,
|
|
13
13
|
} from '@zhin.js/im-contract';
|
|
14
|
-
import { formatCompact,
|
|
14
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
15
15
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
16
16
|
import { runTelegramPollLoop } from './polling.js';
|
|
17
17
|
import { normalizeTelegramChatMember } from './platform-permit.js';
|
|
@@ -36,8 +36,6 @@ import {
|
|
|
36
36
|
import { registerTelegramAgentEndpoint } from './telegram-agent-deps.js';
|
|
37
37
|
import { registerTelegramWebhookRoutes } from './webhook.js';
|
|
38
38
|
|
|
39
|
-
const logger = getLogger('telegram');
|
|
40
|
-
|
|
41
39
|
const CHAT_MEMBER_CACHE_TTL_MS = 60_000;
|
|
42
40
|
const CHAT_MEMBER_CACHE_MAX = 2_000;
|
|
43
41
|
|
|
@@ -87,6 +85,8 @@ interface TelegramApiErr {
|
|
|
87
85
|
* 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
|
|
88
86
|
*/
|
|
89
87
|
export class TelegramEndpoint implements EndpointInstance {
|
|
88
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
89
|
+
|
|
90
90
|
readonly #options: TelegramEndpointOptions;
|
|
91
91
|
readonly #fetch: TelegramFetch;
|
|
92
92
|
#pollAbort?: AbortController;
|
|
@@ -104,6 +104,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
constructor(options: TelegramEndpointOptions) {
|
|
107
|
+
this.#logger = getAdapterLogger('telegram', options.config.id);
|
|
107
108
|
this.#options = options;
|
|
108
109
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
109
110
|
}
|
|
@@ -133,7 +134,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
133
134
|
if (this.#started) return;
|
|
134
135
|
this.#started = true;
|
|
135
136
|
try {
|
|
136
|
-
this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.
|
|
137
|
+
this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.id, this);
|
|
137
138
|
const me = await this.callApi<{ id?: number; username?: string; first_name?: string }>('getMe');
|
|
138
139
|
this.#botUserId = me.id;
|
|
139
140
|
this.#botUsername = me.username;
|
|
@@ -146,9 +147,9 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
146
147
|
const webhook = this.#options.config.webhook!;
|
|
147
148
|
if (!webhook.secretToken) {
|
|
148
149
|
// 未配 secretToken 时 webhook 无鉴权:任何人知道 path 即可注入假 update。
|
|
149
|
-
logger.warn(formatCompact({
|
|
150
|
+
this.#logger.warn(formatCompact({
|
|
150
151
|
op: 'webhook_no_secret',
|
|
151
|
-
endpoint: this.#options.config.
|
|
152
|
+
endpoint: this.#options.config.id,
|
|
152
153
|
path: webhook.path,
|
|
153
154
|
hint: 'set webhook.secretToken to authenticate Telegram callbacks',
|
|
154
155
|
}));
|
|
@@ -159,9 +160,9 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
159
160
|
allowed_updates: this.#options.config.allowedUpdates,
|
|
160
161
|
...(webhook.secretToken ? { secret_token: webhook.secretToken } : {}),
|
|
161
162
|
});
|
|
162
|
-
logger.info(formatCompact({
|
|
163
|
+
this.#logger.info(formatCompact({
|
|
163
164
|
op: 'connect',
|
|
164
|
-
endpoint: this.#options.config.
|
|
165
|
+
endpoint: this.#options.config.id,
|
|
165
166
|
mode: 'webhook',
|
|
166
167
|
path: webhook.path,
|
|
167
168
|
username: me.username,
|
|
@@ -172,15 +173,15 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
172
173
|
await this.callApi('deleteWebhook', { drop_pending_updates: false });
|
|
173
174
|
this.#pollAbort = new AbortController();
|
|
174
175
|
this.#pollPromise = runTelegramPollLoop(this, this.#pollAbort.signal);
|
|
175
|
-
logger.info(formatCompact({
|
|
176
|
+
this.#logger.info(formatCompact({
|
|
176
177
|
op: 'connect',
|
|
177
|
-
endpoint: this.#options.config.
|
|
178
|
+
endpoint: this.#options.config.id,
|
|
178
179
|
mode: 'polling',
|
|
179
180
|
username: me.username,
|
|
180
181
|
}));
|
|
181
182
|
} catch (error) {
|
|
182
183
|
await this.stop();
|
|
183
|
-
logger.error('Failed to connect Telegram bot:', error);
|
|
184
|
+
this.#logger.error('Failed to connect Telegram bot:', error);
|
|
184
185
|
throw error;
|
|
185
186
|
}
|
|
186
187
|
}
|
|
@@ -206,7 +207,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
206
207
|
this.#unregisterAgent = undefined;
|
|
207
208
|
this.#chatMemberCache.clear();
|
|
208
209
|
this.#started = false;
|
|
209
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
210
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -269,7 +270,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
269
270
|
if (!this.#open) return;
|
|
270
271
|
const conversation = telegramInboundConversation(String(this.#options.id), msg.chat);
|
|
271
272
|
void this.#admitWithSenderRole(msg, conversation).catch((err) => {
|
|
272
|
-
logger.warn(formatCompact({
|
|
273
|
+
this.#logger.warn(formatCompact({
|
|
273
274
|
op: 'telegram_gateway_receive_failed',
|
|
274
275
|
target: `${conversation.kind}:${conversation.id}`,
|
|
275
276
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -286,18 +287,20 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
286
287
|
message: { conversation, id: String(msg.message_id) },
|
|
287
288
|
content: formatInboundContent(msg),
|
|
288
289
|
segments: formatInboundSegments(msg),
|
|
289
|
-
sender:
|
|
290
|
+
sender: {
|
|
291
|
+
id: String(msg.from?.id ?? ''),
|
|
292
|
+
name: senderDisplayName(msg.from) || undefined,
|
|
293
|
+
...(permit?.role ? { roles: [permit.role] } : {}),
|
|
294
|
+
},
|
|
295
|
+
endpointId: this.#options.config.id,
|
|
296
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
290
297
|
metadata: Object.freeze({
|
|
291
|
-
endpoint: this.#options.config.name,
|
|
292
|
-
// Preserve Telegram's native value below, but publish the canonical
|
|
293
|
-
// scene kind so every Runtime consumer sees the same conversation type.
|
|
294
298
|
channelType: resolveTelegramChannelType(msg.chat.type),
|
|
295
299
|
chatType: msg.chat.type,
|
|
296
300
|
userId: msg.from?.id,
|
|
297
301
|
date: msg.date,
|
|
298
302
|
...(permit?.role ? { senderRole: permit.role } : {}),
|
|
299
303
|
...(permit?.permissions.length ? { senderPermissions: [...permit.permissions] } : {}),
|
|
300
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
301
304
|
}),
|
|
302
305
|
});
|
|
303
306
|
}
|
|
@@ -360,26 +363,26 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
360
363
|
/** Test / internal: admit a callback query when open. */
|
|
361
364
|
admitCallback(query: TelegramCallbackQuery): void {
|
|
362
365
|
if (!this.#open) return;
|
|
363
|
-
const
|
|
366
|
+
const endpointKey = String(this.#options.id);
|
|
364
367
|
const msg = query.message;
|
|
365
368
|
// 无挂载消息的 callback(如 inline 模式)退化为 sender 私聊会话
|
|
366
369
|
const conversation = msg
|
|
367
|
-
? telegramInboundConversation(
|
|
368
|
-
: telegramInboundConversation(
|
|
370
|
+
? telegramInboundConversation(endpointKey, msg.chat)
|
|
371
|
+
: telegramInboundConversation(endpointKey, { id: query.from.id, type: 'private' });
|
|
369
372
|
void this.#options.gateway.receive({
|
|
370
373
|
conversation,
|
|
371
374
|
message: { conversation, id: query.id },
|
|
372
375
|
content: formatCallbackContent(query),
|
|
373
376
|
segments: formatCallbackSegments(query),
|
|
374
|
-
sender: senderDisplayName(query.from),
|
|
377
|
+
sender: { id: String(query.from?.id ?? ''), name: senderDisplayName(query.from) || undefined },
|
|
378
|
+
endpointId: this.#options.config.id,
|
|
375
379
|
metadata: Object.freeze({
|
|
376
|
-
endpoint: this.#options.config.name,
|
|
377
380
|
eventType: 'callback_query',
|
|
378
381
|
payload: query.data,
|
|
379
382
|
sourceMessageId: msg ? String(msg.message_id) : undefined,
|
|
380
383
|
}),
|
|
381
384
|
}).catch((err) => {
|
|
382
|
-
logger.warn(formatCompact({
|
|
385
|
+
this.#logger.warn(formatCompact({
|
|
383
386
|
op: 'telegram_gateway_receive_failed',
|
|
384
387
|
target: `${conversation.kind}:${conversation.id}`,
|
|
385
388
|
error: err instanceof Error ? err.message : String(err),
|
package/src/index.ts
CHANGED
package/src/platform-permit.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Telegram platform permit — ChatMember 状态 + 细粒度权限
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
6
|
const ADAPTER = 'telegram';
|
|
7
7
|
|
|
@@ -42,13 +42,9 @@ export function normalizeTelegramChatMember(member: {
|
|
|
42
42
|
return { role: 'member', permissions };
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
function
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function checkTelegramPlatformPermit(perm: string, message: Message<any>): boolean {
|
|
51
|
-
const { role, permissions } = senderPermits(message);
|
|
45
|
+
export function checkTelegramPlatformPermit(perm: string, subject: PermissionSubject): boolean {
|
|
46
|
+
const role = subject.sender?.role?.[0];
|
|
47
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
52
48
|
const has = (t: string) => permissions.includes(t);
|
|
53
49
|
|
|
54
50
|
switch (perm) {
|
|
@@ -67,6 +63,3 @@ export function checkTelegramPlatformPermit(perm: string, message: Message<any>)
|
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
export function registerTelegramPlatformPermitChecker(): () => void {
|
|
71
|
-
return registerPlatformPermitChecker(ADAPTER, checkTelegramPlatformPermit);
|
|
72
|
-
}
|
package/src/protocol.ts
CHANGED
|
@@ -13,7 +13,7 @@ const logger = getLogger('telegram');
|
|
|
13
13
|
|
|
14
14
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
15
15
|
export interface TelegramAdapterConfig {
|
|
16
|
-
readonly
|
|
16
|
+
readonly id?: string;
|
|
17
17
|
readonly token?: string;
|
|
18
18
|
/** Default true. `false` selects webhook mode (requires httpHostToken). */
|
|
19
19
|
readonly polling?: boolean;
|
|
@@ -36,7 +36,7 @@ export interface TelegramAdapterConfig {
|
|
|
36
36
|
|
|
37
37
|
export interface ResolvedTelegramConfig {
|
|
38
38
|
readonly context: 'telegram';
|
|
39
|
-
readonly
|
|
39
|
+
readonly id: string;
|
|
40
40
|
readonly token: string;
|
|
41
41
|
readonly mode: 'polling' | 'webhook';
|
|
42
42
|
readonly allowedUpdates: readonly string[];
|
|
@@ -250,8 +250,8 @@ export function resolveTelegramConfig(config: TelegramAdapterConfig = {}): Resol
|
|
|
250
250
|
'Telegram adapter requires token (plugins.<key>.token or endpoints with context: telegram)',
|
|
251
251
|
);
|
|
252
252
|
}
|
|
253
|
-
const
|
|
254
|
-
|| (typeof entry?.
|
|
253
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
254
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
255
255
|
|| process.env.TELEGRAM_BOT_NAME
|
|
256
256
|
|| 'telegram-bot';
|
|
257
257
|
const polling = config.polling ?? entry?.polling;
|
|
@@ -277,7 +277,7 @@ export function resolveTelegramConfig(config: TelegramAdapterConfig = {}): Resol
|
|
|
277
277
|
: undefined;
|
|
278
278
|
return {
|
|
279
279
|
context: 'telegram',
|
|
280
|
-
|
|
280
|
+
id,
|
|
281
281
|
token,
|
|
282
282
|
mode,
|
|
283
283
|
allowedUpdates: [...allowedUpdates],
|
|
@@ -336,11 +336,11 @@ export function resolveTelegramChannelType(
|
|
|
336
336
|
* kind 直取 chat.type(private/group/supergroup/channel),无 parent。
|
|
337
337
|
*/
|
|
338
338
|
export function telegramInboundConversation(
|
|
339
|
-
|
|
339
|
+
endpointKey: string,
|
|
340
340
|
chat: Pick<TelegramChat, 'id' | 'type'>,
|
|
341
341
|
): ConversationRef {
|
|
342
342
|
return {
|
|
343
|
-
endpoint: { id:
|
|
343
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
344
344
|
kind: resolveTelegramChannelType(chat.type),
|
|
345
345
|
id: String(chat.id),
|
|
346
346
|
};
|
|
@@ -28,20 +28,20 @@ export interface TelegramAgentEndpoint {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export interface TelegramAgentDeps {
|
|
31
|
-
getEndpoint: (
|
|
31
|
+
getEndpoint: (endpointKey: string) => TelegramAgentEndpoint;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const endpoints = new Map<string, TelegramAgentEndpoint>();
|
|
35
35
|
let override: TelegramAgentDeps | null = null;
|
|
36
36
|
|
|
37
37
|
export function registerTelegramAgentEndpoint(
|
|
38
|
-
|
|
38
|
+
endpointKey: string,
|
|
39
39
|
endpoint: TelegramAgentEndpoint,
|
|
40
40
|
): () => void {
|
|
41
|
-
endpoints.set(
|
|
41
|
+
endpoints.set(endpointKey, endpoint);
|
|
42
42
|
return () => {
|
|
43
|
-
if (endpoints.get(
|
|
44
|
-
endpoints.delete(
|
|
43
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
44
|
+
endpoints.delete(endpointKey);
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
}
|
|
@@ -54,9 +54,9 @@ export function setTelegramAgentDeps(deps: TelegramAgentDeps | null): void {
|
|
|
54
54
|
export function getTelegramAgentDeps(): TelegramAgentDeps {
|
|
55
55
|
if (override) return override;
|
|
56
56
|
return {
|
|
57
|
-
getEndpoint(
|
|
58
|
-
const registered = endpoints.get(
|
|
59
|
-
if (!registered) throw new Error(`Endpoint ${
|
|
57
|
+
getEndpoint(endpointKey: string): TelegramAgentEndpoint {
|
|
58
|
+
const registered = endpoints.get(endpointKey);
|
|
59
|
+
if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
60
60
|
return registered;
|
|
61
61
|
},
|
|
62
62
|
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|