evogram-gramjs 1.0.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 (64) hide show
  1. package/.evogram/7878190870/database.db +0 -0
  2. package/lib/EvogramGramJS.d.ts +51 -0
  3. package/lib/EvogramGramJS.js +99 -0
  4. package/lib/commands/Accounts.command.d.ts +6 -0
  5. package/lib/commands/Accounts.command.js +90 -0
  6. package/lib/commands/AddAccount.command.d.ts +6 -0
  7. package/lib/commands/AddAccount.command.js +170 -0
  8. package/lib/commands/index.d.ts +0 -0
  9. package/lib/commands/index.js +1 -0
  10. package/lib/commands/managment/DeleteAccount.command.d.ts +0 -0
  11. package/lib/commands/managment/DeleteAccount.command.js +12 -0
  12. package/lib/config/database.config.d.ts +26 -0
  13. package/lib/config/database.config.js +31 -0
  14. package/lib/entities/Session.entity.d.ts +28 -0
  15. package/lib/entities/Session.entity.js +71 -0
  16. package/lib/entities/SessionEventLog.entity.d.ts +22 -0
  17. package/lib/entities/SessionEventLog.entity.js +50 -0
  18. package/lib/examples/auth.example.d.ts +10 -0
  19. package/lib/examples/auth.example.js +126 -0
  20. package/lib/examples/database.example.d.ts +13 -0
  21. package/lib/examples/database.example.js +109 -0
  22. package/lib/examples/usage.example.d.ts +13 -0
  23. package/lib/examples/usage.example.js +127 -0
  24. package/lib/index.d.ts +7 -0
  25. package/lib/index.js +10 -0
  26. package/lib/services/DatabaseService.d.ts +30 -0
  27. package/lib/services/DatabaseService.js +93 -0
  28. package/lib/services/ImageUploadService.d.ts +15 -0
  29. package/lib/services/ImageUploadService.js +56 -0
  30. package/lib/sessions/Session.d.ts +13 -0
  31. package/lib/sessions/Session.js +25 -0
  32. package/lib/sessions/SessionAuth.d.ts +62 -0
  33. package/lib/sessions/SessionAuth.js +165 -0
  34. package/lib/sessions/SessionLogger.d.ts +84 -0
  35. package/lib/sessions/SessionLogger.js +196 -0
  36. package/lib/sessions/SessionManager.d.ts +79 -0
  37. package/lib/sessions/SessionManager.js +184 -0
  38. package/lib/types/auth.types.d.ts +90 -0
  39. package/lib/types/auth.types.js +19 -0
  40. package/lib/types/session.types.d.ts +87 -0
  41. package/lib/types/session.types.js +21 -0
  42. package/lib/utils/Deferrer.d.ts +6 -0
  43. package/lib/utils/Deferrer.js +14 -0
  44. package/package-lock.json +6 -0
  45. package/package.json +27 -0
  46. package/src/EvogramGramJS.ts +98 -0
  47. package/src/commands/Accounts.command.ts +84 -0
  48. package/src/commands/AddAccount.command.ts +171 -0
  49. package/src/commands/index.ts +0 -0
  50. package/src/commands/managment/DeleteAccount.command.ts +13 -0
  51. package/src/config/database.config.ts +75 -0
  52. package/src/entities/Session.entity.ts +58 -0
  53. package/src/entities/SessionEventLog.entity.ts +41 -0
  54. package/src/index.ts +7 -0
  55. package/src/services/DatabaseService.ts +82 -0
  56. package/src/services/ImageUploadService.ts +49 -0
  57. package/src/sessions/Session.ts +21 -0
  58. package/src/sessions/SessionAuth.ts +173 -0
  59. package/src/sessions/SessionLogger.ts +208 -0
  60. package/src/sessions/SessionManager.ts +190 -0
  61. package/src/types/auth.types.ts +94 -0
  62. package/src/types/session.types.ts +96 -0
  63. package/src/utils/Deferrer.ts +12 -0
  64. package/tsconfig.json +17 -0
@@ -0,0 +1,173 @@
1
+ import { EventEmitter } from 'events'
2
+ import { TelegramClient } from 'telegram'
3
+ import { EvogramGramJS } from '../EvogramGramJS'
4
+ import { ImageUploadService } from '../services/ImageUploadService'
5
+ import { AuthState } from '../types/auth.types'
6
+ import { Deferred } from '../utils/Deferrer'
7
+ import { SessionLogger } from './SessionLogger'
8
+
9
+ /**
10
+ * События авторизации для сессии
11
+ */
12
+ export enum SessionAuthEvent {
13
+ /** Начало авторизации */
14
+ AUTH_STARTED = 'auth:started',
15
+ /** Код отправлен */
16
+ CODE_SENT = 'auth:code_sent',
17
+ /** Код получен */
18
+ CODE_RECEIVED = 'auth:code_received',
19
+ /** Требуется пароль */
20
+ PASSWORD_REQUIRED = 'auth:password_required',
21
+ /** Авторизация успешна */
22
+ AUTH_SUCCESS = 'auth:success',
23
+ /** Ошибка авторизации */
24
+ AUTH_ERROR = 'auth:error',
25
+ /** Авторизация отменена */
26
+ AUTH_CANCELLED = 'auth:cancelled',
27
+ }
28
+
29
+ /**
30
+ * Класс авторизации для конкретной сессии
31
+ * Предоставляет методы авторизации, привязанные к сессии
32
+ */
33
+ export class SessionAuth extends EventEmitter {
34
+ public state: {
35
+ code: Deferred<string>
36
+ password: Deferred<string>
37
+ isRequiredPassword: boolean
38
+ stage: AuthState
39
+ connect: Deferred<boolean>
40
+ } = null as any
41
+
42
+ constructor(private readonly sessionId: string, private readonly client: TelegramClient, private readonly logger?: SessionLogger) {
43
+ super()
44
+ }
45
+
46
+ async start(phoneNumber: string) {
47
+ if (this.state) throw new Error(`Авторизация для сессии "${this.sessionId}" уже начата`)
48
+
49
+ this.state = {
50
+ code: new Deferred<string>(),
51
+ password: new Deferred<string>(),
52
+ isRequiredPassword: false,
53
+ stage: AuthState.INITIAL,
54
+ connect: new Deferred<boolean>(),
55
+ }
56
+
57
+ try {
58
+ await new Promise(async (res, rej) => {
59
+ await this.client
60
+ .start({
61
+ phoneNumber,
62
+ phoneCode: async () => {
63
+ res(true)
64
+ this.state.stage = AuthState.WAITING_CODE
65
+
66
+ const code = await this.state.code.promise
67
+ this.state.code = new Deferred<string>()
68
+
69
+ return code
70
+ },
71
+ password: async () => {
72
+ this.state.isRequiredPassword = true
73
+ this.state.stage = AuthState.WAITING_PASSWORD
74
+
75
+ const password = await this.state.password.promise
76
+ this.state.password = new Deferred<string>()
77
+
78
+ return password
79
+ },
80
+ onError: (error) => {
81
+ this.state.stage = AuthState.ERROR
82
+
83
+ this.emit(SessionAuthEvent.AUTH_ERROR, {
84
+ sessionId: this.sessionId,
85
+ error: error instanceof Error ? error.message : String(error),
86
+ })
87
+ },
88
+ })
89
+ .catch(rej)
90
+
91
+ try {
92
+ const me = await this.client.getMe()
93
+ this.state.connect.resolve(true)
94
+
95
+ let avatarBuffer = await this.client.downloadProfilePhoto('me'),
96
+ avatarUrl
97
+ if (avatarBuffer) avatarUrl = await ImageUploadService.uploadToImgbox(Buffer.isBuffer(avatarBuffer) ? avatarBuffer : Buffer.from(avatarBuffer))
98
+
99
+ await EvogramGramJS.databaseService.saveSession({
100
+ sessionId: this.sessionId,
101
+ apiId: this.client.apiId,
102
+ apiHash: this.client.apiHash,
103
+ userId: Number(me.id),
104
+ username: me.username,
105
+ firstName: me.firstName,
106
+ lastName: me.lastName,
107
+ phoneNumber: me.phone,
108
+ sessionString: this.client.session.save()!,
109
+ avatarUrl,
110
+ })
111
+ } catch {}
112
+ })
113
+
114
+ return {
115
+ success: true,
116
+ }
117
+ } catch (error) {
118
+ this.emit(SessionAuthEvent.AUTH_ERROR, {
119
+ sessionId: this.sessionId,
120
+ error: error instanceof Error ? error.message : String(error),
121
+ })
122
+
123
+ return {
124
+ success: false,
125
+ error,
126
+ }
127
+ }
128
+ }
129
+
130
+ async setCode(code: string) {
131
+ if (!this.state) throw new Error(`Авторизация для сессии "${this.sessionId}" не начата`)
132
+ const errorPromise = new Promise<Error>((resolve, reject) => {
133
+ this.once(SessionAuthEvent.AUTH_ERROR, (data) => data.sessionId === this.sessionId && resolve(data.error))
134
+ setTimeout(resolve, 1_000)
135
+ })
136
+
137
+ this.state.code.resolve(code)
138
+ const error = await errorPromise
139
+
140
+ return {
141
+ success: error ? false : true,
142
+ error: error || undefined,
143
+ }
144
+ }
145
+
146
+ async setPassword(password: string) {
147
+ if (!this.state) throw new Error(`Авторизация для сессии "${this.sessionId}" не начата`)
148
+
149
+ const errorPromise = new Promise<Error>((resolve, reject) => {
150
+ this.once(SessionAuthEvent.AUTH_ERROR, (data) => data.sessionId === this.sessionId && resolve(data.error))
151
+ setTimeout(resolve, 1_000)
152
+ })
153
+
154
+ this.state.password.resolve(password)
155
+ const error = await errorPromise
156
+
157
+ return {
158
+ success: error ? false : true,
159
+ error: error || undefined,
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Проверяет, требуется ли пароль для авторизации
165
+ *
166
+ * @returns true, если требуется пароль
167
+ */
168
+ async isRequiredPassword(): Promise<boolean> {
169
+ if (this.state?.isRequiredPassword) return true
170
+ await new Promise((resolve) => setTimeout(resolve, 1000))
171
+ return this.state?.isRequiredPassword ?? false
172
+ }
173
+ }
@@ -0,0 +1,208 @@
1
+ import { createWriteStream, WriteStream } from 'fs'
2
+ import { mkdir } from 'fs/promises'
3
+ import { join } from 'path'
4
+
5
+ /**
6
+ * Логгер для отдельной сессии
7
+ * Записывает все действия и активность сессии в отдельный файл
8
+ */
9
+ export class SessionLogger {
10
+ private logStream: WriteStream | null = null
11
+ private logFilePath: string
12
+ private isInitialized: boolean = false
13
+
14
+ /**
15
+ * @param sessionId Идентификатор сессии
16
+ * @param logsDirectory Директория для хранения логов (по умолчанию './logs')
17
+ */
18
+ constructor(private readonly sessionId: string, private readonly logsDirectory: string = './logs') {
19
+ // Формируем путь к файлу лога
20
+ const sanitizedSessionId = this.sanitizeFileName(sessionId)
21
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
22
+ this.logFilePath = join(this.logsDirectory, `session-${sanitizedSessionId}-${timestamp}.log`)
23
+ }
24
+
25
+ /**
26
+ * Инициализирует логгер (создает директорию и файл)
27
+ */
28
+ async initialize(): Promise<void> {
29
+ if (this.isInitialized) return
30
+
31
+ try {
32
+ // Создаем директорию для логов, если её нет
33
+ await mkdir(this.logsDirectory, { recursive: true })
34
+
35
+ // Создаем поток записи в файл (режим append)
36
+ this.logStream = createWriteStream(this.logFilePath, { flags: 'a' })
37
+
38
+ // Записываем заголовок
39
+ this.writeLog('INFO', `Логгер инициализирован для сессии: ${this.sessionId}`)
40
+ this.writeLog('INFO', `Файл лога: ${this.logFilePath}`)
41
+ this.writeLog('INFO', `Время создания: ${new Date().toISOString()}`)
42
+ this.writeLog('INFO', '─'.repeat(80))
43
+
44
+ this.isInitialized = true
45
+ } catch (error) {
46
+ console.error(`Ошибка инициализации логгера для сессии ${this.sessionId}:`, error)
47
+ throw error
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Записывает лог-запись в файл
53
+ *
54
+ * @param level Уровень логирования (INFO, WARN, ERROR, DEBUG)
55
+ * @param message Сообщение для логирования
56
+ * @param data Дополнительные данные (опционально)
57
+ */
58
+ log(level: 'INFO' | 'WARN' | 'ERROR' | 'DEBUG', message: string, data?: any): void {
59
+ if (!this.isInitialized) {
60
+ // Если логгер еще не инициализирован, инициализируем синхронно
61
+ this.initialize().catch((error) => {
62
+ console.error(`Ошибка инициализации логгера:`, error)
63
+ })
64
+ return
65
+ }
66
+
67
+ this.writeLog(level, message, data)
68
+ }
69
+
70
+ /**
71
+ * Логирует информацию
72
+ */
73
+ info(message: string, data?: any): void {
74
+ this.log('INFO', message, data)
75
+ }
76
+
77
+ /**
78
+ * Логирует предупреждение
79
+ */
80
+ warn(message: string, data?: any): void {
81
+ this.log('WARN', message, data)
82
+ }
83
+
84
+ /**
85
+ * Логирует ошибку
86
+ */
87
+ error(message: string, error?: Error | any): void {
88
+ const errorMessage = error instanceof Error ? error.message : String(error)
89
+ const errorStack = error instanceof Error ? error.stack : undefined
90
+ this.log('ERROR', message, { error: errorMessage, stack: errorStack })
91
+ }
92
+
93
+ /**
94
+ * Логирует отладочную информацию
95
+ */
96
+ debug(message: string, data?: any): void {
97
+ this.log('DEBUG', message, data)
98
+ }
99
+
100
+ /**
101
+ * Логирует действие сессии
102
+ *
103
+ * @param action Название действия
104
+ * @param details Детали действия
105
+ */
106
+ logAction(action: string, details?: any): void {
107
+ this.info(`Действие: ${action}`, details)
108
+ }
109
+
110
+ /**
111
+ * Логирует событие от Telegram клиента
112
+ *
113
+ * @param eventName Название события
114
+ * @param eventData Данные события
115
+ */
116
+ logTelegramEvent(eventName: string, eventData?: any): void {
117
+ this.debug(`Telegram событие: ${eventName}`, eventData)
118
+ }
119
+
120
+ /**
121
+ * Закрывает поток записи
122
+ */
123
+ async close(): Promise<void> {
124
+ if (this.logStream) {
125
+ this.writeLog('INFO', '─'.repeat(80))
126
+ this.writeLog('INFO', `Логгер закрыт для сессии: ${this.sessionId}`)
127
+ this.writeLog('INFO', `Время закрытия: ${new Date().toISOString()}`)
128
+
129
+ return new Promise((resolve, reject) => {
130
+ this.logStream!.end((error: Error | null | undefined) => {
131
+ if (error) {
132
+ reject(error)
133
+ } else {
134
+ this.logStream = null
135
+ this.isInitialized = false
136
+ resolve()
137
+ }
138
+ })
139
+ })
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Получает путь к файлу лога
145
+ */
146
+ getLogFilePath(): string {
147
+ return this.logFilePath
148
+ }
149
+
150
+ /**
151
+ * Внутренний метод для записи в файл
152
+ *
153
+ * @private
154
+ */
155
+ private writeLog(level: string, message: string, data?: any): void {
156
+ if (!this.logStream) {
157
+ // Если поток еще не создан, выводим в консоль
158
+ console.log(`[${this.sessionId}] [${level}] ${message}`, data || '')
159
+ return
160
+ }
161
+
162
+ const timestamp = new Date().toISOString()
163
+ const logEntry: any = {
164
+ timestamp,
165
+ level,
166
+ sessionId: this.sessionId,
167
+ message,
168
+ }
169
+
170
+ if (data !== undefined) {
171
+ logEntry.data = data
172
+ }
173
+
174
+ // Форматируем запись для удобного чтения
175
+ const logLine = this.formatLogEntry(logEntry)
176
+ this.logStream.write(logLine + '\n')
177
+ }
178
+
179
+ /**
180
+ * Форматирует запись лога для записи в файл
181
+ *
182
+ * @private
183
+ */
184
+ private formatLogEntry(entry: any): string {
185
+ const { timestamp, level, message, data } = entry
186
+ let logLine = `[${timestamp}] [${level}] ${message}`
187
+
188
+ if (data !== undefined) {
189
+ try {
190
+ const dataStr = typeof data === 'string' ? data : JSON.stringify(data, null, 2)
191
+ logLine += `\n${dataStr}`
192
+ } catch (error) {
193
+ logLine += `\n[Не удалось сериализовать данные]`
194
+ }
195
+ }
196
+
197
+ return logLine
198
+ }
199
+
200
+ /**
201
+ * Очищает имя файла от недопустимых символов
202
+ *
203
+ * @private
204
+ */
205
+ private sanitizeFileName(fileName: string): string {
206
+ return fileName.replace(/[^a-zA-Z0-9_-]/g, '_')
207
+ }
208
+ }
@@ -0,0 +1,190 @@
1
+ import { EventEmitter } from 'events'
2
+ import { TelegramClient } from 'telegram'
3
+ import { UpdateConnectionState } from 'telegram/network'
4
+ import { StringSession } from 'telegram/sessions'
5
+ import { EvogramGramJS } from '../EvogramGramJS'
6
+ import { DatabaseService } from '../services/DatabaseService'
7
+ import { SessionConfig, SessionEvent, SessionEventData, SessionInfo, SessionInvalidEventData } from '../types/session.types'
8
+ import { Session } from './Session'
9
+ import { SessionAuth } from './SessionAuth'
10
+ import { SessionLogger } from './SessionLogger'
11
+
12
+ /**
13
+ * Сервис для управления множеством сессий Telegram клиентов
14
+ *
15
+ * Предоставляет удобный API для:
16
+ * - Добавления и удаления сессий
17
+ * - Получения информации о сессиях
18
+ * - Отслеживания событий (подключение, отключение, ошибки)
19
+ * - Сохранения данных в базе данных
20
+ */
21
+ export class SessionManager extends EventEmitter {
22
+ constructor(private readonly TELEGRAM_APP_ID: number, private readonly TELEGRAM_APP_HASH: string, private readonly databaseService?: DatabaseService) {
23
+ super()
24
+ }
25
+
26
+ /** Хранилище всех активных сессий */
27
+ private sessions: Map<string, SessionInfo> = new Map()
28
+
29
+ public async initialize(): Promise<void> {
30
+ const sessions = await this.databaseService?.getSessions()
31
+ if (!sessions || sessions.length === 0) return
32
+
33
+ for (const session of sessions) {
34
+ await this.addSession({
35
+ sessionId: session.sessionId,
36
+ sessionString: session.sessionString,
37
+ apiId: session.apiId,
38
+ apiHash: session.apiHash,
39
+ clientOptions: session.clientOptions ? JSON.parse(session.clientOptions) : undefined,
40
+ })
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Добавляет новую сессию
46
+ *
47
+ * @param config Конфигурация сессии
48
+ * @returns Promise с информацией о созданной сессии
49
+ * @throws Error если сессия с таким ID уже существует
50
+ */
51
+ async addSession(config: SessionConfig): Promise<SessionInfo> {
52
+ // Проверяем, не существует ли уже сессия с таким ID в памяти
53
+ if (this.sessions.has(config.sessionId)) return this.sessions.get(config.sessionId)!
54
+
55
+ // Создаем строковую сессию (если не предоставлена, создается пустая)
56
+ const session = new StringSession(config.sessionString || '')
57
+
58
+ // Создаем Telegram клиент
59
+ const client = new TelegramClient(session, config.apiId ?? this.TELEGRAM_APP_ID, config.apiHash ?? this.TELEGRAM_APP_HASH, {
60
+ useIPV6: config.clientOptions?.useIPV6 ?? false,
61
+ connectionRetries: config.clientOptions?.connectionRetries ?? 5,
62
+ })
63
+ await client.connect()
64
+
65
+ client.addEventHandler(async (event) => {
66
+ if ((await this.getSession(config.sessionId)?.db())?.error) return
67
+
68
+ if (event instanceof UpdateConnectionState) {
69
+ const error = await client
70
+ .getMe()
71
+ .then(() => undefined)
72
+ .catch((error) => error)
73
+
74
+ if (error) {
75
+ this.emit(SessionEvent.SESSION_INVALID, {
76
+ sessionId: config.sessionId,
77
+ error: error,
78
+ } as SessionInvalidEventData)
79
+
80
+ await EvogramGramJS.databaseService.updateSession(config.sessionId, { error: error.errorMessage })
81
+ await this.disconnectSession(config.sessionId)
82
+ }
83
+ }
84
+ })
85
+
86
+ const sessionAuth = new SessionAuth(config.sessionId, client)
87
+
88
+ const sessionInfo = new Session(config.sessionId, client, undefined, sessionAuth)
89
+ this.sessions.set(config.sessionId, sessionInfo)
90
+
91
+ // Генерируем событие добавления сессии
92
+ this.emit(SessionEvent.SESSION_ADDED, {
93
+ sessionId: config.sessionId,
94
+ sessionInfo,
95
+ } as SessionEventData)
96
+
97
+ return sessionInfo
98
+ }
99
+
100
+ async disconnectSession(sessionId: string): Promise<void> {
101
+ const session = this.sessions.get(sessionId)
102
+ if (!session) throw new Error(`Сессия с ID ${sessionId} не найдена`)
103
+
104
+ await session.client.disconnect()
105
+ this.emit(SessionEvent.SESSION_DISCONNECTED, {
106
+ sessionId: sessionId,
107
+ } as SessionEventData)
108
+ }
109
+
110
+ async getActiveSessions(): Promise<SessionInfo[]> {
111
+ const sessions = Array.from(this.sessions.values())
112
+
113
+ const results = await Promise.all(
114
+ sessions.map(async (session) => {
115
+ const dbData = await session.db()
116
+ return { session, hasError: !!dbData?.error }
117
+ })
118
+ )
119
+
120
+ return results.filter((result) => !result.hasError).map((result) => result.session)
121
+ }
122
+
123
+ /**
124
+ * Получает информацию о сессии по ID
125
+ *
126
+ * @param sessionId Идентификатор сессии
127
+ * @returns Информация о сессии или undefined, если не найдена
128
+ */
129
+ getSession(sessionId: string): SessionInfo | undefined {
130
+ const sessionInfo = this.sessions.get(sessionId)
131
+ return sessionInfo
132
+ }
133
+
134
+ /**
135
+ * Получает Telegram клиент по ID сессии
136
+ *
137
+ * @param sessionId Идентификатор сессии
138
+ * @returns Telegram клиент или undefined, если сессия не найдена
139
+ */
140
+ getClient(sessionId: string): TelegramClient | undefined {
141
+ return this.getSession(sessionId)?.client
142
+ }
143
+
144
+ /**
145
+ * Получает логгер сессии по ID
146
+ *
147
+ * @param sessionId Идентификатор сессии
148
+ * @returns Логгер сессии или undefined, если сессия не найдена или логирование отключено
149
+ */
150
+ getLogger(sessionId: string): SessionLogger | undefined {
151
+ return this.getSession(sessionId)?.logger
152
+ }
153
+
154
+ /**
155
+ * Получает все активные сессии
156
+ *
157
+ * @returns Массив информации о всех сессиях
158
+ */
159
+ getAllSessions(): SessionInfo[] {
160
+ return Array.from(this.sessions.values())
161
+ }
162
+
163
+ /**
164
+ * Получает список всех ID сессий
165
+ *
166
+ * @returns Массив идентификаторов сессий
167
+ */
168
+ getAllSessionIds(): string[] {
169
+ return Array.from(this.sessions.keys())
170
+ }
171
+
172
+ /**
173
+ * Проверяет, существует ли сессия с указанным ID
174
+ *
175
+ * @param sessionId Идентификатор сессии
176
+ * @returns true, если сессия существует, иначе false
177
+ */
178
+ hasSession(sessionId: string): boolean {
179
+ return this.sessions.has(sessionId)
180
+ }
181
+
182
+ /**
183
+ * Получает количество активных сессий
184
+ *
185
+ * @returns Количество сессий
186
+ */
187
+ getSessionCount(): number {
188
+ return this.sessions.size
189
+ }
190
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Состояния процесса авторизации
3
+ */
4
+ export enum AuthState {
5
+ /** Начальное состояние - не авторизован */
6
+ INITIAL = 'initial',
7
+ /** Ожидание кода подтверждения */
8
+ WAITING_CODE = 'waiting_code',
9
+ /** Ожидание пароля (2FA) */
10
+ WAITING_PASSWORD = 'waiting_password',
11
+ /** Авторизация завершена */
12
+ AUTHORIZED = 'authorized',
13
+ /** Ошибка авторизации */
14
+ ERROR = 'error',
15
+ }
16
+
17
+ /**
18
+ * Информация о процессе авторизации
19
+ */
20
+ export interface AuthInfo {
21
+ /** Идентификатор сессии */
22
+ sessionId: string
23
+ /** Текущее состояние авторизации */
24
+ state: AuthState
25
+ /** Номер телефона (если указан) */
26
+ phoneNumber?: string
27
+ /** Требуется ли пароль (2FA) */
28
+ isRequiredPassword: boolean
29
+ /** Код подтверждения (если ожидается) */
30
+ code?: string
31
+ /** Пароль (2FA) (если ожидается) */
32
+ password?: string
33
+ /** Хеш кода подтверждения */
34
+ phoneCodeHash?: string
35
+ /** Сообщение об ошибке (если есть) */
36
+ error?: string
37
+ /** Время начала авторизации */
38
+ startedAt: Date
39
+ /** Время последнего обновления */
40
+ updatedAt: Date
41
+ /** Промисы для ожидания кода и пароля */
42
+ _codeResolver?: (code: string) => void
43
+ _codeRejecter?: (error: Error) => void
44
+ _passwordResolver?: (password: string) => void
45
+ _passwordRejecter?: (error: Error) => void
46
+ /** Промис для отслеживания начальной ошибки (до запроса кода) */
47
+ _initialErrorRejecter?: (error: Error) => void
48
+ /** Resolver для промиса, когда код был запрошен (успешное начало) */
49
+ _codeRequestedResolver?: () => void
50
+ /** Флаг, что код был запрошен (для различения начальной ошибки от ошибки после запроса кода) */
51
+ _codeRequested?: boolean
52
+ /** Флаг, что была ошибка неверного кода (для отслеживания повторной попытки) */
53
+ _hasCodeError?: boolean
54
+ }
55
+
56
+ /**
57
+ * Результат отправки кода
58
+ */
59
+ export interface SendCodeResult {
60
+ /** Успешно ли отправлен код */
61
+ success: boolean
62
+ /** Требуется ли пароль (2FA) */
63
+ isRequiredPassword: boolean
64
+ /** Сообщение об ошибке (если есть) */
65
+ error?: string
66
+ /** Тип отправки кода (sms, call, etc.) */
67
+ phoneCodeHash?: string
68
+ }
69
+
70
+ /**
71
+ * Результат ввода кода
72
+ */
73
+ export interface SignInResult {
74
+ /** Успешно ли авторизован */
75
+ success: boolean
76
+ /** Требуется ли пароль (2FA) */
77
+ isRequiredPassword: boolean
78
+ /** Сообщение об ошибке (если есть) */
79
+ error?: string
80
+ /** Строка сессии (если авторизация успешна) */
81
+ sessionString?: string
82
+ }
83
+
84
+ /**
85
+ * Результат ввода пароля
86
+ */
87
+ export interface SignInWithPasswordResult {
88
+ /** Успешно ли авторизован */
89
+ success: boolean
90
+ /** Сообщение об ошибке (если есть) */
91
+ error?: string
92
+ /** Строка сессии (если авторизация успешна) */
93
+ sessionString?: string
94
+ }