@stage-labs/metro 0.1.0-beta.21 → 0.1.0-beta.23
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/dist/cli.js +18 -12
- package/dist/control.js +68 -12
- package/dist/prompt.js +51 -0
- package/package.json +1 -1
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/package.json +1 -1
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/accounts.ts +10 -10
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/actions.ts +1 -1
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/attachments.ts +1 -1
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/format.ts +7 -7
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/group-actions.ts +1 -1
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/index.ts +10 -10
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/station.ts +2 -2
- package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/voice-transcribe.ts +6 -6
- package/runtime/node_modules/@metro-labs/mcp/package.json +2 -2
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-api.ts +14 -8
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/boot.ts +2 -4
- package/runtime/node_modules/@metro-labs/mcp/src/db/materialize.ts +49 -27
- package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +2 -2
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-schemas.ts +6 -6
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-interactive.ts +6 -6
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach.ts +6 -6
- package/runtime/node_modules/@metro-labs/mcp/src/stations/lines.ts +2 -2
- package/runtime/node_modules/@metro-labs/mcp/src/stations/registry.ts +4 -4
- package/runtime/node_modules/@metro-labs/telegram/package.json +5 -2
- package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +47 -86
- package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +210 -251
- package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +66 -107
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/client.ts +4 -4
- package/runtime/node_modules/@metro-labs/telegram/src/format.ts +110 -141
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/group.ts +1 -1
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/history.ts +1 -1
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/inbound.ts +6 -6
- package/runtime/node_modules/@metro-labs/telegram/src/index.ts +35 -92
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/login.ts +20 -20
- package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +65 -151
- package/runtime/node_modules/@metro-labs/telegram/src/members.ts +60 -32
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/reactions.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram/src/station.ts +8 -1
- package/runtime/node_modules/@metro-labs/telegram/src/types.ts +6 -47
- package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -3
- package/runtime/node_modules/@metro-labs/{telegram-user → telegram-bot}/package.json +3 -6
- package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +120 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +295 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +172 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +103 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +166 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +17 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +48 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +3 -0
- package/runtime/runtime.json +1 -1
- package/runtime/node_modules/@metro-labs/telegram-user/src/accounts.ts +0 -81
- package/runtime/node_modules/@metro-labs/telegram-user/src/actions.ts +0 -254
- package/runtime/node_modules/@metro-labs/telegram-user/src/attachments.ts +0 -87
- package/runtime/node_modules/@metro-labs/telegram-user/src/format.ts +0 -141
- package/runtime/node_modules/@metro-labs/telegram-user/src/index.ts +0 -46
- package/runtime/node_modules/@metro-labs/telegram-user/src/media-actions.ts +0 -80
- package/runtime/node_modules/@metro-labs/telegram-user/src/members.ts +0 -75
- package/runtime/node_modules/@metro-labs/telegram-user/src/station.ts +0 -24
- package/runtime/node_modules/@metro-labs/telegram-user/src/types.ts +0 -7
- package/runtime/node_modules/@metro-labs/telegram-user/src/wire.ts +0 -1
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/api-base.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/group.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/members.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/send-files.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/verify.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/voice-speak.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/voice.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/wire.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/normalize.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{telegram → telegram-bot}/src/verify.ts +0 -0
|
@@ -1,295 +1,254 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { respond } from './wire.js';
|
|
1
|
+
import { TrainError } from '@metro-labs/mcp/train-error';
|
|
3
2
|
import { errMsg } from '@metro-labs/mcp/log';
|
|
4
|
-
import { normalizeTelegram } from '@metro-labs/mcp/stations/messaging-normalize';
|
|
5
|
-
import {
|
|
6
|
-
adminMemberList,
|
|
7
|
-
inaccessibleMemberList,
|
|
8
|
-
type TgChatMember,
|
|
9
|
-
} from './members.js';
|
|
10
3
|
import {
|
|
11
4
|
makeStation,
|
|
5
|
+
respond,
|
|
12
6
|
type CallMsg,
|
|
13
7
|
type StationHandler,
|
|
14
8
|
} from '@metro-labs/mcp/stations/station-runtime';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
9
|
+
import { accountFor, accounts, targetOf } from './accounts.js';
|
|
10
|
+
import type { UserClient } from './client.js';
|
|
11
|
+
import { normalizeTelegramUser } from './normalize.js';
|
|
17
12
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
media,
|
|
21
|
-
MEDIA_METHOD_FIELD,
|
|
22
|
-
sendDice,
|
|
23
|
-
sendLocation,
|
|
24
|
-
sendMedia,
|
|
13
|
+
sendAttachments,
|
|
14
|
+
type CanonicalAttachment,
|
|
25
15
|
} from './media-actions.js';
|
|
16
|
+
import { clampLimit, shapeHistory } from './history.js';
|
|
17
|
+
import { fetchMembers, isRestricted, restrictedMemberList } from './members.js';
|
|
18
|
+
import {
|
|
19
|
+
groupAddMembers,
|
|
20
|
+
groupCreate,
|
|
21
|
+
groupInviteLink,
|
|
22
|
+
groupRemoveMembers,
|
|
23
|
+
} from './group.js';
|
|
24
|
+
|
|
25
|
+
type Args = Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
interface Resolved {
|
|
28
|
+
accountId: string;
|
|
29
|
+
client: UserClient;
|
|
30
|
+
chatId: number;
|
|
31
|
+
topicId?: number;
|
|
32
|
+
}
|
|
26
33
|
|
|
34
|
+
type ClientFor = (accountId: string) => UserClient;
|
|
27
35
|
|
|
36
|
+
function str(v: unknown): string | undefined {
|
|
37
|
+
return typeof v === 'string' ? v : undefined;
|
|
38
|
+
}
|
|
28
39
|
|
|
40
|
+
function lineOfArgs(args: Args): string {
|
|
41
|
+
const line = str(args.line);
|
|
42
|
+
if (!line) throw new TrainError('bad_request', 'missing line');
|
|
43
|
+
return line;
|
|
44
|
+
}
|
|
29
45
|
|
|
30
|
-
|
|
46
|
+
function resolve(args: Args, clientFor: ClientFor): Resolved {
|
|
47
|
+
const line = lineOfArgs(args);
|
|
48
|
+
const target = targetOf(line);
|
|
49
|
+
if (!target) throw new TrainError('bad_request', `bad line '${line}'`);
|
|
50
|
+
const accountId = accountFor({ account: str(args.account), line });
|
|
51
|
+
return {
|
|
52
|
+
accountId,
|
|
53
|
+
client: clientFor(accountId),
|
|
54
|
+
chatId: target.chatId,
|
|
55
|
+
...(target.topicId !== undefined ? { topicId: target.topicId } : {}),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
31
58
|
|
|
32
|
-
|
|
33
|
-
async function getMe(
|
|
34
|
-
accountId: string,
|
|
35
|
-
): Promise<{ id: number; username: string | null } | null> {
|
|
36
|
-
const cached = meCache.get(accountId);
|
|
37
|
-
if (cached) return cached;
|
|
59
|
+
async function guard<T>(run: () => Promise<T>): Promise<T> {
|
|
38
60
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
const v = { id: me.id, username: me.username ?? null };
|
|
46
|
-
meCache.set(accountId, v);
|
|
47
|
-
return v;
|
|
48
|
-
} catch {
|
|
49
|
-
return null;
|
|
61
|
+
return await run();
|
|
62
|
+
} catch (e) {
|
|
63
|
+
const msg = errMsg(e);
|
|
64
|
+
if (/FLOOD_WAIT|SLOWMODE_WAIT/i.test(msg))
|
|
65
|
+
throw new TrainError('rate_limited', msg);
|
|
66
|
+
throw new TrainError('telegram_call', msg);
|
|
50
67
|
}
|
|
51
68
|
}
|
|
52
69
|
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const me = await getMe(a.cfg.id);
|
|
57
|
-
const username = me?.username ?? null;
|
|
58
|
-
return {
|
|
59
|
-
id: a.cfg.id,
|
|
60
|
-
handle: username === null ? null : `@${username}`,
|
|
61
|
-
url: username === null ? null : `https://t.me/${username}`,
|
|
62
|
-
owner: a.cfg.owner ?? null,
|
|
63
|
-
botId: me?.id ?? null,
|
|
64
|
-
username,
|
|
65
|
-
};
|
|
66
|
-
}),
|
|
67
|
-
);
|
|
68
|
-
respond(id, { result: { accounts: list } });
|
|
70
|
+
function attachmentsOf(args: Args): CanonicalAttachment[] {
|
|
71
|
+
const raw = args.attachments;
|
|
72
|
+
return Array.isArray(raw) ? (raw as CanonicalAttachment[]) : [];
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
function makeSend(clientFor: ClientFor): StationHandler {
|
|
76
|
+
return async (id, args) => {
|
|
77
|
+
const { accountId, client, chatId, topicId } = resolve(args, clientFor);
|
|
78
|
+
const text = str(args.text) ?? '';
|
|
79
|
+
const replyTo = str(args.replyTo);
|
|
80
|
+
const explicitReplyTo = replyTo ? Number(replyTo) : undefined;
|
|
81
|
+
const replyParam = explicitReplyTo ?? topicId;
|
|
82
|
+
const attachments = attachmentsOf(args);
|
|
83
|
+
if (attachments.length) {
|
|
84
|
+
const sent = await guard(() =>
|
|
85
|
+
sendAttachments({ client, chatId, replyTo: replyParam }, attachments, text),
|
|
86
|
+
);
|
|
87
|
+
respond(id, {
|
|
88
|
+
result: {
|
|
89
|
+
messageId: String(sent.message.id),
|
|
90
|
+
account: accountId,
|
|
91
|
+
attachments: sent.delivered,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const peer = await guard(() => client.tg.resolvePeer(chatId));
|
|
97
|
+
const sent = await guard(() =>
|
|
98
|
+
client.tg.sendText(
|
|
99
|
+
peer,
|
|
100
|
+
text,
|
|
101
|
+
replyParam !== undefined ? { replyTo: replyParam } : undefined,
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
respond(id, {
|
|
105
|
+
result: { messageId: String(sent.id), account: accountId },
|
|
106
|
+
});
|
|
107
|
+
};
|
|
85
108
|
}
|
|
86
109
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
att: WireAttachment,
|
|
99
|
-
caption: string | undefined,
|
|
100
|
-
): Promise<{ accountId: string; message_id: number; kind: string }> {
|
|
101
|
-
const kind = attachmentKind(att);
|
|
102
|
-
const mf = MEDIA_METHOD_FIELD[kind];
|
|
103
|
-
if (!mf) throw new Error(`telegram cannot send a '${kind}' attachment`);
|
|
104
|
-
const sent = await sendMedia(mf.method, mf.field, {
|
|
105
|
-
line: a.line,
|
|
106
|
-
path: attachmentSrc(att),
|
|
107
|
-
caption,
|
|
108
|
-
replyTo: a.replyTo,
|
|
109
|
-
parseMode: a.parseMode,
|
|
110
|
-
account: a.account,
|
|
111
|
-
name: att.name,
|
|
112
|
-
});
|
|
113
|
-
return { ...sent, kind };
|
|
110
|
+
function makeReact(clientFor: ClientFor): StationHandler {
|
|
111
|
+
return async (id, args) => {
|
|
112
|
+
const { accountId, client, chatId } = resolve(args, clientFor);
|
|
113
|
+
const message = Number(str(args.messageId));
|
|
114
|
+
const raw = str(args.emoji);
|
|
115
|
+
const emoji = raw === undefined || raw === '' ? null : raw;
|
|
116
|
+
await guard(() =>
|
|
117
|
+
client.tg.sendReaction({ chatId, message, emoji }),
|
|
118
|
+
);
|
|
119
|
+
respond(id, { result: { ok: true, account: accountId } });
|
|
120
|
+
};
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
function makeEdit(clientFor: ClientFor): StationHandler {
|
|
124
|
+
return async (id, args) => {
|
|
125
|
+
const { accountId, client, chatId } = resolve(args, clientFor);
|
|
126
|
+
const message = Number(str(args.messageId));
|
|
127
|
+
const text = str(args.text) ?? '';
|
|
128
|
+
await guard(() => client.tg.editMessage({ chatId, message, text }));
|
|
129
|
+
respond(id, { result: { ok: true, account: accountId } });
|
|
130
|
+
};
|
|
131
|
+
}
|
|
118
132
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (!att) continue;
|
|
126
|
-
const caption = i === 0 ? text : undefined;
|
|
127
|
-
const sent = await sendOneAttachment(a, att, caption);
|
|
128
|
-
last = sent;
|
|
129
|
-
delivered.push(sent.kind);
|
|
130
|
-
emitOutbound(
|
|
131
|
-
sent.accountId,
|
|
132
|
-
line,
|
|
133
|
-
String(sent.message_id),
|
|
134
|
-
captionLabel(caption, sent.kind),
|
|
135
|
-
replyTo,
|
|
133
|
+
function makeDelete(clientFor: ClientFor): StationHandler {
|
|
134
|
+
return async (id, args) => {
|
|
135
|
+
const { accountId, client, chatId } = resolve(args, clientFor);
|
|
136
|
+
const message = Number(str(args.messageId));
|
|
137
|
+
await guard(() =>
|
|
138
|
+
client.tg.deleteMessagesById(chatId, [message], { revoke: true }),
|
|
136
139
|
);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
respond(id, {
|
|
140
|
-
result: {
|
|
141
|
-
messageId: String(last.message_id),
|
|
142
|
-
account: last.accountId,
|
|
143
|
-
attachments: delivered,
|
|
144
|
-
},
|
|
145
|
-
});
|
|
140
|
+
respond(id, { result: { ok: true, account: accountId } });
|
|
141
|
+
};
|
|
146
142
|
}
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
144
|
+
function makeRead(clientFor: ClientFor): StationHandler {
|
|
145
|
+
return async (id, args) => {
|
|
146
|
+
const { accountId, client, chatId } = resolve(args, clientFor);
|
|
147
|
+
const limit = clampLimit(args.limit);
|
|
148
|
+
const before = str(args.before);
|
|
149
|
+
const beforeId = before ? Number(before) : undefined;
|
|
150
|
+
const offset =
|
|
151
|
+
beforeId !== undefined && Number.isFinite(beforeId)
|
|
152
|
+
? { offset: { id: beforeId, date: 0 } }
|
|
153
|
+
: {};
|
|
154
|
+
const page = await guard(() =>
|
|
155
|
+
client.tg.getHistory(chatId, { limit, ...offset }),
|
|
156
|
+
);
|
|
157
|
+
respond(id, { result: shapeHistory(accountId, chatId, page) });
|
|
158
|
+
};
|
|
163
159
|
}
|
|
164
160
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
161
|
+
function makeListMembers(clientFor: ClientFor): StationHandler {
|
|
162
|
+
return async (id, args) => {
|
|
163
|
+
const { client, chatId } = resolve(args, clientFor);
|
|
164
|
+
const limit = typeof args.limit === 'number' ? args.limit : undefined;
|
|
165
|
+
try {
|
|
166
|
+
respond(id, { result: await fetchMembers(client, chatId, limit) });
|
|
167
|
+
} catch (e) {
|
|
168
|
+
const msg = errMsg(e);
|
|
169
|
+
if (isRestricted(msg)) {
|
|
170
|
+
respond(id, { result: restrictedMemberList(msg) });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
throw e;
|
|
174
|
+
}
|
|
171
175
|
};
|
|
172
|
-
const { accountId, chatId } = targetOf(line, account);
|
|
173
|
-
await tg(accountId, 'setMessageReaction', {
|
|
174
|
-
chat_id: chatId,
|
|
175
|
-
message_id: Number(messageId),
|
|
176
|
-
reaction: emoji ? [{ type: 'emoji', emoji }] : [],
|
|
177
|
-
});
|
|
178
|
-
respond(id, { result: { ok: true, account: accountId } });
|
|
179
176
|
}
|
|
180
177
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
178
|
+
function makeGroupCreate(clientFor: ClientFor): StationHandler {
|
|
179
|
+
return async (id, args) => {
|
|
180
|
+
const accountId = accountFor({ account: str(args.account) });
|
|
181
|
+
const client = clientFor(accountId);
|
|
182
|
+
respond(id, {
|
|
183
|
+
result: await guard(() => groupCreate(client, accountId, args)),
|
|
184
|
+
});
|
|
188
185
|
};
|
|
189
|
-
const { accountId, chatId } = targetOf(line, account);
|
|
190
|
-
await tg(accountId, 'editMessageText', {
|
|
191
|
-
chat_id: chatId,
|
|
192
|
-
message_id: Number(messageId),
|
|
193
|
-
text,
|
|
194
|
-
parse_mode: parseMode,
|
|
195
|
-
});
|
|
196
|
-
respond(id, { result: { ok: true, account: accountId } });
|
|
197
186
|
}
|
|
198
187
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
188
|
+
function makeGroupAdd(clientFor: ClientFor): StationHandler {
|
|
189
|
+
return async (id, args) => {
|
|
190
|
+
const { client, chatId } = resolve(args, clientFor);
|
|
191
|
+
const line = lineOfArgs(args);
|
|
192
|
+
respond(id, {
|
|
193
|
+
result: await guard(() => groupAddMembers(client, chatId, line, args)),
|
|
194
|
+
});
|
|
204
195
|
};
|
|
205
|
-
const { accountId, chatId } = targetOf(line, account);
|
|
206
|
-
await tg(accountId, 'deleteMessage', {
|
|
207
|
-
chat_id: chatId,
|
|
208
|
-
message_id: Number(messageId),
|
|
209
|
-
});
|
|
210
|
-
respond(id, { result: { ok: true, account: accountId } });
|
|
211
196
|
}
|
|
212
197
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
const accountId = accountFor({ account });
|
|
222
|
-
const acct = accounts.get(accountId);
|
|
223
|
-
if (!acct) throw new Error(`unknown account '${accountId}'`);
|
|
224
|
-
const meta = await tg<{ file_path: string }>(accountId, 'getFile', {
|
|
225
|
-
file_id: fileId,
|
|
226
|
-
});
|
|
227
|
-
const res = await fetch(`${acct.fileApi}/${meta.file_path}`, {
|
|
228
|
-
signal: AbortSignal.timeout(60_000),
|
|
229
|
-
});
|
|
230
|
-
if (!res.ok) throw new Error(`telegram download ${res.status}`);
|
|
231
|
-
assertContentLength(res.headers.get('content-length'));
|
|
232
|
-
const data = await res.arrayBuffer();
|
|
233
|
-
const filename = meta.file_path.split('/').pop() ?? `${fileId}.bin`;
|
|
234
|
-
const path = `${outDir}/${Date.now()}-${filename}`;
|
|
235
|
-
await Bun.write(path, data);
|
|
236
|
-
respond(id, {
|
|
237
|
-
result: { path, fileSize: data.byteLength, account: accountId },
|
|
238
|
-
});
|
|
198
|
+
function makeGroupRemove(clientFor: ClientFor): StationHandler {
|
|
199
|
+
return async (id, args) => {
|
|
200
|
+
const { client, chatId } = resolve(args, clientFor);
|
|
201
|
+
const line = lineOfArgs(args);
|
|
202
|
+
respond(id, {
|
|
203
|
+
result: await guard(() => groupRemoveMembers(client, chatId, line, args)),
|
|
204
|
+
});
|
|
205
|
+
};
|
|
239
206
|
}
|
|
240
207
|
|
|
241
|
-
|
|
242
|
-
id
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
let admins: TgChatMember[];
|
|
248
|
-
try {
|
|
249
|
-
admins = await tg<TgChatMember[]>(accountId, 'getChatAdministrators', {
|
|
250
|
-
chat_id: chatId,
|
|
251
|
-
});
|
|
252
|
-
} catch (e) {
|
|
253
|
-
respond(id, { result: inaccessibleMemberList(errMsg(e)) });
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
let total: number | null = null;
|
|
257
|
-
try {
|
|
258
|
-
total = await tg<number>(accountId, 'getChatMemberCount', {
|
|
259
|
-
chat_id: chatId,
|
|
208
|
+
function makeGroupInvite(clientFor: ClientFor): StationHandler {
|
|
209
|
+
return async (id, args) => {
|
|
210
|
+
const { client, chatId } = resolve(args, clientFor);
|
|
211
|
+
const line = lineOfArgs(args);
|
|
212
|
+
respond(id, {
|
|
213
|
+
result: await guard(() => groupInviteLink(client, chatId, line)),
|
|
260
214
|
});
|
|
261
|
-
}
|
|
262
|
-
total = null;
|
|
263
|
-
}
|
|
264
|
-
respond(id, { result: adminMemberList(admins, total) });
|
|
215
|
+
};
|
|
265
216
|
}
|
|
266
217
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
};
|
|
218
|
+
function makeAccounts(clientFor: ClientFor): StationHandler {
|
|
219
|
+
return (id) => {
|
|
220
|
+
const list = [...accounts.values()].map((a) => {
|
|
221
|
+
const me = clientFor(a.id).self();
|
|
222
|
+
const username = me?.username ?? null;
|
|
223
|
+
return {
|
|
224
|
+
id: a.id,
|
|
225
|
+
handle: username === null ? me?.phone ?? null : `@${username}`,
|
|
226
|
+
url: username === null ? null : `https://t.me/${username}`,
|
|
227
|
+
owner: a.owner ?? null,
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
respond(id, { result: { accounts: list } });
|
|
231
|
+
return Promise.resolve();
|
|
232
|
+
};
|
|
233
|
+
}
|
|
284
234
|
|
|
285
|
-
export
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
235
|
+
export function makeHandleCall(
|
|
236
|
+
clientFor: ClientFor,
|
|
237
|
+
): (msg: CallMsg) => Promise<void> {
|
|
238
|
+
return makeStation({
|
|
239
|
+
handlers: {
|
|
240
|
+
accounts: makeAccounts(clientFor),
|
|
241
|
+
send: makeSend(clientFor),
|
|
242
|
+
react: makeReact(clientFor),
|
|
243
|
+
edit: makeEdit(clientFor),
|
|
244
|
+
delete: makeDelete(clientFor),
|
|
245
|
+
read: makeRead(clientFor),
|
|
246
|
+
listMembers: makeListMembers(clientFor),
|
|
247
|
+
groupCreate: makeGroupCreate(clientFor),
|
|
248
|
+
groupAddMembers: makeGroupAdd(clientFor),
|
|
249
|
+
groupRemoveMembers: makeGroupRemove(clientFor),
|
|
250
|
+
groupInviteLink: makeGroupInvite(clientFor),
|
|
251
|
+
},
|
|
252
|
+
normalize: normalizeTelegramUser,
|
|
253
|
+
});
|
|
254
|
+
}
|