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.
- package/.evogram/7878190870/database.db +0 -0
- 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 +90 -0
- package/lib/commands/AddAccount.command.d.ts +6 -0
- package/lib/commands/AddAccount.command.js +170 -0
- package/lib/commands/index.d.ts +0 -0
- package/lib/commands/index.js +1 -0
- package/lib/commands/managment/DeleteAccount.command.d.ts +0 -0
- package/lib/commands/managment/DeleteAccount.command.js +12 -0
- 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 +62 -0
- package/lib/sessions/SessionAuth.js +165 -0
- package/lib/sessions/SessionLogger.d.ts +84 -0
- package/lib/sessions/SessionLogger.js +196 -0
- package/lib/sessions/SessionManager.d.ts +79 -0
- package/lib/sessions/SessionManager.js +184 -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-lock.json +6 -0
- package/package.json +27 -0
- package/src/EvogramGramJS.ts +98 -0
- package/src/commands/Accounts.command.ts +84 -0
- package/src/commands/AddAccount.command.ts +171 -0
- package/src/commands/index.ts +0 -0
- package/src/commands/managment/DeleteAccount.command.ts +13 -0
- package/src/config/database.config.ts +75 -0
- package/src/entities/Session.entity.ts +58 -0
- package/src/entities/SessionEventLog.entity.ts +41 -0
- package/src/index.ts +7 -0
- package/src/services/DatabaseService.ts +82 -0
- package/src/services/ImageUploadService.ts +49 -0
- package/src/sessions/Session.ts +21 -0
- package/src/sessions/SessionAuth.ts +173 -0
- package/src/sessions/SessionLogger.ts +208 -0
- package/src/sessions/SessionManager.ts +190 -0
- package/src/types/auth.types.ts +94 -0
- package/src/types/session.types.ts +96 -0
- package/src/utils/Deferrer.ts +12 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Command, CommandContext, CommandD, CommandStorageArgument, CommandUpdate, MessageContext } from 'evogram'
|
|
2
|
+
import { EvogramGramJS } from '../EvogramGramJS'
|
|
3
|
+
import { AuthState } from '../types/auth.types'
|
|
4
|
+
|
|
5
|
+
@CommandD({ name: 'addaccount', argsMethod: 'parameterized', backButton: 'Список аккаунтов' })
|
|
6
|
+
export class AddAccountCommand extends Command {
|
|
7
|
+
public async execute(
|
|
8
|
+
context: CommandContext,
|
|
9
|
+
@CommandStorageArgument('phone', async ({ context, value }) => {
|
|
10
|
+
if (value) {
|
|
11
|
+
if (!(await context.storage.get('session'))) {
|
|
12
|
+
const session = await EvogramGramJS.sessionManager.addSession({
|
|
13
|
+
sessionId: value,
|
|
14
|
+
logging: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
logsDirectory: './logs',
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const result = await session.auth.start(value)
|
|
21
|
+
if (result.success) {
|
|
22
|
+
await context.storage.set('stage', 'code')
|
|
23
|
+
await context.storage.set('session', session.sessionId)
|
|
24
|
+
|
|
25
|
+
return value
|
|
26
|
+
} else {
|
|
27
|
+
context.state.command = undefined
|
|
28
|
+
await context.storage.clearAll()
|
|
29
|
+
|
|
30
|
+
//@ts-ignore
|
|
31
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
32
|
+
// prettier-ignore
|
|
33
|
+
text:
|
|
34
|
+
'<blockquote><b>❗️Произошла ошибка при добавлении аккаунта</b></blockquote>\n\n' +
|
|
35
|
+
|
|
36
|
+
result.error,
|
|
37
|
+
parse_mode: 'HTML',
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
} else return value
|
|
41
|
+
} else {
|
|
42
|
+
//@ts-ignore
|
|
43
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
44
|
+
// prettier-ignore
|
|
45
|
+
text:
|
|
46
|
+
'<blockquote><b>➕ Добавление аккаунта</b></blockquote>\n\n' +
|
|
47
|
+
|
|
48
|
+
'<i>Отправьте номер телефона в следующем сообщении</i>',
|
|
49
|
+
parse_mode: 'HTML',
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
phone: string,
|
|
54
|
+
@CommandStorageArgument('code', async ({ context, value }) => {
|
|
55
|
+
if (value) {
|
|
56
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
57
|
+
if (session.auth.state?.stage !== AuthState.WAITING_CODE) return value
|
|
58
|
+
|
|
59
|
+
const result = await session.auth.setCode(value)
|
|
60
|
+
|
|
61
|
+
if (result.success) {
|
|
62
|
+
await context.storage.set('stage', 'password')
|
|
63
|
+
return value
|
|
64
|
+
} else {
|
|
65
|
+
//@ts-ignore
|
|
66
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
67
|
+
// prettier-ignore
|
|
68
|
+
text:
|
|
69
|
+
'<blockquote><b>➕ Добавление аккаунта</b></blockquote>\n\n' +
|
|
70
|
+
|
|
71
|
+
'<i>Отправьте код подтверждения, отправленный на аккаунт, в следующем сообщении</i>\n\n' +
|
|
72
|
+
|
|
73
|
+
`<blockquote><b>❗️Произошла ошибка</b></blockquote>\n\n` +
|
|
74
|
+
|
|
75
|
+
result.error,
|
|
76
|
+
parse_mode: 'HTML',
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
//@ts-ignore
|
|
83
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
84
|
+
// prettier-ignore
|
|
85
|
+
text:
|
|
86
|
+
'<blockquote><b>➕ Добавление аккаунта</b></blockquote>\n\n' +
|
|
87
|
+
|
|
88
|
+
'<i>Отправьте код подтверждения, отправленный на аккаунт, в следующем сообщении</i>',
|
|
89
|
+
parse_mode: 'HTML',
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
code: string,
|
|
94
|
+
@CommandStorageArgument('password', async ({ context, value }) => {
|
|
95
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
96
|
+
|
|
97
|
+
const isRequired = await session.auth.isRequiredPassword()
|
|
98
|
+
if (!isRequired || value === 'none') return 'none'
|
|
99
|
+
|
|
100
|
+
if (value) {
|
|
101
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
102
|
+
const result = await session.auth.setPassword(value)
|
|
103
|
+
|
|
104
|
+
if (result.success) {
|
|
105
|
+
return value
|
|
106
|
+
} else {
|
|
107
|
+
//@ts-ignore
|
|
108
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
109
|
+
// prettier-ignore
|
|
110
|
+
text:
|
|
111
|
+
'<blockquote><b>➕ Добавление аккаунта</b></blockquote>\n\n' +
|
|
112
|
+
|
|
113
|
+
'<i>На аккаунте включен 2FA. Отправьте пароль для 2FA в следующем сообщении</i>\n\n' +
|
|
114
|
+
|
|
115
|
+
`<blockquote><b>❗️Произошла ошибка</b></blockquote>\n\n` +
|
|
116
|
+
|
|
117
|
+
result.error,
|
|
118
|
+
parse_mode: 'HTML',
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
//@ts-ignore
|
|
123
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
124
|
+
// prettier-ignore
|
|
125
|
+
text:
|
|
126
|
+
'<blockquote><b>➕ Добавление аккаунта</b></blockquote>\n\n' +
|
|
127
|
+
|
|
128
|
+
'<i>На аккаунте включен 2FA. Отправьте пароль для 2FA в следующем сообщении</i>',
|
|
129
|
+
parse_mode: 'HTML',
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
password: string
|
|
134
|
+
) {
|
|
135
|
+
const session = EvogramGramJS.sessionManager.getSession(await context.storage.get('session'))!
|
|
136
|
+
|
|
137
|
+
context.send(
|
|
138
|
+
`Вы успешно добавили аккаунт ${await session.client
|
|
139
|
+
.getMe()
|
|
140
|
+
.then((user) => user.username)
|
|
141
|
+
.catch(() => 'unknown')}`
|
|
142
|
+
)
|
|
143
|
+
await context.storage.clearAll()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@CommandUpdate('message')
|
|
147
|
+
async handleMessage(context: CommandContext, message: MessageContext) {
|
|
148
|
+
if (!message?.text) return
|
|
149
|
+
|
|
150
|
+
console.log({ session: await context.storage.get('session'), phone: await context.storage.get('phone'), code: await context.storage.get('code'), password: await context.storage.get('password'), command: context.state.command, stage: await context.storage.get('stage') })
|
|
151
|
+
|
|
152
|
+
await context.edit('⏳').catch(() => {})
|
|
153
|
+
await message.delete().catch(() => {})
|
|
154
|
+
|
|
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 })
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
onError(context: CommandContext, error: Error) {
|
|
161
|
+
//@ts-ignore
|
|
162
|
+
context[context.callbackQuery ? 'edit' : 'send']?.({
|
|
163
|
+
// prettier-ignore
|
|
164
|
+
text:
|
|
165
|
+
'<blockquote><b>❗️Произошла ошибка при добавлении аккаунта</b></blockquote>\n\n' +
|
|
166
|
+
|
|
167
|
+
error.message,
|
|
168
|
+
parse_mode: 'HTML',
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// import { Command, CommandArgument, CommandContext, CommandD } from 'evogram'
|
|
2
|
+
// import { EvogramGramJS } from '../../EvogramGramJS'
|
|
3
|
+
|
|
4
|
+
// @CommandD({ name: 'deleteaccount', argsMethod: 'parameterized' })
|
|
5
|
+
// export class DeleteAccountCommand extends Command {
|
|
6
|
+
// public async execute(context: CommandContext, @CommandArgument('sessionId') sessionId: string) {
|
|
7
|
+
// const session = EvogramGramJS.sessionManager.getSession(sessionId)
|
|
8
|
+
// if (!session) return context.send('Сессия не найдена')
|
|
9
|
+
|
|
10
|
+
// await EvogramGramJS.databaseService.deleteSession(sessionId)
|
|
11
|
+
// return context.send('Сессия успешно удалена')
|
|
12
|
+
// }
|
|
13
|
+
// }
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DataSourceOptions } from 'typeorm'
|
|
2
|
+
import { Session } from '../entities/Session.entity'
|
|
3
|
+
import { SessionEventLog } from '../entities/SessionEventLog.entity'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Конфигурация базы данных
|
|
7
|
+
*/
|
|
8
|
+
export interface DatabaseConfig {
|
|
9
|
+
/** Тип базы данных */
|
|
10
|
+
type?: 'sqlite' | 'postgres' | 'mysql' | 'mariadb'
|
|
11
|
+
/** Путь к файлу БД (для SQLite) или строка подключения */
|
|
12
|
+
database?: string
|
|
13
|
+
/** Хост БД (для PostgreSQL/MySQL) */
|
|
14
|
+
host?: string
|
|
15
|
+
/** Порт БД (для PostgreSQL/MySQL) */
|
|
16
|
+
port?: number
|
|
17
|
+
/** Имя пользователя БД */
|
|
18
|
+
username?: string
|
|
19
|
+
/** Пароль БД */
|
|
20
|
+
password?: string
|
|
21
|
+
/** Включить синхронизацию схемы (только для разработки) */
|
|
22
|
+
synchronize?: boolean
|
|
23
|
+
/** Включить логирование SQL запросов */
|
|
24
|
+
logging?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Создает конфигурацию DataSource для TypeORM
|
|
29
|
+
*/
|
|
30
|
+
export function createDataSourceOptions(config: DatabaseConfig = {}): DataSourceOptions {
|
|
31
|
+
const { type = 'sqlite', database = './data/evogram.db', host, port, username, password, synchronize = false, logging = false } = config
|
|
32
|
+
|
|
33
|
+
const baseOptions: DataSourceOptions = {
|
|
34
|
+
type: type as any,
|
|
35
|
+
entities: [Session, SessionEventLog],
|
|
36
|
+
synchronize,
|
|
37
|
+
logging,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (type === 'sqlite') {
|
|
41
|
+
// Для SQLite используем специальную конфигурацию
|
|
42
|
+
const sqliteOptions: any = {
|
|
43
|
+
...baseOptions,
|
|
44
|
+
type: 'better-sqlite3',
|
|
45
|
+
database,
|
|
46
|
+
}
|
|
47
|
+
return sqliteOptions as DataSourceOptions
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (type === 'postgres') {
|
|
51
|
+
return {
|
|
52
|
+
...baseOptions,
|
|
53
|
+
type: 'postgres',
|
|
54
|
+
host: host || 'localhost',
|
|
55
|
+
port: port || 5432,
|
|
56
|
+
username,
|
|
57
|
+
password,
|
|
58
|
+
database: database || 'evogram',
|
|
59
|
+
} as DataSourceOptions
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (type === 'mysql' || type === 'mariadb') {
|
|
63
|
+
return {
|
|
64
|
+
...baseOptions,
|
|
65
|
+
type: type === 'mariadb' ? 'mariadb' : 'mysql',
|
|
66
|
+
host: host || 'localhost',
|
|
67
|
+
port: port || 3306,
|
|
68
|
+
username,
|
|
69
|
+
password,
|
|
70
|
+
database: database || 'evogram',
|
|
71
|
+
} as DataSourceOptions
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return baseOptions
|
|
75
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Column, CreateDateColumn, Entity, OneToMany, PrimaryColumn } from 'typeorm'
|
|
2
|
+
import { SessionEventLog } from './SessionEventLog.entity'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Сущность сессии Telegram в базе данных
|
|
6
|
+
*/
|
|
7
|
+
@Entity('sessions')
|
|
8
|
+
export class Session {
|
|
9
|
+
/** Уникальный идентификатор сессии */
|
|
10
|
+
@PrimaryColumn({ type: 'varchar', length: 255 })
|
|
11
|
+
sessionId!: string
|
|
12
|
+
|
|
13
|
+
/** API ID из Telegram */
|
|
14
|
+
@Column({ type: 'integer', nullable: true })
|
|
15
|
+
apiId?: number
|
|
16
|
+
|
|
17
|
+
/** API Hash из Telegram */
|
|
18
|
+
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
19
|
+
apiHash?: string
|
|
20
|
+
|
|
21
|
+
@Column({ type: 'bigint' })
|
|
22
|
+
userId!: number
|
|
23
|
+
|
|
24
|
+
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
25
|
+
username?: string
|
|
26
|
+
|
|
27
|
+
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
28
|
+
firstName?: string
|
|
29
|
+
|
|
30
|
+
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
31
|
+
lastName?: string
|
|
32
|
+
|
|
33
|
+
@Column({ type: 'varchar', length: 255, nullable: true })
|
|
34
|
+
phoneNumber?: string
|
|
35
|
+
|
|
36
|
+
@Column({ type: 'text', nullable: true })
|
|
37
|
+
error?: string
|
|
38
|
+
|
|
39
|
+
/** Строка сессии (зашифрованная) */
|
|
40
|
+
@Column({ type: 'text', nullable: true })
|
|
41
|
+
sessionString?: string
|
|
42
|
+
|
|
43
|
+
/** Дополнительные опции клиента (JSON) */
|
|
44
|
+
@Column({ type: 'text', nullable: true })
|
|
45
|
+
clientOptions?: string
|
|
46
|
+
|
|
47
|
+
/** URL аватарки пользователя */
|
|
48
|
+
@Column({ type: 'varchar', length: 500, nullable: true })
|
|
49
|
+
avatarUrl?: string
|
|
50
|
+
|
|
51
|
+
/** Связанные события сессии */
|
|
52
|
+
@OneToMany(() => SessionEventLog, (eventLog) => eventLog.session, { cascade: true })
|
|
53
|
+
eventLogs!: SessionEventLog[]
|
|
54
|
+
|
|
55
|
+
/** Время создания сессии */
|
|
56
|
+
@CreateDateColumn()
|
|
57
|
+
createdAt!: Date
|
|
58
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
|
|
2
|
+
import { Session } from './Session.entity'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Сущность для логирования событий сессии
|
|
6
|
+
*/
|
|
7
|
+
@Entity('session_event_logs')
|
|
8
|
+
export class SessionEventLog {
|
|
9
|
+
/** Уникальный идентификатор записи */
|
|
10
|
+
@PrimaryGeneratedColumn()
|
|
11
|
+
id!: number
|
|
12
|
+
|
|
13
|
+
/** Идентификатор сессии */
|
|
14
|
+
@Column({ type: 'varchar', length: 255 })
|
|
15
|
+
sessionId!: string
|
|
16
|
+
|
|
17
|
+
/** Тип события */
|
|
18
|
+
@Column({ type: 'varchar', length: 100 })
|
|
19
|
+
eventType!: string
|
|
20
|
+
|
|
21
|
+
/** Уровень логирования */
|
|
22
|
+
@Column({ type: 'varchar', length: 20, default: 'INFO' })
|
|
23
|
+
level!: string
|
|
24
|
+
|
|
25
|
+
/** Сообщение события */
|
|
26
|
+
@Column({ type: 'text' })
|
|
27
|
+
message!: string
|
|
28
|
+
|
|
29
|
+
/** Дополнительные данные события (JSON) */
|
|
30
|
+
@Column({ type: 'text', nullable: true })
|
|
31
|
+
data?: string
|
|
32
|
+
|
|
33
|
+
/** Время создания события */
|
|
34
|
+
@CreateDateColumn()
|
|
35
|
+
createdAt!: Date
|
|
36
|
+
|
|
37
|
+
/** Связь с сессией */
|
|
38
|
+
@ManyToOne(() => Session, (session) => session.eventLogs, { onDelete: 'CASCADE' })
|
|
39
|
+
@JoinColumn({ name: 'sessionId' })
|
|
40
|
+
session!: Session
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './EvogramGramJS'
|
|
2
|
+
export * from './config/database.config'
|
|
3
|
+
export * from './entities/Session.entity'
|
|
4
|
+
export * from './entities/SessionEventLog.entity'
|
|
5
|
+
export * from './services/DatabaseService'
|
|
6
|
+
export * from './types/auth.types'
|
|
7
|
+
export * from './types/session.types'
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
}
|