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.
Files changed (51) hide show
  1. package/.evogram/{7878190870 → 8539886557}/database.db +0 -0
  2. package/evogramjs.sqlite +0 -0
  3. package/package-lock.json +3938 -4
  4. package/package.json +4 -2
  5. package/qr-code-qr-auth-1769097743188.png +0 -0
  6. package/src/commands/AddAccount.command.ts +284 -6
  7. package/src/commands/index.ts +2 -0
  8. package/src/sessions/SessionAuth.ts +184 -1
  9. package/src/sessions/SessionManager.ts +10 -5
  10. package/lib/EvogramGramJS.d.ts +0 -51
  11. package/lib/EvogramGramJS.js +0 -99
  12. package/lib/commands/Accounts.command.d.ts +0 -6
  13. package/lib/commands/Accounts.command.js +0 -95
  14. package/lib/commands/AddAccount.command.d.ts +0 -6
  15. package/lib/commands/AddAccount.command.js +0 -170
  16. package/lib/commands/index.d.ts +0 -0
  17. package/lib/commands/index.js +0 -1
  18. package/lib/commands/managment/DeleteAccount.command.d.ts +0 -0
  19. package/lib/commands/managment/DeleteAccount.command.js +0 -12
  20. package/lib/config/database.config.d.ts +0 -26
  21. package/lib/config/database.config.js +0 -31
  22. package/lib/entities/Session.entity.d.ts +0 -28
  23. package/lib/entities/Session.entity.js +0 -71
  24. package/lib/entities/SessionEventLog.entity.d.ts +0 -22
  25. package/lib/entities/SessionEventLog.entity.js +0 -50
  26. package/lib/examples/auth.example.d.ts +0 -10
  27. package/lib/examples/auth.example.js +0 -126
  28. package/lib/examples/database.example.d.ts +0 -13
  29. package/lib/examples/database.example.js +0 -109
  30. package/lib/examples/usage.example.d.ts +0 -13
  31. package/lib/examples/usage.example.js +0 -127
  32. package/lib/index.d.ts +0 -7
  33. package/lib/index.js +0 -10
  34. package/lib/services/DatabaseService.d.ts +0 -30
  35. package/lib/services/DatabaseService.js +0 -93
  36. package/lib/services/ImageUploadService.d.ts +0 -15
  37. package/lib/services/ImageUploadService.js +0 -56
  38. package/lib/sessions/Session.d.ts +0 -13
  39. package/lib/sessions/Session.js +0 -25
  40. package/lib/sessions/SessionAuth.d.ts +0 -62
  41. package/lib/sessions/SessionAuth.js +0 -165
  42. package/lib/sessions/SessionLogger.d.ts +0 -84
  43. package/lib/sessions/SessionLogger.js +0 -196
  44. package/lib/sessions/SessionManager.d.ts +0 -84
  45. package/lib/sessions/SessionManager.js +0 -199
  46. package/lib/types/auth.types.d.ts +0 -90
  47. package/lib/types/auth.types.js +0 -19
  48. package/lib/types/session.types.d.ts +0 -87
  49. package/lib/types/session.types.js +0 -21
  50. package/lib/utils/Deferrer.d.ts +0 -6
  51. 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.2",
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
- "evogram": "^2.10.4",
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": {
@@ -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', backButton: 'Список аккаунтов' })
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(AddAccountCommand, { phone: message.text })
156
- else if ((await context.storage.get('stage')) === 'code') context.redirect(AddAccountCommand, { code: message.text })
157
- else if ((await context.storage.get('stage')) === 'password') context.redirect(AddAccountCommand, { password: message.text })
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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './Accounts.command'
2
+ export * from './AddAccount.command'
@@ -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.map(async (session) => {
169
- //@ts-ignore
170
- ;[session.db, session.user] = [await session.db().catch(() => null), await session.user().catch(() => null)]
171
- return session
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
@@ -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
- }