evogram-gramjs 1.0.2 → 1.1.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.
- package/.evogram/{7878190870 → 8539886557}/database.db +0 -0
- package/evogramjs.sqlite +0 -0
- package/package-lock.json +3938 -4
- package/package.json +4 -2
- package/qr-code-qr-auth-1769097743188.png +0 -0
- package/src/commands/AddAccount.command.ts +284 -6
- package/src/commands/index.ts +2 -0
- package/src/sessions/SessionAuth.ts +184 -1
- package/src/sessions/SessionManager.ts +10 -5
- package/lib/EvogramGramJS.d.ts +0 -51
- package/lib/EvogramGramJS.js +0 -99
- package/lib/commands/Accounts.command.d.ts +0 -6
- package/lib/commands/Accounts.command.js +0 -95
- package/lib/commands/AddAccount.command.d.ts +0 -6
- package/lib/commands/AddAccount.command.js +0 -170
- package/lib/commands/index.d.ts +0 -0
- package/lib/commands/index.js +0 -1
- package/lib/commands/managment/DeleteAccount.command.d.ts +0 -0
- package/lib/commands/managment/DeleteAccount.command.js +0 -12
- package/lib/config/database.config.d.ts +0 -26
- package/lib/config/database.config.js +0 -31
- package/lib/entities/Session.entity.d.ts +0 -28
- package/lib/entities/Session.entity.js +0 -71
- package/lib/entities/SessionEventLog.entity.d.ts +0 -22
- package/lib/entities/SessionEventLog.entity.js +0 -50
- package/lib/examples/auth.example.d.ts +0 -10
- package/lib/examples/auth.example.js +0 -126
- package/lib/examples/database.example.d.ts +0 -13
- package/lib/examples/database.example.js +0 -109
- package/lib/examples/usage.example.d.ts +0 -13
- package/lib/examples/usage.example.js +0 -127
- package/lib/index.d.ts +0 -7
- package/lib/index.js +0 -10
- package/lib/services/DatabaseService.d.ts +0 -30
- package/lib/services/DatabaseService.js +0 -93
- package/lib/services/ImageUploadService.d.ts +0 -15
- package/lib/services/ImageUploadService.js +0 -56
- package/lib/sessions/Session.d.ts +0 -13
- package/lib/sessions/Session.js +0 -25
- package/lib/sessions/SessionAuth.d.ts +0 -62
- package/lib/sessions/SessionAuth.js +0 -165
- package/lib/sessions/SessionLogger.d.ts +0 -84
- package/lib/sessions/SessionLogger.js +0 -196
- package/lib/sessions/SessionManager.d.ts +0 -84
- package/lib/sessions/SessionManager.js +0 -199
- package/lib/types/auth.types.d.ts +0 -90
- package/lib/types/auth.types.js +0 -19
- package/lib/types/session.types.d.ts +0 -87
- package/lib/types/session.types.js +0 -21
- package/lib/utils/Deferrer.d.ts +0 -6
- package/lib/utils/Deferrer.js +0 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evogram-gramjs",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"main": "./lib/index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/lodash": "^4.17.21",
|
|
20
20
|
"@types/node": "^24.3.0",
|
|
21
|
-
"
|
|
21
|
+
"@types/qrcode": "^1.5.6",
|
|
22
|
+
"evogram": "2.10.4",
|
|
23
|
+
"qrcode": "^1.5.4",
|
|
22
24
|
"telegram": "^2.26.22"
|
|
23
25
|
},
|
|
24
26
|
"optionalDependencies": {
|
|
Binary file
|
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
import { Command, CommandContext, CommandD, CommandStorageArgument, CommandUpdate, MessageContext } from 'evogram'
|
|
2
|
+
import * as QRCode from 'qrcode'
|
|
2
3
|
import { EvogramGramJS } from '../EvogramGramJS'
|
|
3
4
|
import { AuthState } from '../types/auth.types'
|
|
4
5
|
|
|
5
|
-
@CommandD({ name: 'addaccount', argsMethod: 'parameterized'
|
|
6
|
+
@CommandD({ name: 'addaccount', argsMethod: 'parameterized' })
|
|
6
7
|
export class AddAccountCommand extends Command {
|
|
8
|
+
public async execute(context: CommandContext) {
|
|
9
|
+
//@ts-ignore
|
|
10
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
11
|
+
// prettier-ignore
|
|
12
|
+
text:
|
|
13
|
+
'<blockquote><b>➕ Добавление аккаунта</b></blockquote>\n\n' +
|
|
14
|
+
|
|
15
|
+
'<i>Выберите метод добавления аккаунта</i>',
|
|
16
|
+
parse_mode: 'HTML',
|
|
17
|
+
reply_markup: {
|
|
18
|
+
inline_keyboard: [
|
|
19
|
+
[
|
|
20
|
+
{ text: 'SMS-код', command: AddAccountByCodeCommand },
|
|
21
|
+
{ text: 'QR-код', command: AddAccountByQRCodeCommand },
|
|
22
|
+
],
|
|
23
|
+
[{ text: 'StringSession', command: AddAccountByStringSessionCommand }],
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@CommandD({ name: 'addaccountbycode', argsMethod: 'parameterized' })
|
|
31
|
+
export class AddAccountByCodeCommand extends Command {
|
|
7
32
|
public async execute(
|
|
8
33
|
context: CommandContext,
|
|
9
34
|
@CommandStorageArgument('phone', async ({ context, value }) => {
|
|
10
35
|
if (value) {
|
|
36
|
+
console.log({ value })
|
|
11
37
|
if (!(await context.storage.get('session'))) {
|
|
12
38
|
const session = await EvogramGramJS.sessionManager.addSession({
|
|
13
39
|
sessionId: value,
|
|
@@ -130,7 +156,7 @@ export class AddAccountCommand extends Command {
|
|
|
130
156
|
})
|
|
131
157
|
}
|
|
132
158
|
})
|
|
133
|
-
password: string
|
|
159
|
+
password: string,
|
|
134
160
|
) {
|
|
135
161
|
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
136
162
|
|
|
@@ -138,7 +164,7 @@ export class AddAccountCommand extends Command {
|
|
|
138
164
|
`Вы успешно добавили аккаунт ${await session.client
|
|
139
165
|
.getMe()
|
|
140
166
|
.then((user) => user.username)
|
|
141
|
-
.catch(() => 'unknown')}
|
|
167
|
+
.catch(() => 'unknown')}`,
|
|
142
168
|
)
|
|
143
169
|
await context.storage.clearAll()
|
|
144
170
|
}
|
|
@@ -152,9 +178,9 @@ export class AddAccountCommand extends Command {
|
|
|
152
178
|
await context.edit('⏳').catch(() => {})
|
|
153
179
|
await message.delete().catch(() => {})
|
|
154
180
|
|
|
155
|
-
if (!(await context.storage.get('phone'))) context.redirect(
|
|
156
|
-
else if ((await context.storage.get('stage')) === 'code') context.redirect(
|
|
157
|
-
else if ((await context.storage.get('stage')) === 'password') context.redirect(
|
|
181
|
+
if (!(await context.storage.get('phone'))) context.redirect(AddAccountByCodeCommand, { phone: message.text })
|
|
182
|
+
else if ((await context.storage.get('stage')) === 'code') context.redirect(AddAccountByCodeCommand, { code: message.text })
|
|
183
|
+
else if ((await context.storage.get('stage')) === 'password') context.redirect(AddAccountByCodeCommand, { password: message.text })
|
|
158
184
|
}
|
|
159
185
|
|
|
160
186
|
onError(context: CommandContext, error: Error) {
|
|
@@ -169,3 +195,255 @@ export class AddAccountCommand extends Command {
|
|
|
169
195
|
})
|
|
170
196
|
}
|
|
171
197
|
}
|
|
198
|
+
|
|
199
|
+
@CommandD({ name: 'addaccountbyqrcode', argsMethod: 'parameterized' })
|
|
200
|
+
export class AddAccountByQRCodeCommand extends Command {
|
|
201
|
+
public async execute(
|
|
202
|
+
context: CommandContext,
|
|
203
|
+
@CommandStorageArgument('qrcode', async ({ context, value }) => {
|
|
204
|
+
try {
|
|
205
|
+
if (value) return value
|
|
206
|
+
|
|
207
|
+
let qrcodeMsg: any = null
|
|
208
|
+
const session = (await context.storage.get('session'))
|
|
209
|
+
? EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
210
|
+
: await EvogramGramJS.sessionManager.addSession({
|
|
211
|
+
sessionId: `qr-auth-${Date.now()}`,
|
|
212
|
+
logging: {
|
|
213
|
+
enabled: true,
|
|
214
|
+
logsDirectory: './logs',
|
|
215
|
+
},
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
if (![AuthState.INITIAL, AuthState.WAITING_CODE, undefined].includes(session.auth.state?.stage)) return true
|
|
219
|
+
|
|
220
|
+
await context.storage.set('session', session.sessionId)
|
|
221
|
+
|
|
222
|
+
//@ts-ignore
|
|
223
|
+
await context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
224
|
+
text: '<blockquote><b>➕ Добавление аккаунта через QR-код</b></blockquote>\n\n' + '<i>Генерируем QR-код для входа...</i>\n\n',
|
|
225
|
+
parse_mode: 'HTML',
|
|
226
|
+
}).catch(() => {})
|
|
227
|
+
|
|
228
|
+
// Запускаем авторизацию через QR код
|
|
229
|
+
session.auth.startWithQRCode(async (qrUrl, qrToken, expires) => {
|
|
230
|
+
try {
|
|
231
|
+
// Генерируем QR код как изображение
|
|
232
|
+
const qrCodeBuffer = await QRCode.toBuffer(qrUrl, {
|
|
233
|
+
type: 'png',
|
|
234
|
+
width: 500,
|
|
235
|
+
margin: 2,
|
|
236
|
+
color: {
|
|
237
|
+
dark: '#000000',
|
|
238
|
+
light: '#FFFFFF',
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
const expiresDate = new Date(Date.now() + expires * 1000)
|
|
243
|
+
// prettier-ignore
|
|
244
|
+
const caption =
|
|
245
|
+
`<blockquote><b>📱 QR-код для входа</b></blockquote>\n\n` +
|
|
246
|
+
|
|
247
|
+
'<i>Отсканируйте QR-код в приложении Telegram:</i>\n' +
|
|
248
|
+
'<b>Настройки → Устройства → Подключить устройство</b>\n\n' +
|
|
249
|
+
|
|
250
|
+
`⏳ QR-код действителен до: <code>${expiresDate.toLocaleString('ru-RU')}</code>`;
|
|
251
|
+
|
|
252
|
+
if (context.source.text) {
|
|
253
|
+
qrcodeMsg = await context.sendPhoto(qrCodeBuffer, { caption, parse_mode: 'HTML' })
|
|
254
|
+
} else {
|
|
255
|
+
await context.client.api.editMessageMedia({
|
|
256
|
+
chat_id: context.chat.id,
|
|
257
|
+
message_id: context.message!.id,
|
|
258
|
+
media: {
|
|
259
|
+
type: 'photo',
|
|
260
|
+
media: qrCodeBuffer as any,
|
|
261
|
+
caption,
|
|
262
|
+
parse_mode: 'HTML',
|
|
263
|
+
},
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error('Ошибка при генерации QR-кода:', error)
|
|
268
|
+
throw error
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
return new Promise((resolve) => {
|
|
273
|
+
const interval = setInterval(async () => {
|
|
274
|
+
if (session.auth.state?.stage !== AuthState.WAITING_CODE) {
|
|
275
|
+
if (qrcodeMsg) await qrcodeMsg.delete().catch(() => {})
|
|
276
|
+
|
|
277
|
+
clearInterval(interval)
|
|
278
|
+
resolve(true)
|
|
279
|
+
}
|
|
280
|
+
}, 1000)
|
|
281
|
+
})
|
|
282
|
+
} catch (error) {
|
|
283
|
+
console.error(error)
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
qrcode: string,
|
|
287
|
+
@CommandStorageArgument('password', async ({ context, value }) => {
|
|
288
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
289
|
+
|
|
290
|
+
const isRequired = await session.auth.isRequiredPassword()
|
|
291
|
+
if (!isRequired || value === 'none') return 'none'
|
|
292
|
+
|
|
293
|
+
if (value) {
|
|
294
|
+
const result = await session.auth.setPassword(value)
|
|
295
|
+
|
|
296
|
+
if (result.success) {
|
|
297
|
+
return value
|
|
298
|
+
} else {
|
|
299
|
+
//@ts-ignore
|
|
300
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
301
|
+
text: '<blockquote><b>➕ Добавление аккаунта через QR-код</b></blockquote>\n\n' + '<i>На аккаунте включен 2FA. Отправьте пароль для 2FA в следующем сообщении</i>\n\n' + `<blockquote><b>❗️Произошла ошибка</b></blockquote>\n\n` + result.error,
|
|
302
|
+
parse_mode: 'HTML',
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
return null
|
|
306
|
+
}
|
|
307
|
+
} else {
|
|
308
|
+
await context.storage.set('stage', 'password')
|
|
309
|
+
//@ts-ignore
|
|
310
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
311
|
+
text: '<blockquote><b>➕ Добавление аккаунта через QR-код</b></blockquote>\n\n' + '<i>На аккаунте включен 2FA. Отправьте пароль для 2FA в следующем сообщении</i>',
|
|
312
|
+
parse_mode: 'HTML',
|
|
313
|
+
})
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
password: string,
|
|
317
|
+
) {
|
|
318
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
319
|
+
|
|
320
|
+
const user = await session.client.getMe()
|
|
321
|
+
context.send(`✅ Вы успешно добавили аккаунт @${user.username || user.firstName || 'unknown'}`)
|
|
322
|
+
await context.storage.clearAll()
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@CommandUpdate('message')
|
|
326
|
+
async handleMessage(context: CommandContext, message: MessageContext) {
|
|
327
|
+
if (!message?.text) return
|
|
328
|
+
|
|
329
|
+
await context.edit('⏳').catch(() => {})
|
|
330
|
+
await message.delete().catch(() => {})
|
|
331
|
+
|
|
332
|
+
if ((await context.storage.get('stage')) === 'password') context.redirect(AddAccountByQRCodeCommand, { password: message.text })
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
onError(context: CommandContext, error: Error) {
|
|
336
|
+
//@ts-ignore
|
|
337
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
338
|
+
text: '<blockquote><b>❗️Произошла ошибка при добавлении аккаунта</b></blockquote>\n\n' + error.message,
|
|
339
|
+
parse_mode: 'HTML',
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
@CommandD({ name: 'addaccountbystringsession', argsMethod: 'parameterized' })
|
|
345
|
+
export class AddAccountByStringSessionCommand extends Command {
|
|
346
|
+
public async execute(
|
|
347
|
+
context: CommandContext,
|
|
348
|
+
@CommandStorageArgument('stringSession', async ({ context, value }) => {
|
|
349
|
+
if (value) {
|
|
350
|
+
try {
|
|
351
|
+
// Создаем уникальный ID для сессии
|
|
352
|
+
const sessionId = `string-session-${Date.now()}`
|
|
353
|
+
|
|
354
|
+
// Добавляем сессию через SessionManager с переданной строкой
|
|
355
|
+
const session = await EvogramGramJS.sessionManager.addSession({
|
|
356
|
+
sessionId: sessionId,
|
|
357
|
+
sessionString: value,
|
|
358
|
+
logging: {
|
|
359
|
+
enabled: true,
|
|
360
|
+
logsDirectory: './logs',
|
|
361
|
+
},
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
await context.storage.set('session', session.sessionId)
|
|
365
|
+
|
|
366
|
+
// Проверяем, что сессия валидна и авторизована
|
|
367
|
+
const user = await session.client.getMe()
|
|
368
|
+
|
|
369
|
+
if (!user) {
|
|
370
|
+
throw new Error('Не удалось получить данные пользователя. Проверьте StringSession.')
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Сохраняем сессию в базу данных
|
|
374
|
+
try {
|
|
375
|
+
let avatarBuffer = await session.client.downloadProfilePhoto('me')
|
|
376
|
+
let avatarUrl: string | undefined
|
|
377
|
+
|
|
378
|
+
if (avatarBuffer) {
|
|
379
|
+
const ImageUploadService = (await import('../services/ImageUploadService')).ImageUploadService
|
|
380
|
+
avatarUrl = await ImageUploadService.uploadToImgbox(Buffer.isBuffer(avatarBuffer) ? avatarBuffer : Buffer.from(avatarBuffer)).catch(() => undefined)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
await EvogramGramJS.databaseService.saveSession({
|
|
384
|
+
sessionId: session.sessionId,
|
|
385
|
+
apiId: session.client.apiId,
|
|
386
|
+
apiHash: session.client.apiHash,
|
|
387
|
+
userId: Number(user.id),
|
|
388
|
+
username: user.username,
|
|
389
|
+
firstName: user.firstName,
|
|
390
|
+
lastName: user.lastName,
|
|
391
|
+
phoneNumber: user.phone,
|
|
392
|
+
sessionString: value,
|
|
393
|
+
avatarUrl,
|
|
394
|
+
})
|
|
395
|
+
} catch (saveError) {
|
|
396
|
+
console.error('Ошибка при сохранении сессии в БД:', saveError)
|
|
397
|
+
// Продолжаем выполнение, даже если не удалось сохранить аватар
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return value
|
|
401
|
+
} catch (error: any) {
|
|
402
|
+
context.state.command = undefined
|
|
403
|
+
await context.storage.clearAll()
|
|
404
|
+
|
|
405
|
+
//@ts-ignore
|
|
406
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
407
|
+
text: '<blockquote><b>❗️Произошла ошибка при добавлении аккаунта</b></blockquote>\n\n' + '<i>Проверьте корректность StringSession. Убедитесь, что строка сессии действительна.</i>\n\n' + `<code>${error.message}</code>`,
|
|
408
|
+
parse_mode: 'HTML',
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
return null
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
//@ts-ignore
|
|
415
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
416
|
+
text: '<blockquote><b>➕ Добавление аккаунта через StringSession</b></blockquote>\n\n' + '<i>Отправьте StringSession в следующем сообщении</i>\n\n' + 'ℹ️ StringSession - это строка, которая содержит данные авторизации вашего аккаунта. ' + 'Вы можете получить её через официальную библиотеку Telegram или сторонние инструменты.',
|
|
417
|
+
parse_mode: 'HTML',
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
})
|
|
421
|
+
stringSession: string,
|
|
422
|
+
) {
|
|
423
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
424
|
+
|
|
425
|
+
const user = await session.client.getMe()
|
|
426
|
+
context.send(`✅ Вы успешно добавили аккаунт @${user.username || user.firstName || 'unknown'}`)
|
|
427
|
+
await context.storage.clearAll()
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
@CommandUpdate('message')
|
|
431
|
+
async handleMessage(context: CommandContext, message: MessageContext) {
|
|
432
|
+
if (!message?.text) return
|
|
433
|
+
|
|
434
|
+
await context.edit('⏳').catch(() => {})
|
|
435
|
+
await message.delete().catch(() => {})
|
|
436
|
+
|
|
437
|
+
if (!(await context.storage.get('stringSession'))) {
|
|
438
|
+
context.redirect(AddAccountByStringSessionCommand, { stringSession: message.text })
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
onError(context: CommandContext, error: Error) {
|
|
443
|
+
//@ts-ignore
|
|
444
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
445
|
+
text: '<blockquote><b>❗️Произошла ошибка при добавлении аккаунта</b></blockquote>\n\n' + error.message,
|
|
446
|
+
parse_mode: 'HTML',
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
}
|
package/src/commands/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'events'
|
|
2
|
-
import { TelegramClient } from 'telegram'
|
|
2
|
+
import { Api, TelegramClient } from 'telegram'
|
|
3
3
|
import { EvogramGramJS } from '../EvogramGramJS'
|
|
4
4
|
import { ImageUploadService } from '../services/ImageUploadService'
|
|
5
5
|
import { AuthState } from '../types/auth.types'
|
|
@@ -160,6 +160,189 @@ export class SessionAuth extends EventEmitter {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Начинает авторизацию через QR-код
|
|
165
|
+
*
|
|
166
|
+
* @param onQRCode Callback для обработки QR-кода (получает URL и токен)
|
|
167
|
+
* @returns Promise с результатом авторизации
|
|
168
|
+
*/
|
|
169
|
+
async startWithQRCode(
|
|
170
|
+
onQRCode: (qrUrl: string, qrToken: string, expires: number) => Promise<void>
|
|
171
|
+
): Promise<{ success: boolean; error?: any }> {
|
|
172
|
+
console.log(`[QR-AUTH] Начало метода startWithQRCode для сессии "${this.sessionId}"`)
|
|
173
|
+
console.log(`[QR-AUTH] Текущее состояние state:`, this.state ? 'уже инициализировано' : 'null')
|
|
174
|
+
|
|
175
|
+
if (this.state) throw new Error(`Авторизация для сессии "${this.sessionId}" уже начата`)
|
|
176
|
+
|
|
177
|
+
console.log(`[QR-AUTH] Инициализация state для сессии "${this.sessionId}"`)
|
|
178
|
+
this.state = {
|
|
179
|
+
code: new Deferred<string>(),
|
|
180
|
+
password: new Deferred<string>(),
|
|
181
|
+
isRequiredPassword: false,
|
|
182
|
+
stage: AuthState.INITIAL,
|
|
183
|
+
connect: new Deferred<boolean>(),
|
|
184
|
+
}
|
|
185
|
+
console.log(`[QR-AUTH] State успешно инициализирован:`, {
|
|
186
|
+
stage: this.state.stage,
|
|
187
|
+
isRequiredPassword: this.state.isRequiredPassword,
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
console.log(`[QR-AUTH] Получение API credentials для клиента`)
|
|
192
|
+
const apiCredentials = {
|
|
193
|
+
apiId: this.client.apiId,
|
|
194
|
+
apiHash: this.client.apiHash,
|
|
195
|
+
}
|
|
196
|
+
console.log(`[QR-AUTH] API credentials:`, {
|
|
197
|
+
apiId: apiCredentials.apiId,
|
|
198
|
+
apiHashLength: apiCredentials.apiHash?.length || 0,
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
console.log(`[QR-AUTH] Смена стадии на WAITING_CODE`)
|
|
202
|
+
this.state.stage = AuthState.WAITING_CODE
|
|
203
|
+
console.log(`[QR-AUTH] Текущая стадия:`, this.state.stage)
|
|
204
|
+
|
|
205
|
+
console.log(`[QR-AUTH] Вызов client.signInUserWithQrCode для сессии "${this.sessionId}"`)
|
|
206
|
+
const user = await this.client.signInUserWithQrCode(apiCredentials, {
|
|
207
|
+
qrCode: async (qrCode) => {
|
|
208
|
+
console.log(`[QR-AUTH] Получен QR-код callback для сессии "${this.sessionId}"`)
|
|
209
|
+
console.log(`[QR-AUTH] QR-код объект:`, {
|
|
210
|
+
tokenLength: qrCode.token?.length || 0,
|
|
211
|
+
expires: qrCode.expires,
|
|
212
|
+
expiresDate: new Date(qrCode.expires * 1000).toISOString(),
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
const qrToken = qrCode.token.toString('base64url')
|
|
216
|
+
console.log(`[QR-AUTH] QR token (base64url):`, qrToken)
|
|
217
|
+
|
|
218
|
+
const qrUrl = `tg://login?token=${qrToken}`
|
|
219
|
+
console.log(`[QR-AUTH] QR URL:`, qrUrl)
|
|
220
|
+
|
|
221
|
+
console.log(`[QR-AUTH] Вызов onQRCode callback`)
|
|
222
|
+
await onQRCode(qrUrl, qrToken, qrCode.expires)
|
|
223
|
+
console.log(`[QR-AUTH] onQRCode callback выполнен успешно`)
|
|
224
|
+
},
|
|
225
|
+
password: async (hint) => {
|
|
226
|
+
console.log(`[QR-AUTH] Запрошен пароль для сессии "${this.sessionId}"`)
|
|
227
|
+
console.log(`[QR-AUTH] Password hint:`, hint)
|
|
228
|
+
|
|
229
|
+
this.state.isRequiredPassword = true
|
|
230
|
+
this.state.stage = AuthState.WAITING_PASSWORD
|
|
231
|
+
console.log(`[QR-AUTH] Состояние обновлено:`, {
|
|
232
|
+
stage: this.state.stage,
|
|
233
|
+
isRequiredPassword: this.state.isRequiredPassword,
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
console.log(`[QR-AUTH] Ожидание password promise`)
|
|
237
|
+
const password = await this.state.password.promise
|
|
238
|
+
console.log(`[QR-AUTH] Password получен, длина:`, password?.length || 0)
|
|
239
|
+
|
|
240
|
+
this.state.password = new Deferred<string>()
|
|
241
|
+
console.log(`[QR-AUTH] Password promise сброшен`)
|
|
242
|
+
|
|
243
|
+
return password
|
|
244
|
+
},
|
|
245
|
+
onError: (error) => {
|
|
246
|
+
console.log(`[QR-AUTH] ❌ Ошибка в callback onError для сессии "${this.sessionId}"`)
|
|
247
|
+
console.log(`[QR-AUTH] Тип ошибки:`, error?.constructor?.name)
|
|
248
|
+
console.log(`[QR-AUTH] Сообщение ошибки:`, error instanceof Error ? error.message : String(error))
|
|
249
|
+
console.log(`[QR-AUTH] Stack trace:`, error instanceof Error ? error.stack : 'N/A')
|
|
250
|
+
|
|
251
|
+
this.state.stage = AuthState.ERROR
|
|
252
|
+
console.log(`[QR-AUTH] Стадия изменена на ERROR`)
|
|
253
|
+
|
|
254
|
+
this.emit(SessionAuthEvent.AUTH_ERROR, {
|
|
255
|
+
sessionId: this.sessionId,
|
|
256
|
+
error: error instanceof Error ? error.message : String(error),
|
|
257
|
+
})
|
|
258
|
+
console.log(`[QR-AUTH] Событие AUTH_ERROR отправлено`)
|
|
259
|
+
},
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
console.log(`[QR-AUTH] ✅ signInUserWithQrCode завершен для сессии "${this.sessionId}"`)
|
|
263
|
+
console.log(`[QR-AUTH] Полученный user объект:`, {
|
|
264
|
+
type: user?.constructor?.name,
|
|
265
|
+
isApiUser: user instanceof Api.User,
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
// Проверяем, что это реальный пользователь
|
|
269
|
+
if (!(user instanceof Api.User)) {
|
|
270
|
+
console.log(`[QR-AUTH] ❌ Неверный тип пользователя:`, user?.constructor?.name)
|
|
271
|
+
throw new Error('Получен неверный тип пользователя')
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
this.state.stage = AuthState.AUTHORIZED
|
|
275
|
+
this.state.connect.resolve(true)
|
|
276
|
+
|
|
277
|
+
// Сохраняем сессию в базу данных
|
|
278
|
+
console.log(`[QR-AUTH] Начало сохранения сессии в БД`)
|
|
279
|
+
try {
|
|
280
|
+
let avatarBuffer = await this.client.downloadProfilePhoto('me'),
|
|
281
|
+
avatarUrl
|
|
282
|
+
|
|
283
|
+
if (avatarBuffer) {
|
|
284
|
+
console.log(`[QR-AUTH] Загрузка аватара на Imgbox`)
|
|
285
|
+
avatarUrl = await ImageUploadService.uploadToImgbox(Buffer.isBuffer(avatarBuffer) ? avatarBuffer : Buffer.from(avatarBuffer)).catch(() => null)
|
|
286
|
+
console.log(`[QR-AUTH] Аватар загружен на Imgbox:`, avatarUrl)
|
|
287
|
+
} else {
|
|
288
|
+
console.log(`[QR-AUTH] Аватар отсутствует, пропускаем загрузку`)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const sessionString = this.client.session.save()
|
|
292
|
+
|
|
293
|
+
const sessionData = {
|
|
294
|
+
sessionId: this.sessionId,
|
|
295
|
+
apiId: this.client.apiId,
|
|
296
|
+
apiHash: this.client.apiHash,
|
|
297
|
+
userId: Number(user.id),
|
|
298
|
+
username: user.username,
|
|
299
|
+
firstName: user.firstName,
|
|
300
|
+
lastName: user.lastName,
|
|
301
|
+
phoneNumber: user.phone,
|
|
302
|
+
sessionString: sessionString!,
|
|
303
|
+
avatarUrl,
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
await EvogramGramJS.databaseService.saveSession(sessionData as any)
|
|
307
|
+
} catch (saveError) {
|
|
308
|
+
console.log(`[QR-AUTH] ⚠️ Ошибка при сохранении сессии в БД:`, {
|
|
309
|
+
error: saveError instanceof Error ? saveError.message : String(saveError),
|
|
310
|
+
stack: saveError instanceof Error ? saveError.stack : 'N/A',
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
console.log(`[QR-AUTH] Отправка события AUTH_SUCCESS`)
|
|
315
|
+
this.emit(SessionAuthEvent.AUTH_SUCCESS, {
|
|
316
|
+
sessionId: this.sessionId,
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
console.log(`[QR-AUTH] ✅ Авторизация через QR-код успешно завершена для сессии "${this.sessionId}"`)
|
|
320
|
+
return {
|
|
321
|
+
success: true,
|
|
322
|
+
}
|
|
323
|
+
} catch (error) {
|
|
324
|
+
console.log(`[QR-AUTH] ❌ Критическая ошибка в startWithQRCode для сессии "${this.sessionId}"`)
|
|
325
|
+
console.log(`[QR-AUTH] Тип ошибки:`, error?.constructor?.name)
|
|
326
|
+
console.log(`[QR-AUTH] Сообщение ошибки:`, error instanceof Error ? error.message : String(error))
|
|
327
|
+
console.log(`[QR-AUTH] Stack trace:`, error instanceof Error ? error.stack : 'N/A')
|
|
328
|
+
console.log(`[QR-AUTH] Полный объект ошибки:`, error)
|
|
329
|
+
|
|
330
|
+
this.state.stage = AuthState.ERROR
|
|
331
|
+
console.log(`[QR-AUTH] Стадия изменена на ERROR`)
|
|
332
|
+
|
|
333
|
+
this.emit(SessionAuthEvent.AUTH_ERROR, {
|
|
334
|
+
sessionId: this.sessionId,
|
|
335
|
+
error: error instanceof Error ? error.message : String(error),
|
|
336
|
+
})
|
|
337
|
+
console.log(`[QR-AUTH] Событие AUTH_ERROR отправлено`)
|
|
338
|
+
|
|
339
|
+
return {
|
|
340
|
+
success: false,
|
|
341
|
+
error: error instanceof Error ? error.message : String(error),
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
163
346
|
/**
|
|
164
347
|
* Проверяет, требуется ли пароль для авторизации
|
|
165
348
|
*
|
|
@@ -164,12 +164,17 @@ export class SessionManager extends EventEmitter {
|
|
|
164
164
|
|
|
165
165
|
async getAllLoadedSessions(): Promise<({ db: SessionEntity | null; user: Api.User | null } & Omit<SessionInfo, 'db' | 'user'>)[]> {
|
|
166
166
|
const sessions = Array.from(this.sessions.values())
|
|
167
|
+
|
|
167
168
|
const results = await Promise.all(
|
|
168
|
-
sessions
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
sessions
|
|
170
|
+
.filter((x) => x.sessionId)
|
|
171
|
+
.map(async (session) => {
|
|
172
|
+
return {
|
|
173
|
+
...session,
|
|
174
|
+
db: await session.db().catch(() => null),
|
|
175
|
+
user: await session.user().catch(() => null),
|
|
176
|
+
}
|
|
177
|
+
})
|
|
173
178
|
)
|
|
174
179
|
|
|
175
180
|
//@ts-ignore
|
package/lib/EvogramGramJS.d.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { DatabaseConfig } from './config/database.config';
|
|
2
|
-
import { DatabaseService } from './services/DatabaseService';
|
|
3
|
-
import { SessionManager } from './sessions/SessionManager';
|
|
4
|
-
/**
|
|
5
|
-
* Главный статический класс для работы с EvogramGramJS
|
|
6
|
-
* Управляет сессиями Telegram и базой данных
|
|
7
|
-
*/
|
|
8
|
-
export declare class EvogramGramJS {
|
|
9
|
-
private static _sessionManager;
|
|
10
|
-
private static _databaseService;
|
|
11
|
-
private static _telegramAppId;
|
|
12
|
-
private static _telegramAppHash;
|
|
13
|
-
/**
|
|
14
|
-
* Инициализирует EvogramGramJS
|
|
15
|
-
*
|
|
16
|
-
* @param telegramAppId API ID из Telegram
|
|
17
|
-
* @param telegramAppHash API Hash из Telegram
|
|
18
|
-
* @param databaseConfig Конфигурация базы данных (опционально)
|
|
19
|
-
*/
|
|
20
|
-
static initialize(telegramAppId: number, telegramAppHash: string, databaseConfig?: DatabaseConfig): void;
|
|
21
|
-
/**
|
|
22
|
-
* Получает менеджер сессий
|
|
23
|
-
*
|
|
24
|
-
* @returns SessionManager
|
|
25
|
-
* @throws Error если EvogramGramJS не инициализирован
|
|
26
|
-
*/
|
|
27
|
-
static get sessionManager(): SessionManager;
|
|
28
|
-
/**
|
|
29
|
-
* Получает сервис базы данных
|
|
30
|
-
*
|
|
31
|
-
* @returns DatabaseService
|
|
32
|
-
* @throws Error если EvogramGramJS не инициализирован
|
|
33
|
-
*/
|
|
34
|
-
static get databaseService(): DatabaseService;
|
|
35
|
-
/**
|
|
36
|
-
* Инициализирует базу данных
|
|
37
|
-
*
|
|
38
|
-
* @param config Конфигурация базы данных
|
|
39
|
-
*/
|
|
40
|
-
static initializeDatabase(config: DatabaseConfig): Promise<void>;
|
|
41
|
-
/**
|
|
42
|
-
* Закрывает подключение к базе данных
|
|
43
|
-
*/
|
|
44
|
-
static closeDatabase(): Promise<void>;
|
|
45
|
-
/**
|
|
46
|
-
* Проверяет, инициализирован ли EvogramGramJS
|
|
47
|
-
*
|
|
48
|
-
* @returns true, если инициализирован
|
|
49
|
-
*/
|
|
50
|
-
static isInitialized(): boolean;
|
|
51
|
-
}
|