@elizaos/plugin-telegram 2.0.0-alpha.4 → 2.0.0-alpha.537
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/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/account-auth-service.d.ts +100 -0
- package/dist/account-auth-service.js +25 -0
- package/dist/account-auth-service.js.map +1 -0
- package/dist/chunk-ORNHNB7E.js +644 -0
- package/dist/chunk-ORNHNB7E.js.map +1 -0
- package/dist/index.d.ts +539 -0
- package/dist/index.js +2319 -14277
- package/dist/index.js.map +1 -95
- package/package.json +27 -23
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
// src/account-auth-service.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { Api, TelegramClient } from "telegram";
|
|
6
|
+
import { StringSession } from "telegram/sessions/index.js";
|
|
7
|
+
var MY_TELEGRAM_URL = "https://my.telegram.org";
|
|
8
|
+
var TELEGRAM_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36";
|
|
9
|
+
var TELEGRAM_ACCOUNT_AUTH_STATUSES = /* @__PURE__ */ new Set([
|
|
10
|
+
"idle",
|
|
11
|
+
"waiting_for_provisioning_code",
|
|
12
|
+
"waiting_for_telegram_code",
|
|
13
|
+
"waiting_for_password",
|
|
14
|
+
"configured",
|
|
15
|
+
"connected",
|
|
16
|
+
"error"
|
|
17
|
+
]);
|
|
18
|
+
function resolveStateDir() {
|
|
19
|
+
return process.env.ELIZA_STATE_DIR?.trim() || path.join(os.homedir(), ".eliza");
|
|
20
|
+
}
|
|
21
|
+
function resolveTelegramAccountSessionDir() {
|
|
22
|
+
const sessionDir = path.join(resolveStateDir(), "telegram-account");
|
|
23
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
24
|
+
return sessionDir;
|
|
25
|
+
}
|
|
26
|
+
function resolveTelegramAccountSessionFile() {
|
|
27
|
+
return path.join(resolveTelegramAccountSessionDir(), "session.txt");
|
|
28
|
+
}
|
|
29
|
+
function resolveTelegramAccountAuthStateFile() {
|
|
30
|
+
return path.join(resolveTelegramAccountSessionDir(), "auth-state.json");
|
|
31
|
+
}
|
|
32
|
+
function loadTelegramAccountSessionString() {
|
|
33
|
+
const sessionFile = resolveTelegramAccountSessionFile();
|
|
34
|
+
if (!fs.existsSync(sessionFile)) {
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
return fs.readFileSync(sessionFile, "utf8").trim();
|
|
38
|
+
}
|
|
39
|
+
function saveTelegramAccountSessionString(session) {
|
|
40
|
+
fs.writeFileSync(resolveTelegramAccountSessionFile(), session, {
|
|
41
|
+
encoding: "utf8",
|
|
42
|
+
mode: 384
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function clearTelegramAccountSession() {
|
|
46
|
+
fs.rmSync(resolveTelegramAccountSessionFile(), { force: true });
|
|
47
|
+
}
|
|
48
|
+
function telegramAccountSessionExists() {
|
|
49
|
+
const sessionFile = resolveTelegramAccountSessionFile();
|
|
50
|
+
return fs.existsSync(sessionFile) && fs.statSync(sessionFile).size > 0;
|
|
51
|
+
}
|
|
52
|
+
function readTrimmedString(value) {
|
|
53
|
+
if (typeof value !== "string") {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const trimmed = value.trim();
|
|
57
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
58
|
+
}
|
|
59
|
+
function readPersistedAccount(value) {
|
|
60
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const record = value;
|
|
64
|
+
const id = readTrimmedString(record.id);
|
|
65
|
+
if (!id) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
id,
|
|
70
|
+
username: readTrimmedString(record.username),
|
|
71
|
+
firstName: readTrimmedString(record.firstName),
|
|
72
|
+
lastName: readTrimmedString(record.lastName),
|
|
73
|
+
phone: readTrimmedString(record.phone)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function readPersistedSnapshot(value) {
|
|
77
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const record = value;
|
|
81
|
+
const status = record.status;
|
|
82
|
+
if (typeof status !== "string" || !TELEGRAM_ACCOUNT_AUTH_STATUSES.has(status)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
status,
|
|
87
|
+
phone: readTrimmedString(record.phone),
|
|
88
|
+
error: typeof record.error === "string" && record.error.trim().length > 0 ? record.error : null,
|
|
89
|
+
isCodeViaApp: record.isCodeViaApp === true,
|
|
90
|
+
account: readPersistedAccount(record.account)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function readPersistedCredentials(value) {
|
|
94
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const record = value;
|
|
98
|
+
const apiIdValue = record.apiId;
|
|
99
|
+
const apiId = typeof apiIdValue === "number" ? apiIdValue : typeof apiIdValue === "string" && apiIdValue.trim().length > 0 ? Number.parseInt(apiIdValue, 10) : Number.NaN;
|
|
100
|
+
const apiHash = readTrimmedString(record.apiHash);
|
|
101
|
+
if (!Number.isInteger(apiId) || apiId <= 0 || !apiHash) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return { apiId, apiHash };
|
|
105
|
+
}
|
|
106
|
+
function readPersistedConnectorConfig(value) {
|
|
107
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const record = value;
|
|
111
|
+
const phone = readTrimmedString(record.phone);
|
|
112
|
+
const appId = readTrimmedString(record.appId);
|
|
113
|
+
const appHash = readTrimmedString(record.appHash);
|
|
114
|
+
const deviceModel = readTrimmedString(record.deviceModel);
|
|
115
|
+
const systemVersion = readTrimmedString(record.systemVersion);
|
|
116
|
+
if (!phone || !appId || !appHash || !deviceModel || !systemVersion) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
phone,
|
|
121
|
+
appId,
|
|
122
|
+
appHash,
|
|
123
|
+
deviceModel,
|
|
124
|
+
systemVersion,
|
|
125
|
+
enabled: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function loadTelegramAccountAuthState() {
|
|
129
|
+
const authStateFile = resolveTelegramAccountAuthStateFile();
|
|
130
|
+
if (!fs.existsSync(authStateFile)) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const parsed = JSON.parse(
|
|
135
|
+
fs.readFileSync(authStateFile, "utf8")
|
|
136
|
+
);
|
|
137
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
const record = parsed;
|
|
141
|
+
const snapshot = readPersistedSnapshot(record.snapshot);
|
|
142
|
+
if (!snapshot) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
snapshot,
|
|
147
|
+
credentials: readPersistedCredentials(record.credentials),
|
|
148
|
+
connectorConfig: readPersistedConnectorConfig(record.connectorConfig),
|
|
149
|
+
provisioningRandomHash: readTrimmedString(record.provisioningRandomHash),
|
|
150
|
+
phoneCodeHash: readTrimmedString(record.phoneCodeHash)
|
|
151
|
+
};
|
|
152
|
+
} catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function saveTelegramAccountAuthState(state) {
|
|
157
|
+
fs.writeFileSync(
|
|
158
|
+
resolveTelegramAccountAuthStateFile(),
|
|
159
|
+
JSON.stringify(state),
|
|
160
|
+
{
|
|
161
|
+
encoding: "utf8",
|
|
162
|
+
mode: 384
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
function clearTelegramAccountAuthState() {
|
|
167
|
+
fs.rmSync(resolveTelegramAccountAuthStateFile(), { force: true });
|
|
168
|
+
}
|
|
169
|
+
function telegramAccountAuthStateExists() {
|
|
170
|
+
const authStateFile = resolveTelegramAccountAuthStateFile();
|
|
171
|
+
return fs.existsSync(authStateFile) && fs.statSync(authStateFile).size > 0;
|
|
172
|
+
}
|
|
173
|
+
function defaultTelegramAccountDeviceModel() {
|
|
174
|
+
return "Eliza Desktop";
|
|
175
|
+
}
|
|
176
|
+
function defaultTelegramAccountSystemVersion() {
|
|
177
|
+
const platform = os.platform();
|
|
178
|
+
const release = os.release();
|
|
179
|
+
if (platform === "darwin") {
|
|
180
|
+
return `macOS ${release}`;
|
|
181
|
+
}
|
|
182
|
+
if (platform === "win32") {
|
|
183
|
+
return `Windows ${release}`;
|
|
184
|
+
}
|
|
185
|
+
return `${platform} ${release}`;
|
|
186
|
+
}
|
|
187
|
+
function mapTelegramAccount(user) {
|
|
188
|
+
return {
|
|
189
|
+
id: user.id.toString(),
|
|
190
|
+
username: typeof user.username === "string" ? user.username : null,
|
|
191
|
+
firstName: typeof user.firstName === "string" ? user.firstName : null,
|
|
192
|
+
lastName: typeof user.lastName === "string" ? user.lastName : null,
|
|
193
|
+
phone: typeof user.phone === "string" ? user.phone : null
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function createTelegramClient(session, credentials, deviceModel, systemVersion) {
|
|
197
|
+
return new TelegramClient(session, credentials.apiId, credentials.apiHash, {
|
|
198
|
+
connectionRetries: 5,
|
|
199
|
+
deviceModel,
|
|
200
|
+
systemVersion
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function isSerializableTelegramSession(session) {
|
|
204
|
+
return typeof session === "object" && session !== null && typeof Reflect.get(session, "save") === "function";
|
|
205
|
+
}
|
|
206
|
+
function serializeSession(client) {
|
|
207
|
+
if (!isSerializableTelegramSession(client.session)) {
|
|
208
|
+
throw new Error("Telegram client session cannot be serialized");
|
|
209
|
+
}
|
|
210
|
+
const savedSession = client.session.save();
|
|
211
|
+
if (typeof savedSession !== "string") {
|
|
212
|
+
throw new Error("Telegram client session did not serialize to a string");
|
|
213
|
+
}
|
|
214
|
+
return savedSession;
|
|
215
|
+
}
|
|
216
|
+
function createAjaxHeaders() {
|
|
217
|
+
return {
|
|
218
|
+
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
|
219
|
+
"User-Agent": TELEGRAM_USER_AGENT,
|
|
220
|
+
Origin: MY_TELEGRAM_URL,
|
|
221
|
+
"X-Requested-With": "XMLHttpRequest"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function createFormHeaders(cookie) {
|
|
225
|
+
return {
|
|
226
|
+
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
|
227
|
+
"User-Agent": TELEGRAM_USER_AGENT,
|
|
228
|
+
...cookie ? { Cookie: cookie } : {}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function extractRandomHash(data) {
|
|
232
|
+
if (!data || typeof data !== "object") {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
const randomHash = data.random_hash;
|
|
236
|
+
return typeof randomHash === "string" && randomHash.trim().length > 0 ? randomHash.trim() : null;
|
|
237
|
+
}
|
|
238
|
+
function getSetCookieHeaders(headers) {
|
|
239
|
+
const withGetSetCookie = headers;
|
|
240
|
+
if (typeof withGetSetCookie.getSetCookie === "function") {
|
|
241
|
+
return withGetSetCookie.getSetCookie();
|
|
242
|
+
}
|
|
243
|
+
const single = headers.get("set-cookie");
|
|
244
|
+
return single ? [single] : [];
|
|
245
|
+
}
|
|
246
|
+
function extractCookieValue(headers, cookieName) {
|
|
247
|
+
const pattern = new RegExp(`(?:^|;\\s*)${cookieName}=([^;]+)`);
|
|
248
|
+
for (const header of getSetCookieHeaders(headers)) {
|
|
249
|
+
const match = header.match(pattern);
|
|
250
|
+
if (match?.[1]) {
|
|
251
|
+
return match[1];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
function extractProvisionedApp(html) {
|
|
257
|
+
const apiIdMatch = html.match(
|
|
258
|
+
/<span class="form-control input-xlarge uneditable-input"[^>]*><strong>(\d+)<\/strong><\/span>/
|
|
259
|
+
);
|
|
260
|
+
const apiHashMatch = html.match(
|
|
261
|
+
/<span class="form-control input-xlarge uneditable-input"[^>]*>([a-f0-9]{32})<\/span>/i
|
|
262
|
+
);
|
|
263
|
+
if (!apiIdMatch?.[1] || !apiHashMatch?.[1]) {
|
|
264
|
+
throw new Error("Failed to parse Telegram app credentials");
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
api_id: Number(apiIdMatch[1]),
|
|
268
|
+
api_hash: apiHashMatch[1]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function extractCreationHash(html) {
|
|
272
|
+
const match = html.match(/<input[^>]*name="hash"[^>]*value="([^"]+)"/i);
|
|
273
|
+
return match?.[1] ?? null;
|
|
274
|
+
}
|
|
275
|
+
async function sendProvisioningCode(phone) {
|
|
276
|
+
const response = await fetch(`${MY_TELEGRAM_URL}/auth/send_password`, {
|
|
277
|
+
method: "POST",
|
|
278
|
+
headers: createAjaxHeaders(),
|
|
279
|
+
body: new URLSearchParams({ phone }),
|
|
280
|
+
signal: AbortSignal.timeout(15e3)
|
|
281
|
+
});
|
|
282
|
+
const text = await response.text();
|
|
283
|
+
if (text.includes("Sorry, too many tries")) {
|
|
284
|
+
throw new Error("Telegram provisioning is rate limited right now");
|
|
285
|
+
}
|
|
286
|
+
const parsed = JSON.parse(text);
|
|
287
|
+
const randomHash = extractRandomHash(parsed);
|
|
288
|
+
if (!randomHash) {
|
|
289
|
+
throw new Error("Telegram provisioning did not return a login token");
|
|
290
|
+
}
|
|
291
|
+
return randomHash;
|
|
292
|
+
}
|
|
293
|
+
async function completeProvisioningLogin(phone, randomHash, code) {
|
|
294
|
+
const response = await fetch(`${MY_TELEGRAM_URL}/auth/login`, {
|
|
295
|
+
method: "POST",
|
|
296
|
+
headers: createAjaxHeaders(),
|
|
297
|
+
body: new URLSearchParams({
|
|
298
|
+
phone,
|
|
299
|
+
random_hash: randomHash,
|
|
300
|
+
password: code
|
|
301
|
+
}),
|
|
302
|
+
redirect: "manual",
|
|
303
|
+
signal: AbortSignal.timeout(15e3)
|
|
304
|
+
});
|
|
305
|
+
const text = await response.text();
|
|
306
|
+
if (text === "Invalid confirmation code!") {
|
|
307
|
+
throw new Error("Invalid Telegram provisioning code");
|
|
308
|
+
}
|
|
309
|
+
if (text !== "true") {
|
|
310
|
+
throw new Error("Telegram provisioning login failed");
|
|
311
|
+
}
|
|
312
|
+
const stelToken = extractCookieValue(response.headers, "stel_token");
|
|
313
|
+
if (!stelToken) {
|
|
314
|
+
throw new Error("Telegram provisioning did not return a session token");
|
|
315
|
+
}
|
|
316
|
+
return stelToken;
|
|
317
|
+
}
|
|
318
|
+
async function getOrCreateProvisionedApp(stelToken) {
|
|
319
|
+
const cookie = `stel_token=${stelToken}`;
|
|
320
|
+
const response = await fetch(`${MY_TELEGRAM_URL}/apps`, {
|
|
321
|
+
headers: {
|
|
322
|
+
Cookie: cookie,
|
|
323
|
+
"User-Agent": TELEGRAM_USER_AGENT
|
|
324
|
+
},
|
|
325
|
+
signal: AbortSignal.timeout(15e3)
|
|
326
|
+
});
|
|
327
|
+
const html = await response.text();
|
|
328
|
+
if (/<title>\s*App configuration\s*<\/title>/i.test(html)) {
|
|
329
|
+
return extractProvisionedApp(html);
|
|
330
|
+
}
|
|
331
|
+
if (!/<title>\s*Create new application\s*<\/title>/i.test(html)) {
|
|
332
|
+
throw new Error("Telegram app provisioning page could not be parsed");
|
|
333
|
+
}
|
|
334
|
+
const creationHash = extractCreationHash(html);
|
|
335
|
+
if (!creationHash) {
|
|
336
|
+
throw new Error("Telegram app provisioning hash missing");
|
|
337
|
+
}
|
|
338
|
+
const createResponse = await fetch(`${MY_TELEGRAM_URL}/apps/create`, {
|
|
339
|
+
method: "POST",
|
|
340
|
+
headers: createFormHeaders(cookie),
|
|
341
|
+
body: new URLSearchParams({
|
|
342
|
+
hash: creationHash,
|
|
343
|
+
app_title: "eliza",
|
|
344
|
+
app_shortname: "eliza",
|
|
345
|
+
app_platform: "other",
|
|
346
|
+
app_url: "",
|
|
347
|
+
app_desc: ""
|
|
348
|
+
}),
|
|
349
|
+
signal: AbortSignal.timeout(15e3)
|
|
350
|
+
});
|
|
351
|
+
return extractProvisionedApp(await createResponse.text());
|
|
352
|
+
}
|
|
353
|
+
var TelegramAccountAuthSession = class {
|
|
354
|
+
snapshot = {
|
|
355
|
+
status: "idle",
|
|
356
|
+
phone: null,
|
|
357
|
+
error: null,
|
|
358
|
+
isCodeViaApp: false,
|
|
359
|
+
account: null
|
|
360
|
+
};
|
|
361
|
+
client = null;
|
|
362
|
+
credentials = null;
|
|
363
|
+
connectorConfig = null;
|
|
364
|
+
provisioningRandomHash = null;
|
|
365
|
+
phoneCodeHash = null;
|
|
366
|
+
deviceModel;
|
|
367
|
+
systemVersion;
|
|
368
|
+
deps;
|
|
369
|
+
constructor(options = {}, deps = {}) {
|
|
370
|
+
this.deviceModel = options.deviceModel?.trim() || defaultTelegramAccountDeviceModel();
|
|
371
|
+
this.systemVersion = options.systemVersion?.trim() || defaultTelegramAccountSystemVersion();
|
|
372
|
+
this.deps = {
|
|
373
|
+
createTelegramClient: deps.createTelegramClient ?? createTelegramClient,
|
|
374
|
+
sendProvisioningCode: deps.sendProvisioningCode ?? sendProvisioningCode,
|
|
375
|
+
completeProvisioningLogin: deps.completeProvisioningLogin ?? completeProvisioningLogin,
|
|
376
|
+
getOrCreateProvisionedApp: deps.getOrCreateProvisionedApp ?? getOrCreateProvisionedApp
|
|
377
|
+
};
|
|
378
|
+
const persisted = loadTelegramAccountAuthState();
|
|
379
|
+
if (persisted) {
|
|
380
|
+
this.snapshot = persisted.snapshot;
|
|
381
|
+
this.credentials = persisted.credentials;
|
|
382
|
+
this.connectorConfig = persisted.connectorConfig;
|
|
383
|
+
this.provisioningRandomHash = persisted.provisioningRandomHash;
|
|
384
|
+
this.phoneCodeHash = persisted.phoneCodeHash;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
getSnapshot() {
|
|
388
|
+
return { ...this.snapshot };
|
|
389
|
+
}
|
|
390
|
+
getResolvedConnectorConfig() {
|
|
391
|
+
return this.connectorConfig ? { ...this.connectorConfig } : null;
|
|
392
|
+
}
|
|
393
|
+
async start(options) {
|
|
394
|
+
const phone = options.phone.trim();
|
|
395
|
+
if (!phone) {
|
|
396
|
+
throw new Error("Telegram phone number is required");
|
|
397
|
+
}
|
|
398
|
+
await this.disconnectClient();
|
|
399
|
+
clearTelegramAccountSession();
|
|
400
|
+
clearTelegramAccountAuthState();
|
|
401
|
+
this.snapshot = {
|
|
402
|
+
status: "idle",
|
|
403
|
+
phone,
|
|
404
|
+
error: null,
|
|
405
|
+
isCodeViaApp: false,
|
|
406
|
+
account: null
|
|
407
|
+
};
|
|
408
|
+
this.credentials = options.credentials;
|
|
409
|
+
this.connectorConfig = null;
|
|
410
|
+
if (this.credentials) {
|
|
411
|
+
await this.beginTelegramLogin();
|
|
412
|
+
return this.getSnapshot();
|
|
413
|
+
}
|
|
414
|
+
this.provisioningRandomHash = await this.deps.sendProvisioningCode(phone);
|
|
415
|
+
this.snapshot.status = "waiting_for_provisioning_code";
|
|
416
|
+
this.persistAuthState();
|
|
417
|
+
return this.getSnapshot();
|
|
418
|
+
}
|
|
419
|
+
async submit(input) {
|
|
420
|
+
switch (this.snapshot.status) {
|
|
421
|
+
case "waiting_for_provisioning_code": {
|
|
422
|
+
const provisioningCode = input.provisioningCode?.trim();
|
|
423
|
+
if (!provisioningCode) {
|
|
424
|
+
throw new Error("Telegram provisioning code is required");
|
|
425
|
+
}
|
|
426
|
+
if (!this.snapshot.phone || !this.provisioningRandomHash) {
|
|
427
|
+
throw new Error("Telegram provisioning session is missing state");
|
|
428
|
+
}
|
|
429
|
+
const stelToken = await this.deps.completeProvisioningLogin(
|
|
430
|
+
this.snapshot.phone,
|
|
431
|
+
this.provisioningRandomHash,
|
|
432
|
+
provisioningCode
|
|
433
|
+
);
|
|
434
|
+
const app = await this.deps.getOrCreateProvisionedApp(stelToken);
|
|
435
|
+
this.credentials = {
|
|
436
|
+
apiId: app.api_id,
|
|
437
|
+
apiHash: app.api_hash
|
|
438
|
+
};
|
|
439
|
+
this.provisioningRandomHash = null;
|
|
440
|
+
await this.beginTelegramLogin();
|
|
441
|
+
return this.getSnapshot();
|
|
442
|
+
}
|
|
443
|
+
case "waiting_for_telegram_code": {
|
|
444
|
+
const telegramCode = input.telegramCode?.trim();
|
|
445
|
+
if (!telegramCode) {
|
|
446
|
+
throw new Error("Telegram login code is required");
|
|
447
|
+
}
|
|
448
|
+
await this.ensureClientConnected();
|
|
449
|
+
await this.completeTelegramCode(telegramCode);
|
|
450
|
+
return this.getSnapshot();
|
|
451
|
+
}
|
|
452
|
+
case "waiting_for_password": {
|
|
453
|
+
const password = input.password ?? "";
|
|
454
|
+
if (!password.trim()) {
|
|
455
|
+
throw new Error("Telegram two-factor password is required");
|
|
456
|
+
}
|
|
457
|
+
await this.ensureClientConnected();
|
|
458
|
+
await this.completePassword(password);
|
|
459
|
+
return this.getSnapshot();
|
|
460
|
+
}
|
|
461
|
+
default:
|
|
462
|
+
throw new Error("Telegram login is not waiting for input");
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async stop() {
|
|
466
|
+
await this.disconnectClient();
|
|
467
|
+
this.provisioningRandomHash = null;
|
|
468
|
+
this.phoneCodeHash = null;
|
|
469
|
+
this.credentials = null;
|
|
470
|
+
this.connectorConfig = null;
|
|
471
|
+
this.snapshot = {
|
|
472
|
+
status: "idle",
|
|
473
|
+
phone: null,
|
|
474
|
+
error: null,
|
|
475
|
+
isCodeViaApp: false,
|
|
476
|
+
account: null
|
|
477
|
+
};
|
|
478
|
+
clearTelegramAccountAuthState();
|
|
479
|
+
}
|
|
480
|
+
async beginTelegramLogin() {
|
|
481
|
+
if (!this.credentials || !this.snapshot.phone) {
|
|
482
|
+
throw new Error("Telegram login credentials are incomplete");
|
|
483
|
+
}
|
|
484
|
+
const session = new StringSession(loadTelegramAccountSessionString());
|
|
485
|
+
this.client = this.deps.createTelegramClient(
|
|
486
|
+
session,
|
|
487
|
+
this.credentials,
|
|
488
|
+
this.deviceModel,
|
|
489
|
+
this.systemVersion
|
|
490
|
+
);
|
|
491
|
+
await this.client.connect();
|
|
492
|
+
this.persistSession();
|
|
493
|
+
if (await this.client.checkAuthorization()) {
|
|
494
|
+
const me = await this.client.getEntity("me");
|
|
495
|
+
await this.finishAuthorized(me);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const sentCode = await this.client.sendCode(
|
|
499
|
+
this.credentials,
|
|
500
|
+
this.snapshot.phone
|
|
501
|
+
);
|
|
502
|
+
this.phoneCodeHash = sentCode.phoneCodeHash;
|
|
503
|
+
this.snapshot.status = "waiting_for_telegram_code";
|
|
504
|
+
this.snapshot.isCodeViaApp = sentCode.isCodeViaApp;
|
|
505
|
+
this.snapshot.error = null;
|
|
506
|
+
this.persistSession();
|
|
507
|
+
this.persistAuthState();
|
|
508
|
+
}
|
|
509
|
+
async completeTelegramCode(code) {
|
|
510
|
+
if (!this.client || !this.credentials || !this.snapshot.phone || !this.phoneCodeHash) {
|
|
511
|
+
throw new Error("Telegram login session is missing state");
|
|
512
|
+
}
|
|
513
|
+
try {
|
|
514
|
+
const result = await this.client.invoke(
|
|
515
|
+
new Api.auth.SignIn({
|
|
516
|
+
phoneNumber: this.snapshot.phone,
|
|
517
|
+
phoneCodeHash: this.phoneCodeHash,
|
|
518
|
+
phoneCode: code
|
|
519
|
+
})
|
|
520
|
+
);
|
|
521
|
+
if (!(result instanceof Api.auth.Authorization)) {
|
|
522
|
+
throw new Error("Telegram returned an unexpected authorization state");
|
|
523
|
+
}
|
|
524
|
+
await this.finishAuthorized(result.user);
|
|
525
|
+
} catch (error) {
|
|
526
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
527
|
+
if (message.includes("SESSION_PASSWORD_NEEDED")) {
|
|
528
|
+
this.snapshot.status = "waiting_for_password";
|
|
529
|
+
this.snapshot.error = null;
|
|
530
|
+
this.persistSession();
|
|
531
|
+
this.persistAuthState();
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
this.snapshot.status = "error";
|
|
535
|
+
this.snapshot.error = message;
|
|
536
|
+
this.persistAuthState();
|
|
537
|
+
throw error;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
async completePassword(password) {
|
|
541
|
+
if (!this.client || !this.credentials) {
|
|
542
|
+
throw new Error("Telegram password login session is missing state");
|
|
543
|
+
}
|
|
544
|
+
try {
|
|
545
|
+
const user = await this.client.signInWithPassword(this.credentials, {
|
|
546
|
+
password: async () => password,
|
|
547
|
+
onError: (error) => {
|
|
548
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
await this.finishAuthorized(user);
|
|
552
|
+
} catch (error) {
|
|
553
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
554
|
+
this.snapshot.status = "error";
|
|
555
|
+
this.snapshot.error = message;
|
|
556
|
+
this.persistAuthState();
|
|
557
|
+
throw error;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
async finishAuthorized(user) {
|
|
561
|
+
if (!this.snapshot.phone || !this.credentials || !this.client) {
|
|
562
|
+
throw new Error("Telegram authorization finished without session state");
|
|
563
|
+
}
|
|
564
|
+
saveTelegramAccountSessionString(serializeSession(this.client));
|
|
565
|
+
this.connectorConfig = {
|
|
566
|
+
phone: this.snapshot.phone,
|
|
567
|
+
appId: String(this.credentials.apiId),
|
|
568
|
+
appHash: this.credentials.apiHash,
|
|
569
|
+
deviceModel: this.deviceModel,
|
|
570
|
+
systemVersion: this.systemVersion,
|
|
571
|
+
enabled: true
|
|
572
|
+
};
|
|
573
|
+
this.snapshot = {
|
|
574
|
+
status: "configured",
|
|
575
|
+
phone: this.snapshot.phone,
|
|
576
|
+
error: null,
|
|
577
|
+
isCodeViaApp: false,
|
|
578
|
+
account: mapTelegramAccount(user)
|
|
579
|
+
};
|
|
580
|
+
clearTelegramAccountAuthState();
|
|
581
|
+
await this.disconnectClient();
|
|
582
|
+
}
|
|
583
|
+
persistSession() {
|
|
584
|
+
if (!this.client) {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const session = serializeSession(this.client);
|
|
588
|
+
if (session.trim().length > 0) {
|
|
589
|
+
saveTelegramAccountSessionString(session);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
persistAuthState() {
|
|
593
|
+
saveTelegramAccountAuthState({
|
|
594
|
+
snapshot: this.snapshot,
|
|
595
|
+
credentials: this.credentials,
|
|
596
|
+
connectorConfig: this.connectorConfig,
|
|
597
|
+
provisioningRandomHash: this.provisioningRandomHash,
|
|
598
|
+
phoneCodeHash: this.phoneCodeHash
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
async disconnectClient() {
|
|
602
|
+
if (!this.client) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
this.persistSession();
|
|
606
|
+
await this.client.disconnect().catch(() => void 0);
|
|
607
|
+
this.client = null;
|
|
608
|
+
}
|
|
609
|
+
async ensureClientConnected() {
|
|
610
|
+
if (this.client) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (!this.credentials) {
|
|
614
|
+
throw new Error("Telegram login session is missing credentials");
|
|
615
|
+
}
|
|
616
|
+
const sessionString = loadTelegramAccountSessionString();
|
|
617
|
+
if (!sessionString.trim()) {
|
|
618
|
+
throw new Error(
|
|
619
|
+
"Telegram login session is missing persisted session data"
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
this.client = this.deps.createTelegramClient(
|
|
623
|
+
new StringSession(sessionString),
|
|
624
|
+
this.credentials,
|
|
625
|
+
this.deviceModel,
|
|
626
|
+
this.systemVersion
|
|
627
|
+
);
|
|
628
|
+
await this.client.connect();
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
export {
|
|
633
|
+
resolveTelegramAccountSessionFile,
|
|
634
|
+
loadTelegramAccountSessionString,
|
|
635
|
+
saveTelegramAccountSessionString,
|
|
636
|
+
clearTelegramAccountSession,
|
|
637
|
+
telegramAccountSessionExists,
|
|
638
|
+
clearTelegramAccountAuthState,
|
|
639
|
+
telegramAccountAuthStateExists,
|
|
640
|
+
defaultTelegramAccountDeviceModel,
|
|
641
|
+
defaultTelegramAccountSystemVersion,
|
|
642
|
+
TelegramAccountAuthSession
|
|
643
|
+
};
|
|
644
|
+
//# sourceMappingURL=chunk-ORNHNB7E.js.map
|