@zhin.js/adapter-telegram 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ import { registerPlatformPermitChecker } from 'zhin.js';
2
+ const ADAPTER = 'telegram';
3
+ export function platformPermit(perm) {
4
+ return `platform(${ADAPTER},${perm})`;
5
+ }
6
+ const FACTORY_PERM_MAP = {
7
+ group_admin: 'chat_administrator',
8
+ group_owner: 'chat_creator',
9
+ };
10
+ export function telegramGroupPermitResolver(logicalPerm) {
11
+ return platformPermit(FACTORY_PERM_MAP[logicalPerm] ?? logicalPerm);
12
+ }
13
+ export function normalizeTelegramChatMember(member) {
14
+ const permissions = [];
15
+ const status = member.status;
16
+ if (status === 'creator') {
17
+ permissions.push('chat_creator', 'chat_administrator', 'restrict_members', 'pin_messages');
18
+ return { role: 'creator', permissions };
19
+ }
20
+ if (status === 'administrator') {
21
+ permissions.push('chat_administrator');
22
+ if (member.can_restrict_members)
23
+ permissions.push('restrict_members');
24
+ if (member.can_pin_messages)
25
+ permissions.push('pin_messages');
26
+ if (member.can_delete_messages)
27
+ permissions.push('delete_messages');
28
+ if (member.can_manage_chat)
29
+ permissions.push('manage_chat');
30
+ return { role: 'administrator', permissions };
31
+ }
32
+ return { role: 'member', permissions };
33
+ }
34
+ function senderPermits(message) {
35
+ const sender = message.$sender;
36
+ return { role: sender.role, permissions: sender.permissions ?? [] };
37
+ }
38
+ export function checkTelegramPlatformPermit(perm, message) {
39
+ const { role, permissions } = senderPermits(message);
40
+ const has = (t) => permissions.includes(t);
41
+ switch (perm) {
42
+ case 'chat_creator':
43
+ return role === 'creator' || has('chat_creator');
44
+ case 'chat_administrator':
45
+ return role === 'creator' || role === 'administrator' || has('chat_administrator');
46
+ case 'restrict_members':
47
+ return has('restrict_members') || role === 'creator';
48
+ case 'pin_messages':
49
+ return has('pin_messages') || role === 'creator';
50
+ case 'manage_chat':
51
+ return has('manage_chat') || role === 'creator';
52
+ default:
53
+ return false;
54
+ }
55
+ }
56
+ export function registerTelegramPlatformPermitChecker() {
57
+ return registerPlatformPermitChecker(ADAPTER, checkTelegramPlatformPermit);
58
+ }
59
+ //# sourceMappingURL=platform-permit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-permit.js","sourceRoot":"","sources":["../src/platform-permit.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,OAAO,GAAG,UAAU,CAAC;AAE3B,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,YAAY,OAAO,IAAI,IAAI,GAAG,CAAC;AACxC,CAAC;AAED,MAAM,gBAAgB,GAA2B;IAC/C,WAAW,EAAE,oBAAoB;IACjC,WAAW,EAAE,cAAc;CAC5B,CAAC;AAEF,MAAM,UAAU,2BAA2B,CAAC,WAAmB;IAC7D,OAAO,cAAc,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,MAM3C;IACC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,WAAW,CAAC,IAAI,CAAC,cAAc,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC;QAC3F,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IAC1C,CAAC;IACD,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;QAC/B,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,oBAAoB;YAAE,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACtE,IAAI,MAAM,CAAC,gBAAgB;YAAE,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,mBAAmB;YAAE,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,eAAe;YAAE,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,aAAa,CAAC,OAAqB;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAoD,CAAC;IAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,IAAY,EAAE,OAAqB;IAC7E,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEnD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,cAAc;YACjB,OAAO,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;QACnD,KAAK,oBAAoB;YACvB,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,eAAe,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC;QACrF,KAAK,kBAAkB;YACrB,OAAO,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC;QACvD,KAAK,cAAc;YACjB,OAAO,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC;QACnD,KAAK,aAAa;YAChB,OAAO,GAAG,CAAC,aAAa,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC;QAClD;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qCAAqC;IACnD,OAAO,6BAA6B,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;AAC7E,CAAC"}
package/lib/types.d.ts CHANGED
@@ -11,7 +11,7 @@ export interface TelegramSenderInfo {
11
11
  isAdmin?: boolean;
12
12
  status?: string;
13
13
  }
14
- export interface TelegramBotConfig {
14
+ export interface TelegramEndpointConfig {
15
15
  context: "telegram";
16
16
  token: string;
17
17
  name: string;
@@ -23,7 +23,7 @@ export interface TelegramBotConfig {
23
23
  };
24
24
  allowedUpdates?: string[];
25
25
  }
26
- export interface TelegramBot {
27
- $config: TelegramBotConfig;
26
+ export interface TelegramEndpoint {
27
+ $config: TelegramEndpointConfig;
28
28
  }
29
29
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjE,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,iBAAiB,CAAC;CAC5B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjE,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,sBAAsB,CAAC;CACjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-telegram",
3
- "version": "3.0.0",
3
+ "version": "4.0.0",
4
4
  "description": "Zhin.js adapter for Telegram",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -35,23 +35,26 @@
35
35
  "telegraf": "^4.16.3"
36
36
  },
37
37
  "devDependencies": {
38
- "@types/node": "^25.9.1",
38
+ "@types/node": "^25.9.2",
39
39
  "@types/react": "^19.2.15",
40
40
  "@types/react-dom": "^19.2.3",
41
41
  "lucide-react": "^1.17.0",
42
42
  "typescript": "^6.0.3",
43
- "@zhin.js/cli": "1.0.88",
44
- "@zhin.js/host-api": "1.0.0",
43
+ "@zhin.js/client": "2.0.3",
44
+ "@zhin.js/cli": "1.0.89",
45
45
  "@zhin.js/contract": "1.0.1",
46
- "zhin.js": "2.0.0"
46
+ "@zhin.js/host-api": "2.0.0",
47
+ "@zhin.js/host-router": "2.0.0",
48
+ "@zhin.js/logger": "0.1.71",
49
+ "zhin.js": "3.0.0"
47
50
  },
48
51
  "peerDependencies": {
49
- "@zhin.js/client": "2.0.2",
52
+ "@zhin.js/client": "2.0.3",
53
+ "@zhin.js/host-api": "2.0.0",
50
54
  "@zhin.js/contract": "1.0.1",
51
- "@zhin.js/host-api": "1.0.0",
52
- "@zhin.js/host-router": "1.0.0",
53
- "@zhin.js/logger": "0.1.70",
54
- "zhin.js": "2.0.0"
55
+ "@zhin.js/host-router": "2.0.0",
56
+ "zhin.js": "3.0.0",
57
+ "@zhin.js/logger": "0.1.71"
55
58
  },
56
59
  "peerDependenciesMeta": {
57
60
  "@zhin.js/client": {
@@ -0,0 +1,24 @@
1
+ # Telegram Platform Permits
2
+
3
+ ## 入站字段
4
+
5
+ 群/超级群消息经 `getChatMember`(TTL 60s)写入:
6
+
7
+ | 字段 | 取值 |
8
+ |------|------|
9
+ | `$sender.role` | `creator` · `administrator` · `member` |
10
+ | `$sender.permissions` | `chat_creator` · `chat_administrator` · `restrict_members` · `pin_messages` · `manage_chat` · … |
11
+
12
+ ## Permit 词汇表
13
+
14
+ | `platform(telegram,…)` | 含义 |
15
+ |------------------------|------|
16
+ | `chat_creator` | 群主 |
17
+ | `chat_administrator` | 管理员 |
18
+ | `restrict_members` | 可禁言成员 |
19
+ | `pin_messages` | 可置顶 |
20
+ | `manage_chat` | 可改群默认权限 |
21
+
22
+ ## 工厂映射
23
+
24
+ `group_admin` → `chat_administrator` · `group_owner` → `chat_creator`
package/src/adapter.ts CHANGED
@@ -5,54 +5,56 @@ import {
5
5
  Adapter,
6
6
  Plugin,
7
7
  } from "zhin.js";
8
- import { TelegramBot } from "./bot.js";
9
- import type { TelegramBotConfig } from "./types.js";
8
+ import { TelegramEndpoint } from "./endpoint.js";
9
+ import type { TelegramEndpointConfig } from "./types.js";
10
+
11
+ export class TelegramAdapter extends Adapter<TelegramEndpoint> {
12
+ static override readonly capabilities = ['inbound', 'outbound'] as const;
10
13
 
11
- export class TelegramAdapter extends Adapter<TelegramBot> {
12
14
  constructor(plugin: Plugin) {
13
15
  super(plugin, "telegram", []);
14
16
  }
15
17
 
16
- createBot(config: TelegramBotConfig): TelegramBot {
17
- return new TelegramBot(this, config);
18
+ createEndpoint(config: TelegramEndpointConfig): TelegramEndpoint {
19
+ return new TelegramEndpoint(this, config);
18
20
  }
19
21
 
20
22
  // ── IGroupManagement 标准群管方法 ──────────────────────────────────
21
23
 
22
- async kickMember(botId: string, sceneId: string, userId: string) {
23
- const bot = this.bots.get(botId);
24
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
25
- return bot.kickMember(Number(sceneId), Number(userId));
24
+ async kickMember(endpointId: string, sceneId: string, userId: string) {
25
+ const endpoint = this.endpoints.get(endpointId);
26
+ if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
27
+ return endpoint.kickMember(Number(sceneId), Number(userId));
26
28
  }
27
29
 
28
- async unbanMember(botId: string, sceneId: string, userId: string) {
29
- const bot = this.bots.get(botId);
30
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
31
- return bot.unbanMember(Number(sceneId), Number(userId));
30
+ async unbanMember(endpointId: string, sceneId: string, userId: string) {
31
+ const endpoint = this.endpoints.get(endpointId);
32
+ if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
33
+ return endpoint.unbanMember(Number(sceneId), Number(userId));
32
34
  }
33
35
 
34
- async muteMember(botId: string, sceneId: string, userId: string, duration = 600) {
35
- const bot = this.bots.get(botId);
36
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
37
- return bot.muteMember(Number(sceneId), Number(userId), duration);
36
+ async muteMember(endpointId: string, sceneId: string, userId: string, duration = 600) {
37
+ const endpoint = this.endpoints.get(endpointId);
38
+ if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
39
+ return endpoint.muteMember(Number(sceneId), Number(userId), duration);
38
40
  }
39
41
 
40
- async setAdmin(botId: string, sceneId: string, userId: string, enable = true) {
41
- const bot = this.bots.get(botId);
42
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
43
- return bot.setAdmin(Number(sceneId), Number(userId), enable);
42
+ async setAdmin(endpointId: string, sceneId: string, userId: string, enable = true) {
43
+ const endpoint = this.endpoints.get(endpointId);
44
+ if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
45
+ return endpoint.setAdmin(Number(sceneId), Number(userId), enable);
44
46
  }
45
47
 
46
- async setGroupName(botId: string, sceneId: string, name: string) {
47
- const bot = this.bots.get(botId);
48
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
49
- return bot.setChatTitle(Number(sceneId), name);
48
+ async setGroupName(endpointId: string, sceneId: string, name: string) {
49
+ const endpoint = this.endpoints.get(endpointId);
50
+ if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
51
+ return endpoint.setChatTitle(Number(sceneId), name);
50
52
  }
51
53
 
52
- async getGroupInfo(botId: string, sceneId: string) {
53
- const bot = this.bots.get(botId);
54
- if (!bot) throw new Error(`Bot ${botId} 不存在`);
55
- return bot.getChatInfo(Number(sceneId));
54
+ async getGroupInfo(endpointId: string, sceneId: string) {
55
+ const endpoint = this.endpoints.get(endpointId);
56
+ if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
57
+ return endpoint.getChatInfo(Number(sceneId));
56
58
  }
57
59
 
58
60
  // ── 生命周期 ───────────────────────────────────────────────────────
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Telegram Bot 实现
2
+ * Telegram Endpoint 实现
3
3
  */
4
4
  import { Telegraf, type Context as TelegrafContext } from "telegraf";
5
5
  import type { Message as TelegramMessage, Update, MessageEntity, ChatMember } from "telegraf/types";
6
6
  import {
7
- Bot,
7
+ Endpoint,
8
8
  Message,
9
9
  SendOptions,
10
10
  SendContent,
@@ -12,10 +12,11 @@ import {
12
12
  segment,
13
13
  type QuotedMessagePayload,
14
14
  } from "zhin.js";
15
- import type { TelegramBotConfig, TelegramSenderInfo } from "./types.js";
15
+ import type { TelegramEndpointConfig, TelegramSenderInfo } from "./types.js";
16
16
  import type { TelegramAdapter } from "./adapter.js";
17
+ import { normalizeTelegramChatMember } from "./platform-permit.js";
17
18
 
18
- export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, TelegramMessage> {
19
+ export class TelegramEndpoint extends Telegraf implements Endpoint<TelegramEndpointConfig, TelegramMessage> {
19
20
  $connected: boolean = false;
20
21
  /** message_id -> chat_id,用于在仅有 message_id 的场景执行 reaction 操作 */
21
22
  private readonly messageChatMap = new Map<string, string>();
@@ -30,7 +31,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
30
31
  return this.$config.name;
31
32
  }
32
33
 
33
- constructor(public adapter: TelegramAdapter, public $config: TelegramBotConfig) {
34
+ constructor(public adapter: TelegramAdapter, public $config: TelegramEndpointConfig) {
34
35
  super($config.token);
35
36
  }
36
37
 
@@ -77,7 +78,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
77
78
  this.$connected = true;
78
79
  const me = await this.telegram.getMe();
79
80
  this.pluginLogger.info(
80
- `Telegram bot ${this.$config.name} connected successfully as @${me.username}`
81
+ `Telegram endpoint ${this.$config.name} connected successfully as @${me.username}`
81
82
  );
82
83
  } catch (error) {
83
84
  this.pluginLogger.error("Failed to connect Telegram bot:", error);
@@ -91,17 +92,52 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
91
92
  (this as unknown as import('node:events').EventEmitter).removeAllListeners();
92
93
  await this.stop();
93
94
  this.$connected = false;
94
- this.pluginLogger.info(`Telegram bot ${this.$config.name} disconnected`);
95
+ this.pluginLogger.info(`Telegram endpoint ${this.$config.name} disconnected`);
95
96
  } catch (error) {
96
97
  this.pluginLogger.error("Error disconnecting Telegram bot:", error);
97
98
  throw error;
98
99
  }
99
100
  }
100
101
 
102
+ private chatMemberCache = new Map<string, { at: number; role?: string; permissions: string[] }>();
103
+
104
+ private async enrichGroupSender(
105
+ message: Message<TelegramMessage>,
106
+ msg: TelegramMessage,
107
+ ): Promise<void> {
108
+ if (message.$channel.type !== "group" || !msg.from?.id) return;
109
+ const chatId = Number(msg.chat.id);
110
+ const userId = msg.from.id;
111
+ const key = `${chatId}:${userId}`;
112
+ const now = Date.now();
113
+ const cached = this.chatMemberCache.get(key);
114
+ if (cached && now - cached.at < 60_000) {
115
+ message.$sender.role = cached.role;
116
+ message.$sender.permissions = cached.permissions;
117
+ return;
118
+ }
119
+ try {
120
+ const member = await this.getChatMember(chatId, userId);
121
+ const normalized = normalizeTelegramChatMember(member as {
122
+ status?: string;
123
+ can_restrict_members?: boolean;
124
+ can_pin_messages?: boolean;
125
+ can_delete_messages?: boolean;
126
+ can_manage_chat?: boolean;
127
+ });
128
+ this.chatMemberCache.set(key, { at: now, ...normalized });
129
+ message.$sender.role = normalized.role;
130
+ message.$sender.permissions = normalized.permissions;
131
+ } catch {
132
+ // 保守拒绝:无角色快照
133
+ }
134
+ }
135
+
101
136
  private async handleTelegramMessage(ctx: TelegrafContext): Promise<void> {
102
137
  if (!ctx.message) return;
103
138
 
104
139
  const message = this.$formatMessage(ctx.message as TelegramMessage);
140
+ await this.enrichGroupSender(message, ctx.message as TelegramMessage);
105
141
  this.adapter.emit("message.receive", message);
106
142
  this.pluginLogger.debug(
107
143
  `${this.$config.name} recv ${message.$channel.type}(${message.$channel.id}): ${segment.raw(message.$content)}`
@@ -121,7 +157,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
121
157
  const result = Message.from(msg, {
122
158
  $id: msg.message_id.toString(),
123
159
  $adapter: "telegram",
124
- $bot: this.$config.name,
160
+ $endpoint: this.$config.name,
125
161
  $sender: {
126
162
  id: msg.from?.id.toString() || "",
127
163
  name: msg.from?.username || msg.from?.first_name || "Unknown",
@@ -155,7 +191,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
155
191
 
156
192
  return await this.adapter.sendMessage({
157
193
  context: "telegram",
158
- bot: this.$config.name,
194
+ endpoint: this.$config.name,
159
195
  id: channelId,
160
196
  type: channelType,
161
197
  content: content,
@@ -207,7 +243,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
207
243
  const result = Message.from(query, {
208
244
  $id: query.id,
209
245
  $adapter: "telegram",
210
- $bot: this.$config.name,
246
+ $endpoint: this.$config.name,
211
247
  $sender: {
212
248
  id: query.from.id.toString(),
213
249
  name: query.from.username || query.from.first_name,
@@ -648,15 +684,15 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
648
684
  }
649
685
 
650
686
  // If neither media nor text was sent, this is an error
651
- throw new Error("TelegramBot.$sendMessage: No media or text content to send.");
687
+ throw new Error("TelegramEndpoint.$sendMessage: No media or text content to send.");
652
688
  }
653
689
 
654
690
  async $recallMessage(id: string): Promise<void> {
655
691
  // Telegram requires both chat_id and message_id to delete a message
656
- // The Bot interface only provides message_id, making recall impossible
692
+ // The Endpoint interface only provides message_id, making recall impossible
657
693
  // Users should use message.$recall() instead, which has the full context
658
694
  throw new Error(
659
- "TelegramBot.$recallMessage: Message recall not supported without chat_id. " +
695
+ "TelegramEndpoint.$recallMessage: Message recall not supported without chat_id. " +
660
696
  "Use message.$recall() method instead, which contains the required context."
661
697
  );
662
698
  }
@@ -683,7 +719,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
683
719
  async $addReaction(messageId: string, emoji: string): Promise<string | null> {
684
720
  const ref = this.resolveTelegramMessageRef(messageId);
685
721
  if (!ref) {
686
- this.pluginLogger.warn(`Telegram Bot ${this.$id} 无法根据 message_id=${messageId} 定位 chat_id,跳过 addReaction`);
722
+ this.pluginLogger.warn(`Telegram Endpoint ${this.$id} 无法根据 message_id=${messageId} 定位 chat_id,跳过 addReaction`);
687
723
  return null;
688
724
  }
689
725
 
@@ -691,7 +727,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
691
727
  await this.setMessageReaction(ref.chatId, ref.msgId, emoji);
692
728
  return emoji;
693
729
  } catch (error) {
694
- this.pluginLogger.error(`Telegram Bot ${this.$id} 添加 reaction 失败:`, error);
730
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 添加 reaction 失败:`, error);
695
731
  return null;
696
732
  }
697
733
  }
@@ -699,7 +735,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
699
735
  async $removeReaction(messageId: string, _reactionId: string): Promise<void> {
700
736
  const ref = this.resolveTelegramMessageRef(messageId);
701
737
  if (!ref) {
702
- this.pluginLogger.warn(`Telegram Bot ${this.$id} 无法根据 message_id=${messageId} 定位 chat_id,跳过 removeReaction`);
738
+ this.pluginLogger.warn(`Telegram Endpoint ${this.$id} 无法根据 message_id=${messageId} 定位 chat_id,跳过 removeReaction`);
703
739
  return;
704
740
  }
705
741
 
@@ -710,7 +746,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
710
746
  reaction: [],
711
747
  });
712
748
  } catch (error) {
713
- this.pluginLogger.error(`Telegram Bot ${this.$id} 移除 reaction 失败:`, error);
749
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 移除 reaction 失败:`, error);
714
750
  }
715
751
  }
716
752
  // ==================== 群组管理 API ====================
@@ -724,10 +760,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
724
760
  async kickMember(chatId: number, userId: number, untilDate?: number): Promise<boolean> {
725
761
  try {
726
762
  await this.telegram.banChatMember(chatId, userId, untilDate);
727
- this.pluginLogger.info(`Telegram Bot ${this.$id} 踢出用户 ${userId} 从聊天 ${chatId}`);
763
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 踢出用户 ${userId} 从聊天 ${chatId}`);
728
764
  return true;
729
765
  } catch (error) {
730
- this.pluginLogger.error(`Telegram Bot ${this.$id} 踢出用户失败:`, error);
766
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 踢出用户失败:`, error);
731
767
  throw error;
732
768
  }
733
769
  }
@@ -740,10 +776,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
740
776
  async unbanMember(chatId: number, userId: number): Promise<boolean> {
741
777
  try {
742
778
  await this.telegram.unbanChatMember(chatId, userId, { only_if_banned: true });
743
- this.pluginLogger.info(`Telegram Bot ${this.$id} 解除用户 ${userId} 的封禁(聊天 ${chatId})`);
779
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 解除用户 ${userId} 的封禁(聊天 ${chatId})`);
744
780
  return true;
745
781
  } catch (error) {
746
- this.pluginLogger.error(`Telegram Bot ${this.$id} 解除封禁失败:`, error);
782
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 解除封禁失败:`, error);
747
783
  throw error;
748
784
  }
749
785
  }
@@ -770,10 +806,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
770
806
  permissions,
771
807
  until_date: untilDate,
772
808
  });
773
- this.pluginLogger.info(`Telegram Bot ${this.$id} 限制用户 ${userId} 权限(聊天 ${chatId})`);
809
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 限制用户 ${userId} 权限(聊天 ${chatId})`);
774
810
  return true;
775
811
  } catch (error) {
776
- this.pluginLogger.error(`Telegram Bot ${this.$id} 限制权限失败:`, error);
812
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 限制权限失败:`, error);
777
813
  throw error;
778
814
  }
779
815
  }
@@ -802,7 +838,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
802
838
  can_add_web_page_previews: true,
803
839
  },
804
840
  });
805
- this.pluginLogger.info(`Telegram Bot ${this.$id} 解除用户 ${userId} 禁言(聊天 ${chatId})`);
841
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 解除用户 ${userId} 禁言(聊天 ${chatId})`);
806
842
  } else {
807
843
  const untilDate = Math.floor(Date.now() / 1000) + duration;
808
844
  await this.telegram.restrictChatMember(chatId, userId, {
@@ -820,11 +856,11 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
820
856
  },
821
857
  until_date: untilDate,
822
858
  });
823
- this.pluginLogger.info(`Telegram Bot ${this.$id} 禁言用户 ${userId} ${duration}秒(聊天 ${chatId})`);
859
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 禁言用户 ${userId} ${duration}秒(聊天 ${chatId})`);
824
860
  }
825
861
  return true;
826
862
  } catch (error) {
827
- this.pluginLogger.error(`Telegram Bot ${this.$id} 禁言操作失败:`, error);
863
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 禁言操作失败:`, error);
828
864
  throw error;
829
865
  }
830
866
  }
@@ -860,10 +896,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
860
896
  can_pin_messages: false,
861
897
  });
862
898
  }
863
- this.pluginLogger.info(`Telegram Bot ${this.$id} ${promote ? '提升' : '降级'}用户 ${userId} 为管理员(聊天 ${chatId})`);
899
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} ${promote ? '提升' : '降级'}用户 ${userId} 为管理员(聊天 ${chatId})`);
864
900
  return true;
865
901
  } catch (error) {
866
- this.pluginLogger.error(`Telegram Bot ${this.$id} 设置管理员失败:`, error);
902
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 设置管理员失败:`, error);
867
903
  throw error;
868
904
  }
869
905
  }
@@ -876,10 +912,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
876
912
  async setChatTitle(chatId: number, title: string): Promise<boolean> {
877
913
  try {
878
914
  await this.telegram.setChatTitle(chatId, title);
879
- this.pluginLogger.info(`Telegram Bot ${this.$id} 设置聊天 ${chatId} 标题为 "${title}"`);
915
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 设置聊天 ${chatId} 标题为 "${title}"`);
880
916
  return true;
881
917
  } catch (error) {
882
- this.pluginLogger.error(`Telegram Bot ${this.$id} 设置标题失败:`, error);
918
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 设置标题失败:`, error);
883
919
  throw error;
884
920
  }
885
921
  }
@@ -892,10 +928,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
892
928
  async setChatDescription(chatId: number, description: string): Promise<boolean> {
893
929
  try {
894
930
  await this.telegram.setChatDescription(chatId, description);
895
- this.pluginLogger.info(`Telegram Bot ${this.$id} 设置聊天 ${chatId} 描述`);
931
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 设置聊天 ${chatId} 描述`);
896
932
  return true;
897
933
  } catch (error) {
898
- this.pluginLogger.error(`Telegram Bot ${this.$id} 设置描述失败:`, error);
934
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 设置描述失败:`, error);
899
935
  throw error;
900
936
  }
901
937
  }
@@ -908,10 +944,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
908
944
  async pinMessage(chatId: number, messageId: number): Promise<boolean> {
909
945
  try {
910
946
  await this.telegram.pinChatMessage(chatId, messageId);
911
- this.pluginLogger.info(`Telegram Bot ${this.$id} 置顶消息 ${messageId}(聊天 ${chatId})`);
947
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 置顶消息 ${messageId}(聊天 ${chatId})`);
912
948
  return true;
913
949
  } catch (error) {
914
- this.pluginLogger.error(`Telegram Bot ${this.$id} 置顶消息失败:`, error);
950
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 置顶消息失败:`, error);
915
951
  throw error;
916
952
  }
917
953
  }
@@ -928,10 +964,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
928
964
  } else {
929
965
  await this.telegram.unpinAllChatMessages(chatId);
930
966
  }
931
- this.pluginLogger.info(`Telegram Bot ${this.$id} 取消置顶消息(聊天 ${chatId})`);
967
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 取消置顶消息(聊天 ${chatId})`);
932
968
  return true;
933
969
  } catch (error) {
934
- this.pluginLogger.error(`Telegram Bot ${this.$id} 取消置顶失败:`, error);
970
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 取消置顶失败:`, error);
935
971
  throw error;
936
972
  }
937
973
  }
@@ -944,7 +980,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
944
980
  try {
945
981
  return await this.telegram.getChat(chatId);
946
982
  } catch (error) {
947
- this.pluginLogger.error(`Telegram Bot ${this.$id} 获取聊天信息失败:`, error);
983
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 获取聊天信息失败:`, error);
948
984
  throw error;
949
985
  }
950
986
  }
@@ -958,7 +994,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
958
994
  try {
959
995
  return await this.telegram.getChatMember(chatId, userId);
960
996
  } catch (error) {
961
- this.pluginLogger.error(`Telegram Bot ${this.$id} 获取成员信息失败:`, error);
997
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 获取成员信息失败:`, error);
962
998
  throw error;
963
999
  }
964
1000
  }
@@ -971,7 +1007,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
971
1007
  try {
972
1008
  return await this.telegram.getChatAdministrators(chatId);
973
1009
  } catch (error) {
974
- this.pluginLogger.error(`Telegram Bot ${this.$id} 获取管理员列表失败:`, error);
1010
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 获取管理员列表失败:`, error);
975
1011
  throw error;
976
1012
  }
977
1013
  }
@@ -984,7 +1020,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
984
1020
  try {
985
1021
  return await this.telegram.getChatMembersCount(chatId);
986
1022
  } catch (error) {
987
- this.pluginLogger.error(`Telegram Bot ${this.$id} 获取成员数量失败:`, error);
1023
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 获取成员数量失败:`, error);
988
1024
  throw error;
989
1025
  }
990
1026
  }
@@ -996,10 +1032,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
996
1032
  async createInviteLink(chatId: number): Promise<string> {
997
1033
  try {
998
1034
  const link = await this.telegram.createChatInviteLink(chatId, {});
999
- this.pluginLogger.info(`Telegram Bot ${this.$id} 创建邀请链接(聊天 ${chatId})`);
1035
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 创建邀请链接(聊天 ${chatId})`);
1000
1036
  return link.invite_link;
1001
1037
  } catch (error) {
1002
- this.pluginLogger.error(`Telegram Bot ${this.$id} 创建邀请链接失败:`, error);
1038
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 创建邀请链接失败:`, error);
1003
1039
  throw error;
1004
1040
  }
1005
1041
  }
@@ -1010,10 +1046,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
1010
1046
  is_anonymous: isAnonymous,
1011
1047
  allows_multiple_answers: allowsMultipleAnswers,
1012
1048
  } as any);
1013
- this.pluginLogger.info(`Telegram Bot ${this.$id} 发送投票到 ${chatId}`);
1049
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 发送投票到 ${chatId}`);
1014
1050
  return result;
1015
1051
  } catch (error) {
1016
- this.pluginLogger.error(`Telegram Bot ${this.$id} 发送投票失败:`, error);
1052
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 发送投票失败:`, error);
1017
1053
  throw error;
1018
1054
  }
1019
1055
  }
@@ -1027,7 +1063,7 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
1027
1063
  });
1028
1064
  return true;
1029
1065
  } catch (error) {
1030
- this.pluginLogger.error(`Telegram Bot ${this.$id} 设置反应失败:`, error);
1066
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 设置反应失败:`, error);
1031
1067
  throw error;
1032
1068
  }
1033
1069
  }
@@ -1035,10 +1071,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
1035
1071
  async sendStickerMessage(chatId: number, sticker: string): Promise<TelegramMessage> {
1036
1072
  try {
1037
1073
  const result = await this.telegram.sendSticker(chatId, sticker);
1038
- this.pluginLogger.info(`Telegram Bot ${this.$id} 发送贴纸到 ${chatId}`);
1074
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 发送贴纸到 ${chatId}`);
1039
1075
  return result;
1040
1076
  } catch (error) {
1041
- this.pluginLogger.error(`Telegram Bot ${this.$id} 发送贴纸失败:`, error);
1077
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 发送贴纸失败:`, error);
1042
1078
  throw error;
1043
1079
  }
1044
1080
  }
@@ -1061,10 +1097,10 @@ export class TelegramBot extends Telegraf implements Bot<TelegramBotConfig, Tele
1061
1097
  }): Promise<boolean> {
1062
1098
  try {
1063
1099
  await this.telegram.setChatPermissions(chatId, permissions);
1064
- this.pluginLogger.info(`Telegram Bot ${this.$id} 设置聊天 ${chatId} 权限`);
1100
+ this.pluginLogger.info(`Telegram Endpoint ${this.$id} 设置聊天 ${chatId} 权限`);
1065
1101
  return true;
1066
1102
  } catch (error) {
1067
- this.pluginLogger.error(`Telegram Bot ${this.$id} 设置聊天权限失败:`, error);
1103
+ this.pluginLogger.error(`Telegram Endpoint ${this.$id} 设置聊天权限失败:`, error);
1068
1104
  throw error;
1069
1105
  }
1070
1106
  }