@zhin.js/adapter-telegram 7.0.14 → 8.0.1
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 +35 -0
- package/README.md +1 -1
- package/adapters/telegram.js +0 -3
- package/adapters/telegram.ts +0 -3
- package/agent/tools/create_invite.ts +4 -6
- package/agent/tools/list_admins.ts +4 -6
- package/agent/tools/member_count.ts +4 -6
- package/agent/tools/pin_message.ts +4 -6
- package/agent/tools/react.ts +4 -6
- package/agent/tools/send_poll.ts +4 -6
- package/agent/tools/send_sticker.ts +4 -6
- package/agent/tools/set_description.ts +4 -6
- package/agent/tools/set_permissions.ts +4 -6
- package/agent/tools/unpin_message.ts +4 -6
- package/lib/client.d.ts +12 -0
- package/lib/client.js +2 -0
- package/lib/endpoint.d.ts +43 -5
- package/lib/endpoint.js +50 -8
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/protocol.d.ts +1 -1
- package/lib/protocol.js +1 -1
- package/lib/telegram-endpoint-commands.d.ts +1 -1
- package/package.json +15 -14
- package/src/client.ts +16 -0
- package/src/endpoint.ts +85 -12
- package/src/index.ts +3 -7
- package/src/protocol.ts +1 -1
- package/lib/telegram-agent-deps.d.ts +0 -28
- package/lib/telegram-agent-deps.js +0 -30
- package/src/telegram-agent-deps.ts +0 -63
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 8.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1fc78bc: Unify native platform Client access behind the literal `adapter` discriminant. Handlers infer both native events and Clients, while command, inbound/outbound middleware, and both Agent tool authoring surfaces expose the exact operation-scoped Client through a lazy `$client` getter. Definitions without `adapter` keep `$client` typed as `unknown`, and runtime dispatch rejects adapter mismatches before resolving the Client. Bundled platform tools now use this single path instead of model-provided endpoint ids and adapter-specific dependency wrappers. Every adapter registers one Client/EventMap contract, and protocol adapters including NapCat, Milky, OneBot and Satori now produce transport-independent Client objects rather than letting Endpoint instances impersonate Clients.
|
|
8
|
+
- Updated dependencies [e9c6a73]
|
|
9
|
+
- Updated dependencies [4e8117c]
|
|
10
|
+
- Updated dependencies [902fa35]
|
|
11
|
+
- Updated dependencies [54bfd6b]
|
|
12
|
+
- Updated dependencies [12025ee]
|
|
13
|
+
- Updated dependencies [09b14d6]
|
|
14
|
+
- Updated dependencies [1fc78bc]
|
|
15
|
+
- @zhin.js/agent@1.1.16
|
|
16
|
+
- @zhin.js/adapter@1.2.1
|
|
17
|
+
- @zhin.js/core@1.5.14
|
|
18
|
+
- @zhin.js/host-http@1.0.13
|
|
19
|
+
- @zhin.js/command@1.0.16
|
|
20
|
+
- @zhin.js/logger@1.0.77
|
|
21
|
+
- zhin.js@6.0.14
|
|
22
|
+
- @zhin.js/feature-kit@1.0.13
|
|
23
|
+
- @zhin.js/permission@1.0.4
|
|
24
|
+
|
|
25
|
+
## 8.0.0
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [b10d058]
|
|
30
|
+
- Updated dependencies [f2c532f]
|
|
31
|
+
- Updated dependencies [3dbf990]
|
|
32
|
+
- @zhin.js/host-http@1.0.12
|
|
33
|
+
- @zhin.js/adapter@1.2.0
|
|
34
|
+
- @zhin.js/core@1.5.13
|
|
35
|
+
- @zhin.js/agent@1.1.15
|
|
36
|
+
- zhin.js@6.0.13
|
|
37
|
+
|
|
3
38
|
## 7.0.14
|
|
4
39
|
|
|
5
40
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ pnpm add @zhin.js/adapter-telegram
|
|
|
20
20
|
## Plugin Runtime
|
|
21
21
|
|
|
22
22
|
- `@zhin.js/adapter` — 约定式 `adapters/telegram.ts`(`defineAdapter`)
|
|
23
|
-
- `@zhin.js/core` — `
|
|
23
|
+
- `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
|
|
24
24
|
- `zhin.js` — `plugin.ts`(`definePlugin`)
|
|
25
25
|
- 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
|
|
26
26
|
- **无需** `@zhin.js/host-http`(polling 路径)
|
package/adapters/telegram.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Convention entry: discover `adapters/telegram.ts` → defineAdapter.
|
|
4
4
|
*/
|
|
5
5
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
|
-
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
7
6
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
8
7
|
import { TelegramEndpoint } from "../lib/endpoint.js";
|
|
9
8
|
import { resolveTelegramConfig, } from "../lib/protocol.js";
|
|
@@ -28,8 +27,6 @@ export default defineAdapter({
|
|
|
28
27
|
});
|
|
29
28
|
return new TelegramEndpoint({
|
|
30
29
|
id: context.id,
|
|
31
|
-
gateway: context.use(messageGatewayToken),
|
|
32
|
-
sideEvents: context.use(sideEventGatewayToken),
|
|
33
30
|
config,
|
|
34
31
|
http: config.mode === 'webhook' ? context.use(httpHostToken) : undefined,
|
|
35
32
|
});
|
package/adapters/telegram.ts
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Convention entry: discover `adapters/telegram.ts` → defineAdapter.
|
|
3
3
|
*/
|
|
4
4
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
|
-
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
6
5
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
6
|
import { TelegramEndpoint } from '../src/endpoint.js';
|
|
8
7
|
import {
|
|
@@ -33,8 +32,6 @@ export default defineAdapter<TelegramAdapterConfig>({
|
|
|
33
32
|
});
|
|
34
33
|
return new TelegramEndpoint({
|
|
35
34
|
id: context.id,
|
|
36
|
-
gateway: context.use(messageGatewayToken),
|
|
37
|
-
sideEvents: context.use(sideEventGatewayToken),
|
|
38
35
|
config,
|
|
39
36
|
http: config.mode === 'webhook' ? context.use(httpHostToken) : undefined,
|
|
40
37
|
});
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { platformPermit } from '../../src/platform-permit.js';
|
|
4
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
5
4
|
|
|
6
|
-
export default defineAgentTool<{
|
|
5
|
+
export default defineAgentTool<{ chat_id: string }>({
|
|
7
6
|
description: '创建 Telegram 群组邀请链接',
|
|
8
7
|
inputSchema: z.object({
|
|
9
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
10
8
|
chat_id: z.string().describe('聊天 ID'),
|
|
11
9
|
}),
|
|
12
|
-
|
|
10
|
+
adapter: 'telegram',
|
|
13
11
|
tags: ['telegram'],
|
|
14
12
|
permissions: [platformPermit('chat_administrator')],
|
|
15
|
-
async execute({
|
|
16
|
-
const endpoint =
|
|
13
|
+
async execute({ chat_id }: { chat_id: string }, context) {
|
|
14
|
+
const endpoint = context.$client;
|
|
17
15
|
const link = await endpoint.createInviteLink(Number(chat_id));
|
|
18
16
|
return { invite_link: link, message: `邀请链接: ${link}` };
|
|
19
17
|
},
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
4
3
|
|
|
5
|
-
export default defineAgentTool<{
|
|
4
|
+
export default defineAgentTool<{ chat_id: string }>({
|
|
6
5
|
description: '获取 Telegram 群组管理员列表',
|
|
7
6
|
inputSchema: z.object({
|
|
8
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
9
7
|
chat_id: z.string().describe('聊天 ID'),
|
|
10
8
|
}),
|
|
11
|
-
|
|
9
|
+
adapter: 'telegram',
|
|
12
10
|
tags: ['telegram'],
|
|
13
|
-
async execute({
|
|
14
|
-
const endpoint =
|
|
11
|
+
async execute({ chat_id }: { chat_id: string }, context) {
|
|
12
|
+
const endpoint = context.$client;
|
|
15
13
|
const admins = await endpoint.getChatAdmins(Number(chat_id));
|
|
16
14
|
return {
|
|
17
15
|
admins: admins.map((a: { user: { id: number; username?: string; first_name?: string }; status: string }) => ({
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
4
3
|
|
|
5
|
-
export default defineAgentTool<{
|
|
4
|
+
export default defineAgentTool<{ chat_id: string }>({
|
|
6
5
|
description: '获取 Telegram 群组成员数量',
|
|
7
6
|
inputSchema: z.object({
|
|
8
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
9
7
|
chat_id: z.string().describe('聊天 ID'),
|
|
10
8
|
}),
|
|
11
|
-
|
|
9
|
+
adapter: 'telegram',
|
|
12
10
|
tags: ['telegram'],
|
|
13
|
-
async execute({
|
|
14
|
-
const endpoint =
|
|
11
|
+
async execute({ chat_id }: { chat_id: string }, context) {
|
|
12
|
+
const endpoint = context.$client;
|
|
15
13
|
const count = await endpoint.getChatMemberCount(Number(chat_id));
|
|
16
14
|
return { count, message: `群组共有 ${count} 名成员` };
|
|
17
15
|
},
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { platformPermit } from '../../src/platform-permit.js';
|
|
4
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
5
4
|
|
|
6
|
-
export default defineAgentTool<{
|
|
5
|
+
export default defineAgentTool<{ chat_id: string; message_id: string }>({
|
|
7
6
|
description: '置顶 Telegram 群组消息',
|
|
8
7
|
inputSchema: z.object({
|
|
9
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
10
8
|
chat_id: z.string().describe('聊天 ID'),
|
|
11
9
|
message_id: z.string().describe('消息 ID'),
|
|
12
10
|
}),
|
|
13
|
-
|
|
11
|
+
adapter: 'telegram',
|
|
14
12
|
tags: ['telegram'],
|
|
15
13
|
permissions: [platformPermit('pin_messages')],
|
|
16
|
-
async execute({
|
|
17
|
-
const endpoint =
|
|
14
|
+
async execute({ chat_id, message_id }: { chat_id: string; message_id: string }, context) {
|
|
15
|
+
const endpoint = context.$client;
|
|
18
16
|
const success = await endpoint.pinMessage(Number(chat_id), Number(message_id));
|
|
19
17
|
return { success, message: success ? '消息已置顶' : '操作失败' };
|
|
20
18
|
},
|
package/agent/tools/react.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
4
3
|
|
|
5
|
-
export default defineAgentTool<{
|
|
4
|
+
export default defineAgentTool<{ chat_id: string; message_id: string; reaction: string }>({
|
|
6
5
|
description: '对 Telegram 消息添加表情反应',
|
|
7
6
|
inputSchema: z.object({
|
|
8
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
9
7
|
chat_id: z.string().describe('聊天 ID'),
|
|
10
8
|
message_id: z.string().describe('消息 ID'),
|
|
11
9
|
reaction: z.string().describe('反应表情(如 👍、❤️、🔥)'),
|
|
12
10
|
}),
|
|
13
|
-
|
|
11
|
+
adapter: 'telegram',
|
|
14
12
|
tags: ['telegram'],
|
|
15
|
-
async execute({
|
|
16
|
-
const endpoint =
|
|
13
|
+
async execute({ chat_id, message_id, reaction }: { chat_id: string; message_id: string; reaction: string }, context) {
|
|
14
|
+
const endpoint = context.$client;
|
|
17
15
|
const success = await endpoint.setMessageReaction(Number(chat_id), Number(message_id), reaction);
|
|
18
16
|
return { success, message: success ? `已添加反应 ${reaction}` : '操作失败' };
|
|
19
17
|
},
|
package/agent/tools/send_poll.ts
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
4
3
|
|
|
5
|
-
export default defineAgentTool<{
|
|
4
|
+
export default defineAgentTool<{ chat_id: string; question: string; options: string; is_anonymous?: boolean; allows_multiple?: boolean }>({
|
|
6
5
|
description: '在 Telegram 群组中发起投票',
|
|
7
6
|
inputSchema: z.object({
|
|
8
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
9
7
|
chat_id: z.string().describe('聊天 ID'),
|
|
10
8
|
question: z.string().describe('投票问题'),
|
|
11
9
|
options: z.string().describe('选项 JSON 数组,如 ["A","B","C"]'),
|
|
12
10
|
is_anonymous: z.boolean().optional().describe('是否匿名投票,默认 true'),
|
|
13
11
|
allows_multiple: z.boolean().optional().describe('是否允许多选,默认 false'),
|
|
14
12
|
}),
|
|
15
|
-
|
|
13
|
+
adapter: 'telegram',
|
|
16
14
|
tags: ['telegram'],
|
|
17
|
-
async execute({
|
|
18
|
-
const endpoint =
|
|
15
|
+
async execute({ chat_id, question, options, is_anonymous, allows_multiple }: { chat_id: string; question: string; options: string; is_anonymous?: boolean; allows_multiple?: boolean }, context) {
|
|
16
|
+
const endpoint = context.$client;
|
|
19
17
|
let optList: string[];
|
|
20
18
|
try {
|
|
21
19
|
optList = JSON.parse(options);
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
4
3
|
|
|
5
|
-
export default defineAgentTool<{
|
|
4
|
+
export default defineAgentTool<{ chat_id: string; sticker: string }>({
|
|
6
5
|
description: '发送 Telegram 贴纸',
|
|
7
6
|
inputSchema: z.object({
|
|
8
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
9
7
|
chat_id: z.string().describe('聊天 ID'),
|
|
10
8
|
sticker: z.string().describe('贴纸 file_id 或 URL'),
|
|
11
9
|
}),
|
|
12
|
-
|
|
10
|
+
adapter: 'telegram',
|
|
13
11
|
tags: ['telegram'],
|
|
14
|
-
async execute({
|
|
15
|
-
const endpoint =
|
|
12
|
+
async execute({ chat_id, sticker }: { chat_id: string; sticker: string }, context) {
|
|
13
|
+
const endpoint = context.$client;
|
|
16
14
|
const result = await endpoint.sendStickerMessage(Number(chat_id), sticker);
|
|
17
15
|
return { success: true, message_id: result.message_id, message: '贴纸已发送' };
|
|
18
16
|
},
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
4
3
|
|
|
5
|
-
export default defineAgentTool<{
|
|
4
|
+
export default defineAgentTool<{ chat_id: string; description: string }>({
|
|
6
5
|
description: '设置 Telegram 群组描述',
|
|
7
6
|
inputSchema: z.object({
|
|
8
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
9
7
|
chat_id: z.string().describe('聊天 ID'),
|
|
10
8
|
description: z.string().describe('群描述文字'),
|
|
11
9
|
}),
|
|
12
|
-
|
|
10
|
+
adapter: 'telegram',
|
|
13
11
|
tags: ['telegram'],
|
|
14
|
-
async execute({
|
|
15
|
-
const endpoint =
|
|
12
|
+
async execute({ chat_id, description }: { chat_id: string; description: string }, context) {
|
|
13
|
+
const endpoint = context.$client;
|
|
16
14
|
const success = await endpoint.setChatDescription(Number(chat_id), description);
|
|
17
15
|
return { success, message: success ? '群描述已更新' : '操作失败' };
|
|
18
16
|
},
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { platformPermit } from '../../src/platform-permit.js';
|
|
4
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
5
4
|
|
|
6
|
-
export default defineAgentTool<{
|
|
5
|
+
export default defineAgentTool<{ chat_id: string; can_send_messages?: boolean; can_send_photos?: boolean; can_send_videos?: boolean; can_send_polls?: boolean; can_send_other_messages?: boolean; can_add_web_page_previews?: boolean; can_change_info?: boolean; can_invite_users?: boolean; can_pin_messages?: boolean }>({
|
|
7
6
|
description: '设置 Telegram 群组的默认成员权限',
|
|
8
7
|
inputSchema: z.object({
|
|
9
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
10
8
|
chat_id: z.string().describe('聊天 ID'),
|
|
11
9
|
can_send_messages: z.boolean().optional().describe('是否可以发消息'),
|
|
12
10
|
can_send_photos: z.boolean().optional().describe('是否可以发图片'),
|
|
@@ -18,11 +16,11 @@ export default defineAgentTool<{ endpoint_id: string; chat_id: string; can_send_
|
|
|
18
16
|
can_invite_users: z.boolean().optional().describe('是否可以邀请用户'),
|
|
19
17
|
can_pin_messages: z.boolean().optional().describe('是否可以置顶消息'),
|
|
20
18
|
}),
|
|
21
|
-
|
|
19
|
+
adapter: 'telegram',
|
|
22
20
|
tags: ['telegram'],
|
|
23
21
|
permissions: [platformPermit('manage_chat')],
|
|
24
|
-
async execute({
|
|
25
|
-
const endpoint =
|
|
22
|
+
async execute({ chat_id, ...perms }: { chat_id: string; can_send_messages?: boolean; can_send_photos?: boolean; can_send_videos?: boolean; can_send_polls?: boolean; can_send_other_messages?: boolean; can_add_web_page_previews?: boolean; can_change_info?: boolean; can_invite_users?: boolean; can_pin_messages?: boolean }, context) {
|
|
23
|
+
const endpoint = context.$client;
|
|
26
24
|
const permissions: Record<string, boolean> = {};
|
|
27
25
|
for (const [k, v] of Object.entries(perms)) {
|
|
28
26
|
if (typeof v === 'boolean') permissions[k] = v;
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { defineAgentTool } from '@zhin.js/agent/tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { platformPermit } from '../../src/platform-permit.js';
|
|
4
|
-
import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
|
|
5
4
|
|
|
6
|
-
export default defineAgentTool<{
|
|
5
|
+
export default defineAgentTool<{ chat_id: string; message_id?: string }>({
|
|
7
6
|
description: '取消置顶 Telegram 群组消息',
|
|
8
7
|
inputSchema: z.object({
|
|
9
|
-
endpoint_id: z.string().describe('Endpoint 名称'),
|
|
10
8
|
chat_id: z.string().describe('聊天 ID'),
|
|
11
9
|
message_id: z.string().optional().describe('消息 ID(可选,不提供则取消所有置顶)'),
|
|
12
10
|
}),
|
|
13
|
-
|
|
11
|
+
adapter: 'telegram',
|
|
14
12
|
tags: ['telegram'],
|
|
15
13
|
permissions: [platformPermit('pin_messages')],
|
|
16
|
-
async execute({
|
|
17
|
-
const endpoint =
|
|
14
|
+
async execute({ chat_id, message_id }: { chat_id: string; message_id?: string }, context) {
|
|
15
|
+
const endpoint = context.$client;
|
|
18
16
|
const success = await endpoint.unpinMessage(Number(chat_id), message_id ? Number(message_id) : undefined);
|
|
19
17
|
return { success, message: success ? '已取消置顶' : '操作失败' };
|
|
20
18
|
},
|
package/lib/client.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TelegramClient } from './endpoint.js';
|
|
2
|
+
import type { TelegramUpdate } from './protocol.js';
|
|
3
|
+
export type TelegramClientEventMap = Record<string, TelegramUpdate>;
|
|
4
|
+
declare module '@zhin.js/feature-kit' {
|
|
5
|
+
interface AdapterClientRegistry {
|
|
6
|
+
readonly telegram: {
|
|
7
|
+
readonly client: TelegramClient;
|
|
8
|
+
readonly events: TelegramClientEventMap;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export declare const telegramClient: import("@zhin.js/adapter").EndpointClientToken<TelegramClient, TelegramClientEventMap>;
|
package/lib/client.js
ADDED
package/lib/endpoint.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
2
|
+
import type { EndpointContentPort, EndpointControl, EndpointSendRequest } from 'zhin.js/adapter';
|
|
3
3
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
4
4
|
import { type MessageRef } from '@zhin.js/im-contract';
|
|
5
5
|
import type { CapabilityId } from 'zhin.js';
|
|
@@ -21,19 +21,57 @@ export type TelegramFetch = (url: string, init?: {
|
|
|
21
21
|
}>;
|
|
22
22
|
export interface TelegramEndpointOptions {
|
|
23
23
|
readonly id: CapabilityId;
|
|
24
|
-
readonly gateway: MessageGateway;
|
|
25
|
-
readonly sideEvents?: SideEventGateway;
|
|
26
24
|
readonly config: ResolvedTelegramConfig;
|
|
27
25
|
readonly http?: HttpHost;
|
|
28
26
|
readonly fetch?: TelegramFetch;
|
|
29
27
|
}
|
|
28
|
+
export interface TelegramClientApi {
|
|
29
|
+
callApi<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
|
|
30
|
+
callApiForm<T = unknown>(method: string, form: FormData): Promise<T>;
|
|
31
|
+
pinMessage(chatId: number, messageId: number): Promise<boolean>;
|
|
32
|
+
unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
|
|
33
|
+
setChatDescription(chatId: number, description: string): Promise<boolean>;
|
|
34
|
+
setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
|
|
35
|
+
getChatMemberCount(chatId: number): Promise<number>;
|
|
36
|
+
getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
|
|
37
|
+
sendStickerMessage(chatId: number, sticker: string): Promise<{
|
|
38
|
+
message_id: number;
|
|
39
|
+
}>;
|
|
40
|
+
setChatPermissionsAll(chatId: number, permissions: Record<string, boolean | undefined>): Promise<boolean>;
|
|
41
|
+
createInviteLink(chatId: number): Promise<string>;
|
|
42
|
+
sendPoll(chatId: number, question: string, options: string[], isAnonymous?: boolean, allowsMultipleAnswers?: boolean): Promise<{
|
|
43
|
+
message_id: number;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
/** Telegram Bot API client carried by message, update and lifecycle events. */
|
|
47
|
+
export declare class TelegramClient implements TelegramClientApi {
|
|
48
|
+
readonly api: TelegramClientApi;
|
|
49
|
+
constructor(api: TelegramClientApi);
|
|
50
|
+
callApi: <T = unknown>(method: string, params?: Record<string, unknown>) => Promise<T>;
|
|
51
|
+
callApiForm: <T = unknown>(method: string, form: FormData) => Promise<T>;
|
|
52
|
+
pinMessage: (chatId: number, messageId: number) => Promise<boolean>;
|
|
53
|
+
unpinMessage: (chatId: number, messageId?: number) => Promise<boolean>;
|
|
54
|
+
setChatDescription: (chatId: number, description: string) => Promise<boolean>;
|
|
55
|
+
setMessageReaction: (chatId: number, messageId: number, reaction: string) => Promise<boolean>;
|
|
56
|
+
getChatMemberCount: (chatId: number) => Promise<number>;
|
|
57
|
+
getChatAdmins: (chatId: number) => Promise<TelegramChatMember[]>;
|
|
58
|
+
sendStickerMessage: (chatId: number, sticker: string) => Promise<{
|
|
59
|
+
message_id: number;
|
|
60
|
+
}>;
|
|
61
|
+
setChatPermissionsAll: (chatId: number, permissions: Record<string, boolean | undefined>) => Promise<boolean>;
|
|
62
|
+
createInviteLink: (chatId: number) => Promise<string>;
|
|
63
|
+
sendPoll: (chatId: number, question: string, options: string[], anonymous?: boolean, multiple?: boolean) => Promise<{
|
|
64
|
+
message_id: number;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
30
67
|
/**
|
|
31
68
|
* Telegram Bot API 无列表类接口(无 getMyChats/getChatMembers),
|
|
32
69
|
* 仅 getChat/getChatMember 按已知 id 单查,不构成列表能力;
|
|
33
70
|
* 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
|
|
34
71
|
*/
|
|
35
|
-
export declare class TelegramEndpoint
|
|
72
|
+
export declare class TelegramEndpoint extends Endpoint<TelegramClient> {
|
|
36
73
|
#private;
|
|
74
|
+
readonly client: TelegramClient;
|
|
37
75
|
readonly control: EndpointControl;
|
|
38
76
|
readonly content: EndpointContentPort;
|
|
39
77
|
constructor(options: TelegramEndpointOptions);
|
package/lib/endpoint.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
1
2
|
/**
|
|
2
3
|
* TelegramEndpoint — lifecycle, outbound, admit, Bot API helpers for agent tools.
|
|
3
4
|
*/
|
|
@@ -6,16 +7,48 @@ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
|
6
7
|
import { runTelegramPollLoop } from './polling.js';
|
|
7
8
|
import { normalizeTelegramChatMember } from './platform-permit.js';
|
|
8
9
|
import { botApiUrl, buildWebhookUrl, formatCallbackContent, formatCallbackSegments, formatInboundContent, formatInboundSegments, formatOutboundPlan, resolveTelegramChannelType, senderDisplayName, telegramInboundConversation, } from './protocol.js';
|
|
9
|
-
import { registerTelegramAgentEndpoint } from './telegram-agent-deps.js';
|
|
10
10
|
import { registerTelegramWebhookRoutes } from './webhook.js';
|
|
11
11
|
const CHAT_MEMBER_CACHE_TTL_MS = 60_000;
|
|
12
12
|
const CHAT_MEMBER_CACHE_MAX = 2_000;
|
|
13
|
+
/** Telegram Bot API client carried by message, update and lifecycle events. */
|
|
14
|
+
export class TelegramClient {
|
|
15
|
+
api;
|
|
16
|
+
constructor(api) {
|
|
17
|
+
this.api = api;
|
|
18
|
+
}
|
|
19
|
+
callApi = (method, params = {}) => this.api.callApi(method, params);
|
|
20
|
+
callApiForm = (method, form) => this.api.callApiForm(method, form);
|
|
21
|
+
pinMessage = (chatId, messageId) => this.api.pinMessage(chatId, messageId);
|
|
22
|
+
unpinMessage = (chatId, messageId) => this.api.unpinMessage(chatId, messageId);
|
|
23
|
+
setChatDescription = (chatId, description) => this.api.setChatDescription(chatId, description);
|
|
24
|
+
setMessageReaction = (chatId, messageId, reaction) => this.api.setMessageReaction(chatId, messageId, reaction);
|
|
25
|
+
getChatMemberCount = (chatId) => this.api.getChatMemberCount(chatId);
|
|
26
|
+
getChatAdmins = (chatId) => this.api.getChatAdmins(chatId);
|
|
27
|
+
sendStickerMessage = (chatId, sticker) => this.api.sendStickerMessage(chatId, sticker);
|
|
28
|
+
setChatPermissionsAll = (chatId, permissions) => this.api.setChatPermissionsAll(chatId, permissions);
|
|
29
|
+
createInviteLink = (chatId) => this.api.createInviteLink(chatId);
|
|
30
|
+
sendPoll = (chatId, question, options, anonymous, multiple) => this.api.sendPoll(chatId, question, options, anonymous, multiple);
|
|
31
|
+
}
|
|
13
32
|
/**
|
|
14
33
|
* Telegram Bot API 无列表类接口(无 getMyChats/getChatMembers),
|
|
15
34
|
* 仅 getChat/getChatMember 按已知 id 单查,不构成列表能力;
|
|
16
35
|
* 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
|
|
17
36
|
*/
|
|
18
|
-
export class TelegramEndpoint {
|
|
37
|
+
export class TelegramEndpoint extends Endpoint {
|
|
38
|
+
client = new TelegramClient({
|
|
39
|
+
callApi: (method, params) => this.callApi(method, params),
|
|
40
|
+
callApiForm: (method, form) => this.callApiForm(method, form),
|
|
41
|
+
pinMessage: (chatId, messageId) => this.pinMessage(chatId, messageId),
|
|
42
|
+
unpinMessage: (chatId, messageId) => this.unpinMessage(chatId, messageId),
|
|
43
|
+
setChatDescription: (chatId, description) => this.setChatDescription(chatId, description),
|
|
44
|
+
setMessageReaction: (chatId, messageId, reaction) => this.setMessageReaction(chatId, messageId, reaction),
|
|
45
|
+
getChatMemberCount: (chatId) => this.getChatMemberCount(chatId),
|
|
46
|
+
getChatAdmins: (chatId) => this.getChatAdmins(chatId),
|
|
47
|
+
sendStickerMessage: (chatId, sticker) => this.sendStickerMessage(chatId, sticker),
|
|
48
|
+
setChatPermissionsAll: (chatId, permissions) => this.setChatPermissionsAll(chatId, permissions),
|
|
49
|
+
createInviteLink: (chatId) => this.createInviteLink(chatId),
|
|
50
|
+
sendPoll: (chatId, question, options, anonymous, multiple) => this.sendPoll(chatId, question, options, anonymous, multiple),
|
|
51
|
+
});
|
|
19
52
|
#logger;
|
|
20
53
|
#options;
|
|
21
54
|
#fetch;
|
|
@@ -24,7 +57,6 @@ export class TelegramEndpoint {
|
|
|
24
57
|
#routeReleases = [];
|
|
25
58
|
#open = false;
|
|
26
59
|
#started = false;
|
|
27
|
-
#unregisterAgent;
|
|
28
60
|
#updateOffset = 0;
|
|
29
61
|
#botUserId;
|
|
30
62
|
#botUsername;
|
|
@@ -36,6 +68,7 @@ export class TelegramEndpoint {
|
|
|
36
68
|
resolve: (reference, context) => this.#resolveContent(reference, context.signal),
|
|
37
69
|
});
|
|
38
70
|
constructor(options) {
|
|
71
|
+
super();
|
|
39
72
|
this.#logger = getAdapterLogger('telegram', options.config.id);
|
|
40
73
|
this.#options = options;
|
|
41
74
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
@@ -61,7 +94,6 @@ export class TelegramEndpoint {
|
|
|
61
94
|
return;
|
|
62
95
|
this.#started = true;
|
|
63
96
|
try {
|
|
64
|
-
this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.id, this);
|
|
65
97
|
const me = await this.callApi('getMe');
|
|
66
98
|
this.#botUserId = me.id;
|
|
67
99
|
this.#botUsername = me.username;
|
|
@@ -128,8 +160,6 @@ export class TelegramEndpoint {
|
|
|
128
160
|
}
|
|
129
161
|
for (const release of this.#routeReleases.splice(0))
|
|
130
162
|
release();
|
|
131
|
-
this.#unregisterAgent?.();
|
|
132
|
-
this.#unregisterAgent = undefined;
|
|
133
163
|
this.#chatMemberCache.clear();
|
|
134
164
|
this.#started = false;
|
|
135
165
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
@@ -243,7 +273,7 @@ export class TelegramEndpoint {
|
|
|
243
273
|
const permit = await this.#resolveGroupSenderPermit(msg);
|
|
244
274
|
// 新 Runtime Message.content 为纯文本:@ 本机只能经 metadata 传递
|
|
245
275
|
const mentioned = this.#isBotMentioned(msg);
|
|
246
|
-
await this
|
|
276
|
+
await this.emit('message.receive', {
|
|
247
277
|
conversation,
|
|
248
278
|
message: { conversation, id: String(msg.message_id) },
|
|
249
279
|
content: formatInboundContent(msg),
|
|
@@ -336,7 +366,7 @@ export class TelegramEndpoint {
|
|
|
336
366
|
const conversation = msg
|
|
337
367
|
? telegramInboundConversation(endpointKey, msg.chat)
|
|
338
368
|
: telegramInboundConversation(endpointKey, { id: query.from.id, type: 'private' });
|
|
339
|
-
void this
|
|
369
|
+
void this.emit('message.receive', {
|
|
340
370
|
conversation,
|
|
341
371
|
message: { conversation, id: query.id },
|
|
342
372
|
content: formatCallbackContent(query),
|
|
@@ -358,6 +388,18 @@ export class TelegramEndpoint {
|
|
|
358
388
|
}
|
|
359
389
|
/** Used by webhook / polling handlers. */
|
|
360
390
|
handleUpdate(update) {
|
|
391
|
+
const eventName = update.message
|
|
392
|
+
? 'message'
|
|
393
|
+
: update.callback_query
|
|
394
|
+
? 'callback_query'
|
|
395
|
+
: 'update';
|
|
396
|
+
void this.emitPlatform(eventName, update).catch((error) => {
|
|
397
|
+
this.#logger.warn(formatCompact({
|
|
398
|
+
op: 'telegram_platform_event_failed',
|
|
399
|
+
event: eventName,
|
|
400
|
+
error: error instanceof Error ? error.message : String(error),
|
|
401
|
+
}));
|
|
402
|
+
});
|
|
361
403
|
if (update.message) {
|
|
362
404
|
this.admit(update.message);
|
|
363
405
|
return;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TelegramEndpoint, type TelegramEndpointOptions, type TelegramFetch, } from './endpoint.js';
|
|
1
|
+
export { TelegramClient, TelegramEndpoint, type TelegramClientApi, 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
|
-
export {
|
|
3
|
+
export { telegramClient, type TelegramClientEventMap } from './client.js';
|
|
4
4
|
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, telegramGroupPermitResolver, } from './platform-permit.js';
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TelegramEndpoint, } from './endpoint.js';
|
|
1
|
+
export { TelegramClient, TelegramEndpoint, } from './endpoint.js';
|
|
2
2
|
export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath, resolveTelegramConfig, senderDisplayName, } from './protocol.js';
|
|
3
|
-
export {
|
|
3
|
+
export { telegramClient } from './client.js';
|
|
4
4
|
export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, telegramGroupPermitResolver, } from './platform-permit.js';
|
package/lib/protocol.d.ts
CHANGED
|
@@ -251,7 +251,7 @@ export declare function resolveTelegramChannelType(chatType: TelegramChat['type'
|
|
|
251
251
|
*/
|
|
252
252
|
export declare function telegramInboundConversation(endpointKey: string, chat: Pick<TelegramChat, 'id' | 'type'>): ConversationRef;
|
|
253
253
|
export declare function senderDisplayName(user?: TelegramUser): string;
|
|
254
|
-
/** Build inbound text for
|
|
254
|
+
/** Build inbound text for OutboundMessageService.receive. */
|
|
255
255
|
export declare function formatInboundContent(msg: TelegramMessage): string;
|
|
256
256
|
export declare function formatCallbackContent(query: TelegramCallbackQuery): string;
|
|
257
257
|
/**
|
package/lib/protocol.js
CHANGED
|
@@ -101,7 +101,7 @@ export function senderDisplayName(user) {
|
|
|
101
101
|
return 'Unknown';
|
|
102
102
|
return user.username || user.first_name || String(user.id);
|
|
103
103
|
}
|
|
104
|
-
/** Build inbound text for
|
|
104
|
+
/** Build inbound text for OutboundMessageService.receive. */
|
|
105
105
|
export function formatInboundContent(msg) {
|
|
106
106
|
if (msg.text)
|
|
107
107
|
return msg.text;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const telegramEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage>>>;
|
|
1
|
+
export declare const telegramEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-telegram",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.1",
|
|
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,20 +32,21 @@
|
|
|
32
32
|
"directory": "plugins/adapters/telegram"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@zhin.js/adapter": "1.1
|
|
36
|
-
"@zhin.js/core": "1.5.
|
|
37
|
-
"@zhin.js/
|
|
35
|
+
"@zhin.js/adapter": "1.2.1",
|
|
36
|
+
"@zhin.js/core": "1.5.14",
|
|
37
|
+
"@zhin.js/feature-kit": "1.0.13",
|
|
38
|
+
"@zhin.js/host-http": "1.0.13",
|
|
38
39
|
"@zhin.js/im-contract": "1.0.4",
|
|
39
|
-
"@zhin.js/logger": "1.0.
|
|
40
|
+
"@zhin.js/logger": "1.0.77"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"zod": "^4.0.0",
|
|
43
|
-
"@zhin.js/adapter": "1.1
|
|
44
|
-
"@zhin.js/agent": "1.1.
|
|
45
|
-
"@zhin.js/command": "1.0.
|
|
46
|
-
"@zhin.js/core": "1.5.
|
|
47
|
-
"@zhin.js/permission": "1.0.
|
|
48
|
-
"zhin.js": "6.0.
|
|
44
|
+
"@zhin.js/adapter": "1.2.1",
|
|
45
|
+
"@zhin.js/agent": "1.1.16",
|
|
46
|
+
"@zhin.js/command": "1.0.16",
|
|
47
|
+
"@zhin.js/core": "1.5.14",
|
|
48
|
+
"@zhin.js/permission": "1.0.4",
|
|
49
|
+
"zhin.js": "6.0.14"
|
|
49
50
|
},
|
|
50
51
|
"peerDependenciesMeta": {
|
|
51
52
|
"@zhin.js/agent": {
|
|
@@ -66,9 +67,9 @@
|
|
|
66
67
|
"typescript": "^6.0.3",
|
|
67
68
|
"vitest": "^4.1.10",
|
|
68
69
|
"zod": "^4.4.3",
|
|
69
|
-
"@zhin.js/agent": "1.1.
|
|
70
|
-
"@zhin.js/host-http": "1.0.
|
|
71
|
-
"zhin.js": "6.0.
|
|
70
|
+
"@zhin.js/agent": "1.1.16",
|
|
71
|
+
"@zhin.js/host-http": "1.0.13",
|
|
72
|
+
"zhin.js": "6.0.14"
|
|
72
73
|
},
|
|
73
74
|
"files": [
|
|
74
75
|
"adapters",
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineEndpointClient } from 'zhin.js/adapter';
|
|
2
|
+
import type { TelegramClient } from './endpoint.js';
|
|
3
|
+
import type { TelegramUpdate } from './protocol.js';
|
|
4
|
+
|
|
5
|
+
export type TelegramClientEventMap = Record<string, TelegramUpdate>;
|
|
6
|
+
|
|
7
|
+
declare module '@zhin.js/feature-kit' {
|
|
8
|
+
interface AdapterClientRegistry {
|
|
9
|
+
readonly telegram: {
|
|
10
|
+
readonly client: TelegramClient;
|
|
11
|
+
readonly events: TelegramClientEventMap;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const telegramClient = defineEndpointClient<TelegramClient, TelegramClientEventMap>('telegram');
|
package/src/endpoint.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
1
2
|
/**
|
|
2
3
|
* TelegramEndpoint — lifecycle, outbound, admit, Bot API helpers for agent tools.
|
|
3
4
|
*/
|
|
4
5
|
import { readFile } from 'node:fs/promises';
|
|
5
|
-
import type { EndpointContentPort, EndpointContentResolveContext, EndpointControl,
|
|
6
|
-
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
6
|
+
import type { EndpointContentPort, EndpointContentResolveContext, EndpointControl, EndpointSendRequest } from 'zhin.js/adapter';
|
|
7
7
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
8
8
|
import {
|
|
9
9
|
type ConversationRef,
|
|
@@ -33,7 +33,6 @@ import {
|
|
|
33
33
|
type TelegramOutboundUpload,
|
|
34
34
|
type TelegramUpdate,
|
|
35
35
|
} from './protocol.js';
|
|
36
|
-
import { registerTelegramAgentEndpoint } from './telegram-agent-deps.js';
|
|
37
36
|
import { registerTelegramWebhookRoutes } from './webhook.js';
|
|
38
37
|
|
|
39
38
|
const CHAT_MEMBER_CACHE_TTL_MS = 60_000;
|
|
@@ -64,13 +63,61 @@ export type TelegramFetch = (
|
|
|
64
63
|
|
|
65
64
|
export interface TelegramEndpointOptions {
|
|
66
65
|
readonly id: CapabilityId;
|
|
67
|
-
readonly gateway: MessageGateway;
|
|
68
|
-
readonly sideEvents?: SideEventGateway;
|
|
69
66
|
readonly config: ResolvedTelegramConfig;
|
|
70
67
|
readonly http?: HttpHost;
|
|
71
68
|
readonly fetch?: TelegramFetch;
|
|
72
69
|
}
|
|
73
70
|
|
|
71
|
+
export interface TelegramClientApi {
|
|
72
|
+
callApi<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
|
|
73
|
+
callApiForm<T = unknown>(method: string, form: FormData): Promise<T>;
|
|
74
|
+
pinMessage(chatId: number, messageId: number): Promise<boolean>;
|
|
75
|
+
unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
|
|
76
|
+
setChatDescription(chatId: number, description: string): Promise<boolean>;
|
|
77
|
+
setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
|
|
78
|
+
getChatMemberCount(chatId: number): Promise<number>;
|
|
79
|
+
getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
|
|
80
|
+
sendStickerMessage(chatId: number, sticker: string): Promise<{ message_id: number }>;
|
|
81
|
+
setChatPermissionsAll(chatId: number, permissions: Record<string, boolean | undefined>): Promise<boolean>;
|
|
82
|
+
createInviteLink(chatId: number): Promise<string>;
|
|
83
|
+
sendPoll(
|
|
84
|
+
chatId: number,
|
|
85
|
+
question: string,
|
|
86
|
+
options: string[],
|
|
87
|
+
isAnonymous?: boolean,
|
|
88
|
+
allowsMultipleAnswers?: boolean,
|
|
89
|
+
): Promise<{ message_id: number }>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Telegram Bot API client carried by message, update and lifecycle events. */
|
|
93
|
+
export class TelegramClient implements TelegramClientApi {
|
|
94
|
+
constructor(readonly api: TelegramClientApi) {}
|
|
95
|
+
callApi = <T = unknown>(method: string, params: Record<string, unknown> = {}) =>
|
|
96
|
+
this.api.callApi<T>(method, params);
|
|
97
|
+
callApiForm = <T = unknown>(method: string, form: FormData) =>
|
|
98
|
+
this.api.callApiForm<T>(method, form);
|
|
99
|
+
pinMessage = (chatId: number, messageId: number) => this.api.pinMessage(chatId, messageId);
|
|
100
|
+
unpinMessage = (chatId: number, messageId?: number) => this.api.unpinMessage(chatId, messageId);
|
|
101
|
+
setChatDescription = (chatId: number, description: string) =>
|
|
102
|
+
this.api.setChatDescription(chatId, description);
|
|
103
|
+
setMessageReaction = (chatId: number, messageId: number, reaction: string) =>
|
|
104
|
+
this.api.setMessageReaction(chatId, messageId, reaction);
|
|
105
|
+
getChatMemberCount = (chatId: number) => this.api.getChatMemberCount(chatId);
|
|
106
|
+
getChatAdmins = (chatId: number) => this.api.getChatAdmins(chatId);
|
|
107
|
+
sendStickerMessage = (chatId: number, sticker: string) =>
|
|
108
|
+
this.api.sendStickerMessage(chatId, sticker);
|
|
109
|
+
setChatPermissionsAll = (chatId: number, permissions: Record<string, boolean | undefined>) =>
|
|
110
|
+
this.api.setChatPermissionsAll(chatId, permissions);
|
|
111
|
+
createInviteLink = (chatId: number) => this.api.createInviteLink(chatId);
|
|
112
|
+
sendPoll = (
|
|
113
|
+
chatId: number,
|
|
114
|
+
question: string,
|
|
115
|
+
options: string[],
|
|
116
|
+
anonymous?: boolean,
|
|
117
|
+
multiple?: boolean,
|
|
118
|
+
) => this.api.sendPoll(chatId, question, options, anonymous, multiple);
|
|
119
|
+
}
|
|
120
|
+
|
|
74
121
|
interface TelegramApiOk<T> {
|
|
75
122
|
readonly ok: true;
|
|
76
123
|
readonly result: T;
|
|
@@ -87,7 +134,24 @@ interface TelegramApiErr {
|
|
|
87
134
|
* 仅 getChat/getChatMember 按已知 id 单查,不构成列表能力;
|
|
88
135
|
* 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
|
|
89
136
|
*/
|
|
90
|
-
export class TelegramEndpoint
|
|
137
|
+
export class TelegramEndpoint extends Endpoint<TelegramClient> {
|
|
138
|
+
readonly client = new TelegramClient({
|
|
139
|
+
callApi: (method, params) => this.callApi(method, params),
|
|
140
|
+
callApiForm: (method, form) => this.callApiForm(method, form),
|
|
141
|
+
pinMessage: (chatId, messageId) => this.pinMessage(chatId, messageId),
|
|
142
|
+
unpinMessage: (chatId, messageId) => this.unpinMessage(chatId, messageId),
|
|
143
|
+
setChatDescription: (chatId, description) => this.setChatDescription(chatId, description),
|
|
144
|
+
setMessageReaction: (chatId, messageId, reaction) =>
|
|
145
|
+
this.setMessageReaction(chatId, messageId, reaction),
|
|
146
|
+
getChatMemberCount: (chatId) => this.getChatMemberCount(chatId),
|
|
147
|
+
getChatAdmins: (chatId) => this.getChatAdmins(chatId),
|
|
148
|
+
sendStickerMessage: (chatId, sticker) => this.sendStickerMessage(chatId, sticker),
|
|
149
|
+
setChatPermissionsAll: (chatId, permissions) =>
|
|
150
|
+
this.setChatPermissionsAll(chatId, permissions),
|
|
151
|
+
createInviteLink: (chatId) => this.createInviteLink(chatId),
|
|
152
|
+
sendPoll: (chatId, question, options, anonymous, multiple) =>
|
|
153
|
+
this.sendPoll(chatId, question, options, anonymous, multiple),
|
|
154
|
+
});
|
|
91
155
|
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
92
156
|
|
|
93
157
|
readonly #options: TelegramEndpointOptions;
|
|
@@ -97,7 +161,6 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
97
161
|
#routeReleases: HttpRouteRegistration[] = [];
|
|
98
162
|
#open = false;
|
|
99
163
|
#started = false;
|
|
100
|
-
#unregisterAgent?: () => void;
|
|
101
164
|
#updateOffset = 0;
|
|
102
165
|
#botUserId?: number;
|
|
103
166
|
#botUsername?: string;
|
|
@@ -110,6 +173,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
110
173
|
});
|
|
111
174
|
|
|
112
175
|
constructor(options: TelegramEndpointOptions) {
|
|
176
|
+
super();
|
|
113
177
|
this.#logger = getAdapterLogger('telegram', options.config.id);
|
|
114
178
|
this.#options = options;
|
|
115
179
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
@@ -140,7 +204,6 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
140
204
|
if (this.#started) return;
|
|
141
205
|
this.#started = true;
|
|
142
206
|
try {
|
|
143
|
-
this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.id, this);
|
|
144
207
|
const me = await this.callApi<{ id?: number; username?: string; first_name?: string }>('getMe');
|
|
145
208
|
this.#botUserId = me.id;
|
|
146
209
|
this.#botUsername = me.username;
|
|
@@ -209,8 +272,6 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
209
272
|
/* poll loop exit */
|
|
210
273
|
}
|
|
211
274
|
for (const release of this.#routeReleases.splice(0)) release();
|
|
212
|
-
this.#unregisterAgent?.();
|
|
213
|
-
this.#unregisterAgent = undefined;
|
|
214
275
|
this.#chatMemberCache.clear();
|
|
215
276
|
this.#started = false;
|
|
216
277
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
@@ -330,7 +391,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
330
391
|
const permit = await this.#resolveGroupSenderPermit(msg);
|
|
331
392
|
// 新 Runtime Message.content 为纯文本:@ 本机只能经 metadata 传递
|
|
332
393
|
const mentioned = this.#isBotMentioned(msg);
|
|
333
|
-
await this
|
|
394
|
+
await this.emit('message.receive', {
|
|
334
395
|
conversation,
|
|
335
396
|
message: { conversation, id: String(msg.message_id) },
|
|
336
397
|
content: formatInboundContent(msg),
|
|
@@ -417,7 +478,7 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
417
478
|
const conversation = msg
|
|
418
479
|
? telegramInboundConversation(endpointKey, msg.chat)
|
|
419
480
|
: telegramInboundConversation(endpointKey, { id: query.from.id, type: 'private' });
|
|
420
|
-
void this
|
|
481
|
+
void this.emit('message.receive', {
|
|
421
482
|
conversation,
|
|
422
483
|
message: { conversation, id: query.id },
|
|
423
484
|
content: formatCallbackContent(query),
|
|
@@ -440,6 +501,18 @@ export class TelegramEndpoint implements EndpointInstance {
|
|
|
440
501
|
|
|
441
502
|
/** Used by webhook / polling handlers. */
|
|
442
503
|
handleUpdate(update: TelegramUpdate): void {
|
|
504
|
+
const eventName = update.message
|
|
505
|
+
? 'message'
|
|
506
|
+
: update.callback_query
|
|
507
|
+
? 'callback_query'
|
|
508
|
+
: 'update';
|
|
509
|
+
void this.emitPlatform(eventName, update).catch((error) => {
|
|
510
|
+
this.#logger.warn(formatCompact({
|
|
511
|
+
op: 'telegram_platform_event_failed',
|
|
512
|
+
event: eventName,
|
|
513
|
+
error: error instanceof Error ? error.message : String(error),
|
|
514
|
+
}));
|
|
515
|
+
});
|
|
443
516
|
if (update.message) {
|
|
444
517
|
this.admit(update.message);
|
|
445
518
|
return;
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export {
|
|
2
|
+
TelegramClient,
|
|
2
3
|
TelegramEndpoint,
|
|
4
|
+
type TelegramClientApi,
|
|
3
5
|
type TelegramEndpointOptions,
|
|
4
6
|
type TelegramFetch,
|
|
5
7
|
} from './endpoint.js';
|
|
@@ -27,13 +29,7 @@ export {
|
|
|
27
29
|
type TelegramWireSegment,
|
|
28
30
|
} from './protocol.js';
|
|
29
31
|
|
|
30
|
-
export {
|
|
31
|
-
getTelegramAgentDeps,
|
|
32
|
-
registerTelegramAgentEndpoint,
|
|
33
|
-
setTelegramAgentDeps,
|
|
34
|
-
type TelegramAgentDeps,
|
|
35
|
-
type TelegramAgentEndpoint,
|
|
36
|
-
} from './telegram-agent-deps.js';
|
|
32
|
+
export { telegramClient, type TelegramClientEventMap } from './client.js';
|
|
37
33
|
|
|
38
34
|
export {
|
|
39
35
|
checkTelegramPlatformPermit,
|
package/src/protocol.ts
CHANGED
|
@@ -358,7 +358,7 @@ export function senderDisplayName(user?: TelegramUser): string {
|
|
|
358
358
|
return user.username || user.first_name || String(user.id);
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
/** Build inbound text for
|
|
361
|
+
/** Build inbound text for OutboundMessageService.receive. */
|
|
362
362
|
export function formatInboundContent(msg: TelegramMessage): string {
|
|
363
363
|
if (msg.text) return msg.text;
|
|
364
364
|
if (msg.caption) return msg.caption;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent tool deps for telegram.
|
|
3
|
-
* Endpoints register themselves on start; tools look up by config name / endpoint id.
|
|
4
|
-
*/
|
|
5
|
-
import type { TelegramChatMember } from './protocol.js';
|
|
6
|
-
export interface TelegramAgentEndpoint {
|
|
7
|
-
pinMessage(chatId: number, messageId: number): Promise<boolean>;
|
|
8
|
-
unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
|
|
9
|
-
setChatDescription(chatId: number, description: string): Promise<boolean>;
|
|
10
|
-
setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
|
|
11
|
-
getChatMemberCount(chatId: number): Promise<number>;
|
|
12
|
-
getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
|
|
13
|
-
sendStickerMessage(chatId: number, sticker: string): Promise<{
|
|
14
|
-
message_id: number;
|
|
15
|
-
}>;
|
|
16
|
-
setChatPermissionsAll(chatId: number, permissions: Record<string, boolean | undefined>): Promise<boolean>;
|
|
17
|
-
createInviteLink(chatId: number): Promise<string>;
|
|
18
|
-
sendPoll(chatId: number, question: string, options: string[], isAnonymous?: boolean, allowsMultipleAnswers?: boolean): Promise<{
|
|
19
|
-
message_id: number;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
export interface TelegramAgentDeps {
|
|
23
|
-
getEndpoint: (endpointKey: string) => TelegramAgentEndpoint;
|
|
24
|
-
}
|
|
25
|
-
export declare function registerTelegramAgentEndpoint(endpointKey: string, endpoint: TelegramAgentEndpoint): () => void;
|
|
26
|
-
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
27
|
-
export declare function setTelegramAgentDeps(deps: TelegramAgentDeps | null): void;
|
|
28
|
-
export declare function getTelegramAgentDeps(): TelegramAgentDeps;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent tool deps for telegram.
|
|
3
|
-
* Endpoints register themselves on start; tools look up by config name / endpoint id.
|
|
4
|
-
*/
|
|
5
|
-
const endpoints = new Map();
|
|
6
|
-
let override = null;
|
|
7
|
-
export function registerTelegramAgentEndpoint(endpointKey, endpoint) {
|
|
8
|
-
endpoints.set(endpointKey, endpoint);
|
|
9
|
-
return () => {
|
|
10
|
-
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
-
endpoints.delete(endpointKey);
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
16
|
-
export function setTelegramAgentDeps(deps) {
|
|
17
|
-
override = deps;
|
|
18
|
-
}
|
|
19
|
-
export function getTelegramAgentDeps() {
|
|
20
|
-
if (override)
|
|
21
|
-
return override;
|
|
22
|
-
return {
|
|
23
|
-
getEndpoint(endpointKey) {
|
|
24
|
-
const registered = endpoints.get(endpointKey);
|
|
25
|
-
if (!registered)
|
|
26
|
-
throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
27
|
-
return registered;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent tool deps for telegram.
|
|
3
|
-
* Endpoints register themselves on start; tools look up by config name / endpoint id.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { TelegramChatMember } from './protocol.js';
|
|
7
|
-
|
|
8
|
-
export interface TelegramAgentEndpoint {
|
|
9
|
-
pinMessage(chatId: number, messageId: number): Promise<boolean>;
|
|
10
|
-
unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
|
|
11
|
-
setChatDescription(chatId: number, description: string): Promise<boolean>;
|
|
12
|
-
setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
|
|
13
|
-
getChatMemberCount(chatId: number): Promise<number>;
|
|
14
|
-
getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
|
|
15
|
-
sendStickerMessage(chatId: number, sticker: string): Promise<{ message_id: number }>;
|
|
16
|
-
setChatPermissionsAll(
|
|
17
|
-
chatId: number,
|
|
18
|
-
permissions: Record<string, boolean | undefined>,
|
|
19
|
-
): Promise<boolean>;
|
|
20
|
-
createInviteLink(chatId: number): Promise<string>;
|
|
21
|
-
sendPoll(
|
|
22
|
-
chatId: number,
|
|
23
|
-
question: string,
|
|
24
|
-
options: string[],
|
|
25
|
-
isAnonymous?: boolean,
|
|
26
|
-
allowsMultipleAnswers?: boolean,
|
|
27
|
-
): Promise<{ message_id: number }>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface TelegramAgentDeps {
|
|
31
|
-
getEndpoint: (endpointKey: string) => TelegramAgentEndpoint;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const endpoints = new Map<string, TelegramAgentEndpoint>();
|
|
35
|
-
let override: TelegramAgentDeps | null = null;
|
|
36
|
-
|
|
37
|
-
export function registerTelegramAgentEndpoint(
|
|
38
|
-
endpointKey: string,
|
|
39
|
-
endpoint: TelegramAgentEndpoint,
|
|
40
|
-
): () => void {
|
|
41
|
-
endpoints.set(endpointKey, endpoint);
|
|
42
|
-
return () => {
|
|
43
|
-
if (endpoints.get(endpointKey) === endpoint) {
|
|
44
|
-
endpoints.delete(endpointKey);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
50
|
-
export function setTelegramAgentDeps(deps: TelegramAgentDeps | null): void {
|
|
51
|
-
override = deps;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function getTelegramAgentDeps(): TelegramAgentDeps {
|
|
55
|
-
if (override) return override;
|
|
56
|
-
return {
|
|
57
|
-
getEndpoint(endpointKey: string): TelegramAgentEndpoint {
|
|
58
|
-
const registered = endpoints.get(endpointKey);
|
|
59
|
-
if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
60
|
-
return registered;
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
}
|