evogram-gramjs 1.1.0 → 1.1.1
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/lib/EvogramGramJS.d.ts +51 -0
- package/lib/EvogramGramJS.js +99 -0
- package/lib/commands/Accounts.command.d.ts +6 -0
- package/lib/commands/Accounts.command.js +95 -0
- package/lib/commands/AddAccount.command.d.ts +19 -0
- package/lib/commands/AddAccount.command.js +461 -0
- package/lib/commands/index.d.ts +2 -0
- package/lib/commands/index.js +5 -0
- package/lib/commands/managment/DeleteAccount.command.d.ts +0 -0
- package/{src/commands/managment/DeleteAccount.command.ts → lib/commands/managment/DeleteAccount.command.js} +1 -2
- package/lib/config/database.config.d.ts +26 -0
- package/lib/config/database.config.js +31 -0
- package/lib/entities/Session.entity.d.ts +28 -0
- package/lib/entities/Session.entity.js +71 -0
- package/lib/entities/SessionEventLog.entity.d.ts +22 -0
- package/lib/entities/SessionEventLog.entity.js +50 -0
- package/lib/examples/auth.example.d.ts +10 -0
- package/lib/examples/auth.example.js +126 -0
- package/lib/examples/database.example.d.ts +13 -0
- package/lib/examples/database.example.js +109 -0
- package/lib/examples/usage.example.d.ts +13 -0
- package/lib/examples/usage.example.js +127 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +10 -0
- package/lib/services/DatabaseService.d.ts +30 -0
- package/lib/services/DatabaseService.js +93 -0
- package/lib/services/ImageUploadService.d.ts +15 -0
- package/lib/services/ImageUploadService.js +56 -0
- package/lib/sessions/Session.d.ts +13 -0
- package/lib/sessions/Session.js +25 -0
- package/lib/sessions/SessionAuth.d.ts +72 -0
- package/lib/sessions/SessionAuth.js +327 -0
- package/lib/sessions/SessionLogger.d.ts +84 -0
- package/lib/sessions/SessionLogger.js +196 -0
- package/lib/sessions/SessionManager.d.ts +84 -0
- package/lib/sessions/SessionManager.js +198 -0
- package/lib/test.d.ts +1 -0
- package/lib/test.js +144 -0
- package/lib/types/auth.types.d.ts +90 -0
- package/lib/types/auth.types.js +19 -0
- package/lib/types/session.types.d.ts +87 -0
- package/lib/types/session.types.js +21 -0
- package/lib/utils/Deferrer.d.ts +6 -0
- package/lib/utils/Deferrer.js +14 -0
- package/package.json +1 -2
- package/src/EvogramGramJS.ts +0 -98
- package/src/commands/Accounts.command.ts +0 -89
- package/src/commands/AddAccount.command.ts +0 -449
- package/src/commands/index.ts +0 -2
- package/src/config/database.config.ts +0 -75
- package/src/entities/Session.entity.ts +0 -58
- package/src/entities/SessionEventLog.entity.ts +0 -41
- package/src/index.ts +0 -7
- package/src/services/DatabaseService.ts +0 -82
- package/src/services/ImageUploadService.ts +0 -49
- package/src/sessions/Session.ts +0 -21
- package/src/sessions/SessionAuth.ts +0 -356
- package/src/sessions/SessionLogger.ts +0 -208
- package/src/sessions/SessionManager.ts +0 -211
- package/src/types/auth.types.ts +0 -94
- package/src/types/session.types.ts +0 -96
- package/src/utils/Deferrer.ts +0 -12
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { DataSource, Repository } from 'typeorm'
|
|
2
|
-
import { DatabaseConfig, createDataSourceOptions } from '../config/database.config'
|
|
3
|
-
import { Session as SessionEntity } from '../entities/Session.entity'
|
|
4
|
-
import { SessionEventLog } from '../entities/SessionEventLog.entity'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Сервис для работы с базой данных
|
|
8
|
-
* Управляет сохранением и загрузкой сессий и их событий
|
|
9
|
-
*/
|
|
10
|
-
export class DatabaseService {
|
|
11
|
-
private dataSource!: DataSource
|
|
12
|
-
private sessionRepository!: Repository<SessionEntity>
|
|
13
|
-
private eventLogRepository!: Repository<SessionEventLog>
|
|
14
|
-
private isInitialized: boolean = false
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Инициализирует подключение к базе данных
|
|
18
|
-
*
|
|
19
|
-
* @param config Конфигурация базы данных
|
|
20
|
-
*/
|
|
21
|
-
async initialize(config: DatabaseConfig = {}): Promise<void> {
|
|
22
|
-
if (this.isInitialized) return
|
|
23
|
-
|
|
24
|
-
const options = createDataSourceOptions(config)
|
|
25
|
-
this.dataSource = new DataSource(options)
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
await this.dataSource.initialize()
|
|
29
|
-
this.sessionRepository = this.dataSource.getRepository(SessionEntity)
|
|
30
|
-
this.eventLogRepository = this.dataSource.getRepository(SessionEventLog)
|
|
31
|
-
this.isInitialized = true
|
|
32
|
-
} catch (error) {
|
|
33
|
-
console.error('Ошибка инициализации базы данных:', error)
|
|
34
|
-
throw error
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async saveSession(session: Partial<SessionEntity>) {
|
|
39
|
-
if (!this.isReady()) throw new Error('База данных не инициализирована')
|
|
40
|
-
|
|
41
|
-
const existingSession = await this.sessionRepository.findOne({ where: { sessionId: session.sessionId } })
|
|
42
|
-
|
|
43
|
-
if (existingSession) await this.sessionRepository.update({ sessionId: existingSession.sessionId }, session)
|
|
44
|
-
else await this.sessionRepository.save(session)
|
|
45
|
-
|
|
46
|
-
return this.getSession(session.sessionId!)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async updateSession(sessionId: string, session: Partial<SessionEntity>) {
|
|
50
|
-
if (!this.isReady()) throw new Error('База данных не инициализирована')
|
|
51
|
-
await this.sessionRepository.update({ sessionId }, session)
|
|
52
|
-
|
|
53
|
-
return this.getSession(sessionId)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async getSession(sessionId: string) {
|
|
57
|
-
if (!this.isReady()) throw new Error('База данных не инициализирована')
|
|
58
|
-
return await this.sessionRepository.findOne({ where: { sessionId } })
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async getSessions() {
|
|
62
|
-
if (!this.isReady()) throw new Error('База данных не инициализирована')
|
|
63
|
-
return await this.sessionRepository.find({ order: { createdAt: 'DESC' } })
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Закрывает подключение к базе данных
|
|
68
|
-
*/
|
|
69
|
-
async close(): Promise<void> {
|
|
70
|
-
if (this.dataSource && this.dataSource.isInitialized) {
|
|
71
|
-
await this.dataSource.destroy()
|
|
72
|
-
this.isInitialized = false
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Проверяет, инициализирована ли база данных
|
|
78
|
-
*/
|
|
79
|
-
isReady(): boolean {
|
|
80
|
-
return this.isInitialized && this.dataSource?.isInitialized
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import axios from 'axios'
|
|
2
|
-
import FormData from 'form-data'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Сервис для загрузки изображений на внешние хостинги
|
|
6
|
-
*/
|
|
7
|
-
export class ImageUploadService {
|
|
8
|
-
static readonly UPLOAD_URL = 'https://imgbox.vu/uploads'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Загружает изображение на imgbox.vu/uploads
|
|
12
|
-
*
|
|
13
|
-
* @param imageBuffer Буфер изображения
|
|
14
|
-
* @param filename Имя файла (опционально)
|
|
15
|
-
* @returns Promise с URL загруженного изображения
|
|
16
|
-
* @throws Error если загрузка не удалась
|
|
17
|
-
*/
|
|
18
|
-
static async uploadToImgbox(imageBuffer: Buffer, filename?: string): Promise<string> {
|
|
19
|
-
try {
|
|
20
|
-
const formData = new FormData()
|
|
21
|
-
formData.append('file', imageBuffer, {
|
|
22
|
-
filename: filename || 'avatar.jpg',
|
|
23
|
-
contentType: 'image/jpeg',
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
const response = await axios.post(this.UPLOAD_URL, formData, {
|
|
27
|
-
headers: formData.getHeaders(),
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
const result = response.data
|
|
31
|
-
|
|
32
|
-
// Проверяем формат ответа imgbox.vu
|
|
33
|
-
// API может возвращать URL в разных форматах, нужно проверить структуру ответа
|
|
34
|
-
if (result.url) {
|
|
35
|
-
return result.url
|
|
36
|
-
} else if (result.data?.url) {
|
|
37
|
-
return result.data.url
|
|
38
|
-
} else if (typeof result === 'string' && result.startsWith('http')) {
|
|
39
|
-
return result
|
|
40
|
-
} else {
|
|
41
|
-
// Если формат ответа неизвестен, возвращаем весь ответ как строку для отладки
|
|
42
|
-
throw new Error(`Неожиданный формат ответа от imgbox.vu: ${JSON.stringify(result)}`)
|
|
43
|
-
}
|
|
44
|
-
} catch (error: any) {
|
|
45
|
-
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
46
|
-
throw new Error(`Ошибка загрузки изображения на imgbox.vu: ${errorMessage}`)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
package/src/sessions/Session.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { TelegramClient } from 'telegram'
|
|
2
|
-
import { EvogramGramJS } from '../EvogramGramJS'
|
|
3
|
-
import { SessionAuth } from './SessionAuth'
|
|
4
|
-
import { SessionLogger } from './SessionLogger'
|
|
5
|
-
|
|
6
|
-
export class Session {
|
|
7
|
-
/** Объект авторизации для сессии */
|
|
8
|
-
public auth: SessionAuth
|
|
9
|
-
|
|
10
|
-
constructor(public readonly sessionId: string, public readonly client: TelegramClient, public readonly logger: SessionLogger | undefined, auth: SessionAuth) {
|
|
11
|
-
this.auth = auth
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public async db() {
|
|
15
|
-
return (await EvogramGramJS.databaseService.getSession(this.sessionId)) ?? null
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public async user() {
|
|
19
|
-
return await this.client.getMe()
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events'
|
|
2
|
-
import { Api, 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
|
-
* Начинает авторизацию через 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
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Проверяет, требуется ли пароль для авторизации
|
|
348
|
-
*
|
|
349
|
-
* @returns true, если требуется пароль
|
|
350
|
-
*/
|
|
351
|
-
async isRequiredPassword(): Promise<boolean> {
|
|
352
|
-
if (this.state?.isRequiredPassword) return true
|
|
353
|
-
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
354
|
-
return this.state?.isRequiredPassword ?? false
|
|
355
|
-
}
|
|
356
|
-
}
|