@zhin.js/adapter-telegram 7.0.1 → 7.0.3
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 +24 -0
- package/README.md +3 -3
- package/lib/endpoint.d.ts +1 -1
- package/lib/endpoint.js +19 -25
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/protocol.d.ts +8 -4
- package/lib/protocol.js +16 -3
- package/package.json +15 -15
- package/src/endpoint.ts +21 -26
- package/src/index.ts +0 -1
- package/src/protocol.ts +21 -6
- /package/commands/endpoint/add/{[name:string].js → [name].js} +0 -0
- /package/commands/endpoint/add/{[name:string].ts → [name].ts} +0 -0
- /package/commands/endpoint/remove/{[name:string].js → [name].js} +0 -0
- /package/commands/endpoint/remove/{[name:string].ts → [name].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 7.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [afc0e66]
|
|
8
|
+
- Updated dependencies [2e41ad5]
|
|
9
|
+
- Updated dependencies [9f57124]
|
|
10
|
+
- @zhin.js/core@1.5.2
|
|
11
|
+
- @zhin.js/adapter@1.1.5
|
|
12
|
+
- @zhin.js/im-contract@1.0.1
|
|
13
|
+
- @zhin.js/plugin-runtime@1.1.3
|
|
14
|
+
- @zhin.js/command@1.0.7
|
|
15
|
+
- @zhin.js/host-http@1.0.6
|
|
16
|
+
- @zhin.js/agent@1.1.3
|
|
17
|
+
- zhin.js@6.0.2
|
|
18
|
+
|
|
19
|
+
## 7.0.2
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [696ab1b]
|
|
24
|
+
- @zhin.js/agent@1.1.2
|
|
25
|
+
- zhin.js@6.0.1
|
|
26
|
+
|
|
3
27
|
## 7.0.1
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Zhin.js Telegram Bot API 适配器(Plugin Runtime),默认通过 **长轮
|
|
|
7
7
|
- 长轮询 `getUpdates` 入站(默认;无需公网 IP / host-http)
|
|
8
8
|
- 解析 text / image / video / audio / voice / document / sticker / location / callback_query
|
|
9
9
|
- 支持私聊与群组
|
|
10
|
-
- 出站 `send({
|
|
10
|
+
- 出站 `send({ conversation, payload })` → Bot API(text / media / keyboard)
|
|
11
11
|
- 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
|
|
12
12
|
- Webhook 模式延期(需 `httpHostToken`);配置 `polling: false` 会明确报错
|
|
13
13
|
|
|
@@ -25,8 +25,8 @@ pnpm add @zhin.js/adapter-telegram
|
|
|
25
25
|
- 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
|
|
26
26
|
- **无需** `@zhin.js/host-http`(polling 路径)
|
|
27
27
|
|
|
28
|
-
入站:`gateway.receive({
|
|
29
|
-
出站:`send({
|
|
28
|
+
入站:`gateway.receive({ conversation, message, content, sender, metadata })`(`conversation` 为 ConversationRef,由 `telegramInboundConversation` 归一化)
|
|
29
|
+
出站:`send({ conversation, payload })` → Telegram Bot API
|
|
30
30
|
|
|
31
31
|
### 平台权限(platform permit)
|
|
32
32
|
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare class TelegramEndpoint implements EndpointInstance {
|
|
|
40
40
|
open(): void;
|
|
41
41
|
close(): void;
|
|
42
42
|
stop(): Promise<void>;
|
|
43
|
-
send({
|
|
43
|
+
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
44
44
|
recallMessage(messageId: string): Promise<void>;
|
|
45
45
|
/** Test / internal: admit a message when open. */
|
|
46
46
|
admit(msg: TelegramMessage): void;
|
package/lib/endpoint.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* TelegramEndpoint — lifecycle, outbound, admit, Bot API helpers for agent tools.
|
|
3
3
|
*/
|
|
4
4
|
import { readFile } from 'node:fs/promises';
|
|
5
|
-
import {
|
|
5
|
+
import { formatLegacyMessageRef, nativeConversationId, parseLegacyMessageReference, } from '@zhin.js/im-contract';
|
|
6
6
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
7
7
|
import { runTelegramPollLoop } from './polling.js';
|
|
8
8
|
import { normalizeTelegramChatMember } from './platform-permit.js';
|
|
9
|
-
import { botApiUrl, buildWebhookUrl, formatCallbackContent, formatCallbackSegments, formatInboundContent, formatInboundSegments, formatOutboundPlan,
|
|
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
12
|
const logger = getLogger('telegram');
|
|
@@ -131,9 +131,8 @@ export class TelegramEndpoint {
|
|
|
131
131
|
this.#started = false;
|
|
132
132
|
logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
|
|
133
133
|
}
|
|
134
|
-
async send({
|
|
135
|
-
const
|
|
136
|
-
const plan = formatOutboundPlan(chatId, payload);
|
|
134
|
+
async send({ conversation, payload }) {
|
|
135
|
+
const plan = formatOutboundPlan(conversation.id, payload);
|
|
137
136
|
let lastId = '';
|
|
138
137
|
for (const action of plan.actions) {
|
|
139
138
|
const form = await this.#buildUploadForm(action.params, plan.uploads);
|
|
@@ -145,7 +144,7 @@ export class TelegramEndpoint {
|
|
|
145
144
|
}
|
|
146
145
|
if (!lastId)
|
|
147
146
|
return `telegram-${Date.now()}`;
|
|
148
|
-
return
|
|
147
|
+
return formatLegacyMessageRef({ conversation, id: lastId });
|
|
149
148
|
}
|
|
150
149
|
async recallMessage(messageId) {
|
|
151
150
|
if (!messageId || messageId.startsWith('telegram-'))
|
|
@@ -188,26 +187,25 @@ export class TelegramEndpoint {
|
|
|
188
187
|
admit(msg) {
|
|
189
188
|
if (!this.#open)
|
|
190
189
|
return;
|
|
191
|
-
const
|
|
192
|
-
void this.#admitWithSenderRole(msg,
|
|
190
|
+
const conversation = telegramInboundConversation(String(this.#options.id), msg.chat);
|
|
191
|
+
void this.#admitWithSenderRole(msg, conversation).catch((err) => {
|
|
193
192
|
logger.warn(formatCompact({
|
|
194
193
|
op: 'telegram_gateway_receive_failed',
|
|
195
|
-
target:
|
|
194
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
196
195
|
error: err instanceof Error ? err.message : String(err),
|
|
197
196
|
}));
|
|
198
197
|
});
|
|
199
198
|
}
|
|
200
|
-
async #admitWithSenderRole(msg,
|
|
199
|
+
async #admitWithSenderRole(msg, conversation) {
|
|
201
200
|
const permit = await this.#resolveGroupSenderPermit(msg);
|
|
202
201
|
// 新 Runtime Message.content 为纯文本:@ 本机只能经 metadata 传递
|
|
203
202
|
const mentioned = this.#isBotMentioned(msg);
|
|
204
203
|
await this.#options.gateway.receive({
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
conversation,
|
|
205
|
+
message: { conversation, id: String(msg.message_id) },
|
|
207
206
|
content: formatInboundContent(msg),
|
|
208
207
|
segments: formatInboundSegments(msg),
|
|
209
208
|
sender: senderDisplayName(msg.from),
|
|
210
|
-
id: String(msg.message_id),
|
|
211
209
|
metadata: Object.freeze({
|
|
212
210
|
endpoint: this.#options.config.name,
|
|
213
211
|
// Preserve Telegram's native value below, but publish the canonical
|
|
@@ -287,15 +285,18 @@ export class TelegramEndpoint {
|
|
|
287
285
|
admitCallback(query) {
|
|
288
286
|
if (!this.#open)
|
|
289
287
|
return;
|
|
288
|
+
const endpointId = String(this.#options.id);
|
|
290
289
|
const msg = query.message;
|
|
291
|
-
|
|
290
|
+
// 无挂载消息的 callback(如 inline 模式)退化为 sender 私聊会话
|
|
291
|
+
const conversation = msg
|
|
292
|
+
? telegramInboundConversation(endpointId, msg.chat)
|
|
293
|
+
: telegramInboundConversation(endpointId, { id: query.from.id, type: 'private' });
|
|
292
294
|
void this.#options.gateway.receive({
|
|
293
|
-
|
|
294
|
-
|
|
295
|
+
conversation,
|
|
296
|
+
message: { conversation, id: query.id },
|
|
295
297
|
content: formatCallbackContent(query),
|
|
296
298
|
segments: formatCallbackSegments(query),
|
|
297
299
|
sender: senderDisplayName(query.from),
|
|
298
|
-
id: query.id,
|
|
299
300
|
metadata: Object.freeze({
|
|
300
301
|
endpoint: this.#options.config.name,
|
|
301
302
|
eventType: 'callback_query',
|
|
@@ -305,7 +306,7 @@ export class TelegramEndpoint {
|
|
|
305
306
|
}).catch((err) => {
|
|
306
307
|
logger.warn(formatCompact({
|
|
307
308
|
op: 'telegram_gateway_receive_failed',
|
|
308
|
-
target:
|
|
309
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
309
310
|
error: err instanceof Error ? err.message : String(err),
|
|
310
311
|
}));
|
|
311
312
|
});
|
|
@@ -413,10 +414,3 @@ export class TelegramEndpoint {
|
|
|
413
414
|
});
|
|
414
415
|
}
|
|
415
416
|
}
|
|
416
|
-
function resolveTelegramChannelType(chatType) {
|
|
417
|
-
if (chatType === 'private')
|
|
418
|
-
return 'private';
|
|
419
|
-
if (chatType === 'channel')
|
|
420
|
-
return 'channel';
|
|
421
|
-
return 'group';
|
|
422
|
-
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { TelegramEndpoint, type TelegramEndpointOptions, type TelegramFetch, } from './endpoint.js';
|
|
2
|
-
export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath,
|
|
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
4
|
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, registerTelegramPlatformPermitChecker, telegramGroupPermitResolver, } from './platform-permit.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { TelegramEndpoint, } from './endpoint.js';
|
|
2
|
-
export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath,
|
|
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
4
|
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, registerTelegramPlatformPermitChecker, telegramGroupPermitResolver, } from './platform-permit.js';
|
package/lib/protocol.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { IncomingMessage } from 'node:http';
|
|
6
6
|
import type { Segment } from '@zhin.js/core/runtime';
|
|
7
|
+
import type { ConversationKind, ConversationRef } from '@zhin.js/im-contract';
|
|
7
8
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
8
9
|
export interface TelegramAdapterConfig {
|
|
9
10
|
readonly name?: string;
|
|
@@ -236,10 +237,13 @@ export declare function readTextBody(request: IncomingMessage, options?: {
|
|
|
236
237
|
readonly limit?: number;
|
|
237
238
|
}): Promise<string>;
|
|
238
239
|
export declare function botApiUrl(config: Pick<ResolvedTelegramConfig, 'apiBaseUrl' | 'token'>, method: string): string;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
/** Telegram chat.type → canonical 会话 kind(supergroup 即 group,无容器层级故无 parent)。 */
|
|
241
|
+
export declare function resolveTelegramChannelType(chatType: TelegramChat['type']): ConversationKind;
|
|
242
|
+
/**
|
|
243
|
+
* 入站归一化 → ConversationRef:Telegram 无 guild/群组容器层级,
|
|
244
|
+
* kind 直取 chat.type(private/group/supergroup/channel),无 parent。
|
|
245
|
+
*/
|
|
246
|
+
export declare function telegramInboundConversation(endpointId: string, chat: Pick<TelegramChat, 'id' | 'type'>): ConversationRef;
|
|
243
247
|
export declare function senderDisplayName(user?: TelegramUser): string;
|
|
244
248
|
/** Build inbound text for MessageGateway.receive. */
|
|
245
249
|
export declare function formatInboundContent(msg: TelegramMessage): string;
|
package/lib/protocol.js
CHANGED
|
@@ -76,10 +76,23 @@ export async function readTextBody(request, options = {}) {
|
|
|
76
76
|
export function botApiUrl(config, method) {
|
|
77
77
|
return `${config.apiBaseUrl}/bot${config.token}/${method}`;
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
/** Telegram chat.type → canonical 会话 kind(supergroup 即 group,无容器层级故无 parent)。 */
|
|
80
|
+
export function resolveTelegramChannelType(chatType) {
|
|
81
|
+
if (chatType === 'private')
|
|
82
|
+
return 'private';
|
|
83
|
+
if (chatType === 'channel')
|
|
84
|
+
return 'channel';
|
|
85
|
+
return 'group';
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 入站归一化 → ConversationRef:Telegram 无 guild/群组容器层级,
|
|
89
|
+
* kind 直取 chat.type(private/group/supergroup/channel),无 parent。
|
|
90
|
+
*/
|
|
91
|
+
export function telegramInboundConversation(endpointId, chat) {
|
|
80
92
|
return {
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
|
|
94
|
+
kind: resolveTelegramChannelType(chat.type),
|
|
95
|
+
id: String(chat.id),
|
|
83
96
|
};
|
|
84
97
|
}
|
|
85
98
|
export function senderDisplayName(user) {
|
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.3",
|
|
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,21 @@
|
|
|
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.
|
|
35
|
+
"@zhin.js/adapter": "1.1.5",
|
|
36
|
+
"@zhin.js/command": "1.0.7",
|
|
37
|
+
"@zhin.js/core": "1.5.2",
|
|
38
|
+
"@zhin.js/host-http": "1.0.6",
|
|
39
|
+
"@zhin.js/im-contract": "1.0.1",
|
|
40
40
|
"@zhin.js/logger": "1.0.75",
|
|
41
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
41
|
+
"@zhin.js/plugin-runtime": "1.1.3"
|
|
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/plugin-runtime": "1.1.
|
|
49
|
-
"zhin.js": "6.0.
|
|
45
|
+
"@zhin.js/adapter": "1.1.5",
|
|
46
|
+
"@zhin.js/agent": "1.1.3",
|
|
47
|
+
"@zhin.js/core": "1.5.2",
|
|
48
|
+
"@zhin.js/plugin-runtime": "1.1.3",
|
|
49
|
+
"zhin.js": "6.0.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
52
52
|
"zhin.js": {
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"typescript": "^6.0.3",
|
|
65
65
|
"vitest": "^4.1.10",
|
|
66
66
|
"zod": "^4.4.3",
|
|
67
|
-
"@zhin.js/agent": "1.1.
|
|
68
|
-
"@zhin.js/host-http": "1.0.
|
|
69
|
-
"zhin.js": "6.0.
|
|
67
|
+
"@zhin.js/agent": "1.1.3",
|
|
68
|
+
"@zhin.js/host-http": "1.0.6",
|
|
69
|
+
"zhin.js": "6.0.2"
|
|
70
70
|
},
|
|
71
71
|
"files": [
|
|
72
72
|
"adapters",
|
package/src/endpoint.ts
CHANGED
|
@@ -6,9 +6,10 @@ import type { EndpointControl, EndpointInstance, EndpointSendRequest } from '@zh
|
|
|
6
6
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
7
7
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
8
8
|
import {
|
|
9
|
-
|
|
9
|
+
formatLegacyMessageRef,
|
|
10
10
|
nativeConversationId,
|
|
11
11
|
parseLegacyMessageReference,
|
|
12
|
+
type ConversationRef,
|
|
12
13
|
} from '@zhin.js/im-contract';
|
|
13
14
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
14
15
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
@@ -22,8 +23,9 @@ import {
|
|
|
22
23
|
formatInboundContent,
|
|
23
24
|
formatInboundSegments,
|
|
24
25
|
formatOutboundPlan,
|
|
25
|
-
|
|
26
|
+
resolveTelegramChannelType,
|
|
26
27
|
senderDisplayName,
|
|
28
|
+
telegramInboundConversation,
|
|
27
29
|
type ResolvedTelegramConfig,
|
|
28
30
|
type TelegramCallbackQuery,
|
|
29
31
|
type TelegramChatMember,
|
|
@@ -207,9 +209,8 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
207
209
|
logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
|
|
208
210
|
}
|
|
209
211
|
|
|
210
|
-
async send({
|
|
211
|
-
const
|
|
212
|
-
const plan = formatOutboundPlan(chatId, payload);
|
|
212
|
+
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
213
|
+
const plan = formatOutboundPlan(conversation.id, payload);
|
|
213
214
|
let lastId = '';
|
|
214
215
|
for (const action of plan.actions) {
|
|
215
216
|
const form = await this.#buildUploadForm(action.params, plan.uploads);
|
|
@@ -219,7 +220,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
219
220
|
if (result.message_id != null) lastId = String(result.message_id);
|
|
220
221
|
}
|
|
221
222
|
if (!lastId) return `telegram-${Date.now()}`;
|
|
222
|
-
return
|
|
223
|
+
return formatLegacyMessageRef({ conversation, id: lastId });
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
async recallMessage(messageId: string): Promise<void> {
|
|
@@ -266,27 +267,26 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
266
267
|
/** Test / internal: admit a message when open. */
|
|
267
268
|
admit(msg: TelegramMessage): void {
|
|
268
269
|
if (!this.#open) return;
|
|
269
|
-
const
|
|
270
|
-
void this.#admitWithSenderRole(msg,
|
|
270
|
+
const conversation = telegramInboundConversation(String(this.#options.id), msg.chat);
|
|
271
|
+
void this.#admitWithSenderRole(msg, conversation).catch((err) => {
|
|
271
272
|
logger.warn(formatCompact({
|
|
272
273
|
op: 'telegram_gateway_receive_failed',
|
|
273
|
-
target:
|
|
274
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
274
275
|
error: err instanceof Error ? err.message : String(err),
|
|
275
276
|
}));
|
|
276
277
|
});
|
|
277
278
|
}
|
|
278
279
|
|
|
279
|
-
async #admitWithSenderRole(msg: TelegramMessage,
|
|
280
|
+
async #admitWithSenderRole(msg: TelegramMessage, conversation: ConversationRef): Promise<void> {
|
|
280
281
|
const permit = await this.#resolveGroupSenderPermit(msg);
|
|
281
282
|
// 新 Runtime Message.content 为纯文本:@ 本机只能经 metadata 传递
|
|
282
283
|
const mentioned = this.#isBotMentioned(msg);
|
|
283
284
|
await this.#options.gateway.receive({
|
|
284
|
-
|
|
285
|
-
|
|
285
|
+
conversation,
|
|
286
|
+
message: { conversation, id: String(msg.message_id) },
|
|
286
287
|
content: formatInboundContent(msg),
|
|
287
288
|
segments: formatInboundSegments(msg),
|
|
288
289
|
sender: senderDisplayName(msg.from),
|
|
289
|
-
id: String(msg.message_id),
|
|
290
290
|
metadata: Object.freeze({
|
|
291
291
|
endpoint: this.#options.config.name,
|
|
292
292
|
// Preserve Telegram's native value below, but publish the canonical
|
|
@@ -360,15 +360,18 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
360
360
|
/** Test / internal: admit a callback query when open. */
|
|
361
361
|
admitCallback(query: TelegramCallbackQuery): void {
|
|
362
362
|
if (!this.#open) return;
|
|
363
|
+
const endpointId = String(this.#options.id);
|
|
363
364
|
const msg = query.message;
|
|
364
|
-
|
|
365
|
+
// 无挂载消息的 callback(如 inline 模式)退化为 sender 私聊会话
|
|
366
|
+
const conversation = msg
|
|
367
|
+
? telegramInboundConversation(endpointId, msg.chat)
|
|
368
|
+
: telegramInboundConversation(endpointId, { id: query.from.id, type: 'private' });
|
|
365
369
|
void this.#options.gateway.receive({
|
|
366
|
-
|
|
367
|
-
|
|
370
|
+
conversation,
|
|
371
|
+
message: { conversation, id: query.id },
|
|
368
372
|
content: formatCallbackContent(query),
|
|
369
373
|
segments: formatCallbackSegments(query),
|
|
370
374
|
sender: senderDisplayName(query.from),
|
|
371
|
-
id: query.id,
|
|
372
375
|
metadata: Object.freeze({
|
|
373
376
|
endpoint: this.#options.config.name,
|
|
374
377
|
eventType: 'callback_query',
|
|
@@ -378,7 +381,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
378
381
|
}).catch((err) => {
|
|
379
382
|
logger.warn(formatCompact({
|
|
380
383
|
op: 'telegram_gateway_receive_failed',
|
|
381
|
-
target:
|
|
384
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
382
385
|
error: err instanceof Error ? err.message : String(err),
|
|
383
386
|
}));
|
|
384
387
|
});
|
|
@@ -521,11 +524,3 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
521
524
|
});
|
|
522
525
|
}
|
|
523
526
|
}
|
|
524
|
-
|
|
525
|
-
function resolveTelegramChannelType(
|
|
526
|
-
chatType: TelegramMessage['chat']['type'],
|
|
527
|
-
): 'private' | 'group' | 'channel' {
|
|
528
|
-
if (chatType === 'private') return 'private';
|
|
529
|
-
if (chatType === 'channel') return 'channel';
|
|
530
|
-
return 'group';
|
|
531
|
-
}
|
package/src/index.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { IncomingMessage } from 'node:http';
|
|
7
7
|
import { isMediaRef } from '@zhin.js/core';
|
|
8
8
|
import type { Segment } from '@zhin.js/core/runtime';
|
|
9
|
+
import type { ConversationKind, ConversationRef } from '@zhin.js/im-contract';
|
|
9
10
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
10
11
|
|
|
11
12
|
const logger = getLogger('telegram');
|
|
@@ -321,13 +322,27 @@ export function botApiUrl(config: Pick<ResolvedTelegramConfig, 'apiBaseUrl' | 't
|
|
|
321
322
|
return `${config.apiBaseUrl}/bot${config.token}/${method}`;
|
|
322
323
|
}
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
/** Telegram chat.type → canonical 会话 kind(supergroup 即 group,无容器层级故无 parent)。 */
|
|
326
|
+
export function resolveTelegramChannelType(
|
|
327
|
+
chatType: TelegramChat['type'],
|
|
328
|
+
): ConversationKind {
|
|
329
|
+
if (chatType === 'private') return 'private';
|
|
330
|
+
if (chatType === 'channel') return 'channel';
|
|
331
|
+
return 'group';
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* 入站归一化 → ConversationRef:Telegram 无 guild/群组容器层级,
|
|
336
|
+
* kind 直取 chat.type(private/group/supergroup/channel),无 parent。
|
|
337
|
+
*/
|
|
338
|
+
export function telegramInboundConversation(
|
|
339
|
+
endpointId: string,
|
|
340
|
+
chat: Pick<TelegramChat, 'id' | 'type'>,
|
|
341
|
+
): ConversationRef {
|
|
328
342
|
return {
|
|
329
|
-
|
|
330
|
-
|
|
343
|
+
endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
|
|
344
|
+
kind: resolveTelegramChannelType(chat.type),
|
|
345
|
+
id: String(chat.id),
|
|
331
346
|
};
|
|
332
347
|
}
|
|
333
348
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|