@overpod/mcp-telegram 1.17.0 → 1.18.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.
@@ -182,7 +182,15 @@ export declare class TelegramService {
182
182
  id: string;
183
183
  name: string;
184
184
  username?: string;
185
+ role: string;
185
186
  }>>;
187
+ getMyRole(chatId: string): Promise<{
188
+ role: string;
189
+ chatId: string;
190
+ chatName: string;
191
+ }>;
192
+ private getParticipantUserId;
193
+ private getParticipantRole;
186
194
  getProfile(userId: string): Promise<{
187
195
  id: string;
188
196
  name: string;
@@ -879,19 +879,99 @@ export class TelegramService {
879
879
  async getChatMembers(chatId, limit = 50) {
880
880
  if (!this.client || !this.connected)
881
881
  throw new Error("Not connected");
882
- const participants = await this.client.getParticipants(chatId, { limit });
883
- const members = [];
884
- for (const p of participants) {
885
- if (p instanceof Api.User) {
886
- const parts = [p.firstName, p.lastName].filter(Boolean);
887
- members.push({
888
- id: p.id.toString(),
882
+ const entity = await this.resolveChat(chatId);
883
+ if (entity instanceof Api.Channel) {
884
+ const result = await this.client.invoke(new Api.channels.GetParticipants({
885
+ channel: entity,
886
+ filter: new Api.ChannelParticipantsRecent(),
887
+ offset: 0,
888
+ limit,
889
+ hash: bigInt.zero,
890
+ }));
891
+ if (!(result instanceof Api.channels.ChannelParticipants))
892
+ return [];
893
+ const userMap = new Map();
894
+ for (const u of result.users) {
895
+ if (u instanceof Api.User)
896
+ userMap.set(u.id.toString(), u);
897
+ }
898
+ return result.participants.map((p) => {
899
+ const userId = this.getParticipantUserId(p);
900
+ const user = userMap.get(userId);
901
+ const parts = user ? [user.firstName, user.lastName].filter(Boolean) : [];
902
+ return {
903
+ id: userId,
889
904
  name: parts.join(" ") || "Unknown",
890
- username: p.username ?? undefined,
891
- });
905
+ username: user?.username ?? undefined,
906
+ role: this.getParticipantRole(p),
907
+ };
908
+ });
909
+ }
910
+ // Basic group — use getParticipants (no role info available)
911
+ const participants = await this.client.getParticipants(entity, { limit });
912
+ return participants
913
+ .filter((p) => p instanceof Api.User)
914
+ .map((p) => {
915
+ const parts = [p.firstName, p.lastName].filter(Boolean);
916
+ return {
917
+ id: p.id.toString(),
918
+ name: parts.join(" ") || "Unknown",
919
+ username: p.username ?? undefined,
920
+ role: "member",
921
+ };
922
+ });
923
+ }
924
+ async getMyRole(chatId) {
925
+ if (!this.client || !this.connected)
926
+ throw new Error("Not connected");
927
+ const entity = await this.resolveChat(chatId);
928
+ const me = await this.getMe();
929
+ if (entity instanceof Api.Channel) {
930
+ const result = await this.client.invoke(new Api.channels.GetParticipant({ channel: entity, participant: new Api.InputUserSelf() }));
931
+ return {
932
+ role: this.getParticipantRole(result.participant),
933
+ chatId: entity.id.toString(),
934
+ chatName: entity.title ?? "Unknown",
935
+ };
936
+ }
937
+ if (entity instanceof Api.Chat) {
938
+ // Basic group — check if creator
939
+ if (entity.creator) {
940
+ return { role: "creator", chatId: entity.id.toString(), chatName: entity.title ?? "Unknown" };
892
941
  }
942
+ if (entity.adminRights) {
943
+ return { role: "admin", chatId: entity.id.toString(), chatName: entity.title ?? "Unknown" };
944
+ }
945
+ return { role: "member", chatId: entity.id.toString(), chatName: entity.title ?? "Unknown" };
893
946
  }
894
- return members;
947
+ if (entity instanceof Api.User) {
948
+ return { role: "user", chatId: entity.id.toString(), chatName: me.username ?? "self" };
949
+ }
950
+ return { role: "unknown", chatId: chatId, chatName: "Unknown" };
951
+ }
952
+ getParticipantUserId(p) {
953
+ if (p instanceof Api.ChannelParticipantCreator)
954
+ return p.userId.toString();
955
+ if (p instanceof Api.ChannelParticipantAdmin)
956
+ return p.userId.toString();
957
+ if (p instanceof Api.ChannelParticipantSelf)
958
+ return p.userId.toString();
959
+ if (p instanceof Api.ChannelParticipantBanned)
960
+ return p.peer?.userId?.toString() ?? "0";
961
+ if (p instanceof Api.ChannelParticipant)
962
+ return p.userId.toString();
963
+ return "0";
964
+ }
965
+ getParticipantRole(p) {
966
+ if (p instanceof Api.ChannelParticipantCreator)
967
+ return "creator";
968
+ if (p instanceof Api.ChannelParticipantAdmin)
969
+ return "admin";
970
+ if (p instanceof Api.ChannelParticipantBanned)
971
+ return "banned";
972
+ if (p instanceof Api.ChannelParticipantLeft)
973
+ return "left";
974
+ return "member";
895
975
  }
896
976
  async getProfile(userId) {
897
977
  if (!this.client || !this.connected)
@@ -93,13 +93,36 @@ export function registerChatTools(server, telegram) {
93
93
  return fail(new Error(err));
94
94
  try {
95
95
  const members = await telegram.getChatMembers(chatId, limit);
96
- const text = members.map((m) => `${m.name}${m.username ? ` (@${m.username})` : ""} (${m.id})`).join("\n");
96
+ const text = members
97
+ .map((m) => {
98
+ const role = m.role !== "member" ? ` [${m.role}]` : "";
99
+ return `${m.name}${m.username ? ` (@${m.username})` : ""} (${m.id})${role}`;
100
+ })
101
+ .join("\n");
97
102
  return ok(sanitize(text) || "No members found");
98
103
  }
99
104
  catch (e) {
100
105
  return fail(e);
101
106
  }
102
107
  });
108
+ server.registerTool("telegram-get-my-role", {
109
+ description: "Get the current user's role in a chat (creator, admin, or member)",
110
+ inputSchema: {
111
+ chatId: z.string().describe("Chat ID or username"),
112
+ },
113
+ annotations: READ_ONLY,
114
+ }, async ({ chatId }) => {
115
+ const err = await requireConnection(telegram);
116
+ if (err)
117
+ return fail(new Error(err));
118
+ try {
119
+ const result = await telegram.getMyRole(chatId);
120
+ return ok(`Role: ${result.role}\nChat: ${result.chatName} (${result.chatId})`);
121
+ }
122
+ catch (e) {
123
+ return fail(e);
124
+ }
125
+ });
103
126
  server.registerTool("telegram-create-group", {
104
127
  description: "Create a new Telegram group or supergroup",
105
128
  inputSchema: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overpod/mcp-telegram",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "MCP server for Telegram userbot — messages, media, reactions, polls & more. Built on GramJS/MTProto.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",