@2byte/tgbot-framework 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/README.md +301 -0
- package/bin/2byte-cli.ts +85 -0
- package/package.json +50 -0
- package/src/cli/CreateBotCommand.ts +182 -0
- package/src/cli/GenerateCommand.ts +112 -0
- package/src/cli/InitCommand.ts +108 -0
- package/src/console/migrate.ts +83 -0
- package/src/core/App.ts +1016 -0
- package/src/core/BotArtisan.ts +80 -0
- package/src/core/BotMigration.ts +31 -0
- package/src/core/BotSeeder.ts +67 -0
- package/src/core/utils.ts +3 -0
- package/src/illumination/Artisan.ts +149 -0
- package/src/illumination/InlineKeyboard.ts +44 -0
- package/src/illumination/Message2Byte.ts +254 -0
- package/src/illumination/Message2ByteLiveProgressive.ts +278 -0
- package/src/illumination/Message2bytePool.ts +108 -0
- package/src/illumination/Migration.ts +186 -0
- package/src/illumination/RunSectionRoute.ts +85 -0
- package/src/illumination/Section.ts +430 -0
- package/src/illumination/SectionComponent.ts +64 -0
- package/src/illumination/Telegraf2byteContext.ts +33 -0
- package/src/index.ts +33 -0
- package/src/libs/TelegramAccountControl.ts +523 -0
- package/src/types.ts +172 -0
- package/src/user/UserModel.ts +132 -0
- package/src/user/UserStore.ts +119 -0
- package/templates/bot/.env.example +18 -0
- package/templates/bot/artisan.ts +9 -0
- package/templates/bot/bot.ts +74 -0
- package/templates/bot/database/dbConnector.ts +5 -0
- package/templates/bot/database/migrate.ts +10 -0
- package/templates/bot/database/migrations/001_create_users.sql +17 -0
- package/templates/bot/database/seed.ts +15 -0
- package/templates/bot/package.json +31 -0
- package/templates/bot/sectionList.ts +7 -0
- package/templates/bot/sections/HomeSection.ts +63 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { type Database } from "bun:sqlite";
|
|
2
|
+
import mustache from "mustache";
|
|
3
|
+
import { Markup, Telegraf } from "telegraf";
|
|
4
|
+
import { App } from "../core/App";
|
|
5
|
+
import { MakeManualPaginateButtonsParams, RunnedSection, SectionOptions } from "../types";
|
|
6
|
+
import { InlineKeyboard } from "./InlineKeyboard";
|
|
7
|
+
import Message2byte from "./Message2Byte";
|
|
8
|
+
import Message2bytePool from "./Message2bytePool";
|
|
9
|
+
import { RunSectionRoute } from "./RunSectionRoute";
|
|
10
|
+
import { Telegraf2byteContext } from "./Telegraf2byteContext";
|
|
11
|
+
|
|
12
|
+
export class Section {
|
|
13
|
+
static command: string;
|
|
14
|
+
static description: string;
|
|
15
|
+
static actionRoutes: { [key: string]: string };
|
|
16
|
+
public sectionId: string = "BaseSection";
|
|
17
|
+
public route: RunSectionRoute;
|
|
18
|
+
protected ctx: Telegraf2byteContext;
|
|
19
|
+
protected bot: Telegraf<Telegraf2byteContext>;
|
|
20
|
+
protected app: App;
|
|
21
|
+
protected markup: typeof Markup = Markup;
|
|
22
|
+
protected btnHome = this.markup.button.callback("🏠 Лобби", "home.index");
|
|
23
|
+
protected iconBack: string = "🔙";
|
|
24
|
+
protected iconPlus: string = "➕";
|
|
25
|
+
protected iconDelete: string = "✖️";
|
|
26
|
+
protected iconOk: string = "☑️";
|
|
27
|
+
protected iconInput: string = "⤵️";
|
|
28
|
+
protected iconOutput: string = "⤴️";
|
|
29
|
+
protected iconTime: string = "⏱";
|
|
30
|
+
protected iconCheck: string = "\u{2714}";
|
|
31
|
+
protected iconSet: string = "🔖";
|
|
32
|
+
protected iconRefresh: string = "🔃";
|
|
33
|
+
protected iconHistory: string = "🗂";
|
|
34
|
+
protected iconEuro: string = "💶";
|
|
35
|
+
protected iconRejected: string = "❌";
|
|
36
|
+
protected labelBack: string = `${this.iconBack} Назад`;
|
|
37
|
+
|
|
38
|
+
protected callbackParams: URLSearchParams | null = null;
|
|
39
|
+
protected mustache: typeof mustache = mustache;
|
|
40
|
+
protected mainMenuKeyboardArray: any[][] = [];
|
|
41
|
+
protected db: Database; // Database connection
|
|
42
|
+
|
|
43
|
+
constructor(options: SectionOptions) {
|
|
44
|
+
this.ctx = options.ctx;
|
|
45
|
+
this.bot = options.bot;
|
|
46
|
+
this.app = options.app;
|
|
47
|
+
this.mainMenuKeyboardArray = this.app.config.mainMenuKeyboard;
|
|
48
|
+
this.route = options.route;
|
|
49
|
+
this.db = (global as any).db as Database;
|
|
50
|
+
this.callbackParams = this.parseParamsCallbackdata();
|
|
51
|
+
this.cancelUserWaitingReply();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public async setup(): Promise<void> {}
|
|
55
|
+
public async unsetup(): Promise<void> {}
|
|
56
|
+
|
|
57
|
+
public async up(): Promise<void> {}
|
|
58
|
+
public async down(): Promise<void> {}
|
|
59
|
+
|
|
60
|
+
parseParamsCallbackdata(): URLSearchParams {
|
|
61
|
+
let strparams = this.ctx.update?.callback_query?.data?.match(/\[(.+?)\]/);
|
|
62
|
+
|
|
63
|
+
if (strparams !== null && strparams?.[1] !== undefined) {
|
|
64
|
+
const valueToType = isFinite(Number(strparams[1])) ? +strparams[1] : strparams[1];
|
|
65
|
+
return new URLSearchParams(String(valueToType));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return new URLSearchParams();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
makePaginateButtons(
|
|
72
|
+
metadata: any,
|
|
73
|
+
callbackDataAction: string,
|
|
74
|
+
paramsQuery: Record<string, any> = {}
|
|
75
|
+
): any[][] {
|
|
76
|
+
if (metadata.hasOwnProperty("meta")) metadata = metadata.meta;
|
|
77
|
+
|
|
78
|
+
if (metadata.last_page == 1) return [];
|
|
79
|
+
|
|
80
|
+
const makeActionData = (page: number): string => {
|
|
81
|
+
const params = { ...paramsQuery, page: page.toString() };
|
|
82
|
+
return `${callbackDataAction}[${new URLSearchParams(
|
|
83
|
+
params as Record<string, string>
|
|
84
|
+
).toString()}]`;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const layoutButtons: any[][] = [];
|
|
88
|
+
const pageButtons: any[] = [];
|
|
89
|
+
|
|
90
|
+
const makeButtonCallback = (text: string, callbackData: string): any => {
|
|
91
|
+
return this.markup.button.callback(text, callbackData);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Pair buttons the start and end
|
|
95
|
+
if (metadata.last_page > 1) {
|
|
96
|
+
const lineFirstNext: any[] = [];
|
|
97
|
+
|
|
98
|
+
if (metadata.current_page > 1) {
|
|
99
|
+
lineFirstNext.push(makeButtonCallback("Назад", makeActionData(metadata.current_page - 1)));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (metadata.current_page < metadata.last_page) {
|
|
103
|
+
lineFirstNext.push(makeButtonCallback("Вперед", makeActionData(metadata.current_page + 1)));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
layoutButtons.push(lineFirstNext);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const generatorPageNumber = (startPage: number, lastPage: number): any[] => {
|
|
110
|
+
const buttons: any[] = [];
|
|
111
|
+
|
|
112
|
+
for (let i = startPage, c = 1; i <= lastPage && c <= 8; i++, c++) {
|
|
113
|
+
let btn = makeButtonCallback(`${i}`, makeActionData(i));
|
|
114
|
+
|
|
115
|
+
if (i == metadata.current_page) {
|
|
116
|
+
btn = makeButtonCallback(`\u{2714} ${i}`, makeActionData(metadata.current_page));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
buttons.push(btn);
|
|
120
|
+
|
|
121
|
+
if (startPage + c > metadata.last_page) break;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return buttons;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Page numbers a generator
|
|
128
|
+
if (metadata.last_page > 8) {
|
|
129
|
+
let startPage = 0;
|
|
130
|
+
let lastPage = 0;
|
|
131
|
+
|
|
132
|
+
if (metadata.current_page < 8) {
|
|
133
|
+
startPage = 1;
|
|
134
|
+
lastPage = 8;
|
|
135
|
+
} else {
|
|
136
|
+
startPage = metadata.current_page - 3;
|
|
137
|
+
lastPage = metadata.current_page + 4;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
layoutButtons.push(generatorPageNumber(startPage, lastPage));
|
|
141
|
+
} else {
|
|
142
|
+
layoutButtons.push(generatorPageNumber(1, metadata.last_page));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
layoutButtons.push(pageButtons);
|
|
146
|
+
|
|
147
|
+
// Pair buttons the start and end
|
|
148
|
+
if (metadata.current_page > 1 && metadata.last_page > 8) {
|
|
149
|
+
const lineStartLast: any[] = [];
|
|
150
|
+
|
|
151
|
+
lineStartLast.push(makeButtonCallback("В начало", makeActionData(1)));
|
|
152
|
+
|
|
153
|
+
if (metadata.current_page < metadata.last_page) {
|
|
154
|
+
lineStartLast.push(makeButtonCallback("В конец", makeActionData(metadata.last_page)));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
layoutButtons.push(lineStartLast);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return layoutButtons;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public static makeManualPaginateButtons(params: MakeManualPaginateButtonsParams): any[][] {
|
|
164
|
+
let { callbackDataAction, currentPage, totalRecords, perPage, paramsQuery } = params;
|
|
165
|
+
|
|
166
|
+
currentPage = parseInt(String(currentPage));
|
|
167
|
+
const last_page = Math.ceil(totalRecords / perPage);
|
|
168
|
+
|
|
169
|
+
if (last_page <= 1) return [];
|
|
170
|
+
|
|
171
|
+
const makeActionData = (page: number): string => {
|
|
172
|
+
const params = { ...paramsQuery, page: page.toString() };
|
|
173
|
+
return `${callbackDataAction}[${new URLSearchParams(
|
|
174
|
+
params as Record<string, string>
|
|
175
|
+
).toString()}]`;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const layoutButtons: any[][] = [];
|
|
179
|
+
|
|
180
|
+
const makeButtonCallback = (text: string, callbackData: string): any => {
|
|
181
|
+
return Markup.button.callback(text, callbackData);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Pair buttons the start and end
|
|
185
|
+
if (last_page > 1) {
|
|
186
|
+
const lineFirstNext: any[] = [];
|
|
187
|
+
|
|
188
|
+
if (currentPage > 1) {
|
|
189
|
+
lineFirstNext.push(makeButtonCallback("⬅️ Назад", makeActionData(currentPage - 1)));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (currentPage < last_page) {
|
|
193
|
+
lineFirstNext.push(makeButtonCallback("Вперед ➡️", makeActionData(currentPage + 1)));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
layoutButtons.push(lineFirstNext);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const generatorPageNumber = (startPage: number, lastPage: number): any[] => {
|
|
200
|
+
const buttons: any[] = [];
|
|
201
|
+
|
|
202
|
+
for (let i = startPage, c = 1; i <= lastPage && c <= 8; i++, c++) {
|
|
203
|
+
let btn = makeButtonCallback(`${i}`, makeActionData(i));
|
|
204
|
+
|
|
205
|
+
if (i == currentPage) {
|
|
206
|
+
btn = makeButtonCallback(`\u{2714} ${i}`, makeActionData(currentPage));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
buttons.push(btn);
|
|
210
|
+
|
|
211
|
+
if (startPage + c > last_page) break;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return buttons;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// Page numbers a generator
|
|
218
|
+
if (last_page > 8) {
|
|
219
|
+
let startPage = 0;
|
|
220
|
+
let lastPage = 0;
|
|
221
|
+
|
|
222
|
+
if (currentPage < 8) {
|
|
223
|
+
startPage = 1;
|
|
224
|
+
lastPage = 8;
|
|
225
|
+
} else {
|
|
226
|
+
startPage = currentPage - 3;
|
|
227
|
+
lastPage = currentPage + 4;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
layoutButtons.push(generatorPageNumber(startPage, lastPage));
|
|
231
|
+
} else {
|
|
232
|
+
layoutButtons.push(generatorPageNumber(1, last_page));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Pair buttons the start and end
|
|
236
|
+
if (currentPage > 1 && last_page > 8) {
|
|
237
|
+
const lineStartLast: any[] = [];
|
|
238
|
+
|
|
239
|
+
lineStartLast.push(makeButtonCallback("В начало", makeActionData(1)));
|
|
240
|
+
|
|
241
|
+
if (currentPage < last_page) {
|
|
242
|
+
lineStartLast.push(makeButtonCallback("В конец", makeActionData(last_page)));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
layoutButtons.push(lineStartLast);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return layoutButtons;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
isRepeatedQuery(objParamsNeedle: Record<string, any>): boolean {
|
|
252
|
+
if (!this.callbackParams) return false;
|
|
253
|
+
|
|
254
|
+
const isEquals = Object.keys(objParamsNeedle)
|
|
255
|
+
.map((key) => [key, objParamsNeedle[key]])
|
|
256
|
+
.every((entry) => {
|
|
257
|
+
return this.callbackParams?.get(entry[0]) == entry[1];
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
return isEquals;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async setupKeyboard(): Promise<void> {
|
|
264
|
+
if (this.ctx.userSession.setupKeyboardDone) return;
|
|
265
|
+
|
|
266
|
+
await this.newMessage("Welcome!")
|
|
267
|
+
.keyboard({
|
|
268
|
+
keyboard: this.mainMenuKeyboardArray,
|
|
269
|
+
resize_keyboard: true,
|
|
270
|
+
one_time_keyboard: true,
|
|
271
|
+
})
|
|
272
|
+
.send();
|
|
273
|
+
|
|
274
|
+
this.ctx.userSession.setupKeyboardDone = true;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async getSetting(name: string): Promise<any> {
|
|
278
|
+
try {
|
|
279
|
+
const allSettings = await (global as any).settings;
|
|
280
|
+
|
|
281
|
+
return allSettings.data[name];
|
|
282
|
+
} catch (err) {
|
|
283
|
+
throw err;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
cancelUserWaitingReply(): boolean {
|
|
288
|
+
if (this.callbackParams?.has("cancel_wait")) {
|
|
289
|
+
// Очищаем состояние ожидания ввода
|
|
290
|
+
if (this.ctx.userSession.awaitingInput) {
|
|
291
|
+
delete this.ctx.userSession.awaitingInput;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (this.ctx.userSession.awaitingInputPromise) {
|
|
295
|
+
// Отклоняем Promise с сообщением об отмене
|
|
296
|
+
this.ctx.userSession.awaitingInputPromise.reject(new Error("Ввод отменен пользователем"));
|
|
297
|
+
delete this.ctx.userSession.awaitingInputPromise;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
backInlineButtion(data: string): any {
|
|
307
|
+
return this.markup.button.callback(this.labelBack, data);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
inlineButton(text: string, data: string): any {
|
|
311
|
+
return this.markup.button.callback(text, data);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
setCallbackParams(params: URLSearchParams): this {
|
|
315
|
+
this.callbackParams = params;
|
|
316
|
+
return this;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
existsAnswerInput(inputKey: string): boolean {
|
|
320
|
+
return this.ctx.userSession[inputKey] !== undefined;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
getAnswerInput(inputKey: string): any {
|
|
324
|
+
return this.ctx.userSession[inputKey];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
setAnswerInput(inputKey: string, value: any): void {
|
|
328
|
+
this.ctx.userSession[inputKey] = value;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
makeQueryParams(...args: any[]): URLSearchParams {
|
|
332
|
+
const params = new URLSearchParams();
|
|
333
|
+
|
|
334
|
+
args.forEach((arg) => {
|
|
335
|
+
if (typeof arg === "string") {
|
|
336
|
+
new URLSearchParams(arg).forEach((value, key) => {
|
|
337
|
+
params.set(key, value);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (arg !== null && typeof arg === "object") {
|
|
341
|
+
this.app.debugLog("arg", arg);
|
|
342
|
+
for (const [key, value] of Object.entries(arg)) {
|
|
343
|
+
params.set(key, String(value));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return params;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
makeInlineKeyboard(buttons: any[][]): InlineKeyboard {
|
|
352
|
+
const keyboard = InlineKeyboard.init(this.ctx);
|
|
353
|
+
buttons.forEach((row) => {
|
|
354
|
+
keyboard.append(row);
|
|
355
|
+
});
|
|
356
|
+
return keyboard;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
makeInlineButton(text: string, data: string): any {
|
|
360
|
+
return Markup.button.callback(text, data);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
message(message: string): Message2byte {
|
|
364
|
+
if (this.route.runIsCallbackQuery) {
|
|
365
|
+
return this.updateMessage(message);
|
|
366
|
+
}
|
|
367
|
+
return Message2byte.init(this.ctx, this).message(message);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
newMessage(message: string): Message2byte {
|
|
371
|
+
return Message2byte.init(this.ctx, this).message(message);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
updateMessage(message: string): Message2byte {
|
|
375
|
+
return Message2byte.init(this.ctx, this).updateMessage(message);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
createPoolNewMessage(message: string): Message2bytePool {
|
|
379
|
+
return Message2byte.init(this.ctx, this).createPoolMessage(message);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
createUpdatePoolMessage(message: string): Message2bytePool {
|
|
383
|
+
return Message2byte.init(this.ctx, this).createUpdatePoolMessage(message);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
createPoolMessage(message: string): Message2bytePool {
|
|
387
|
+
return this.route.runIsCallbackQuery
|
|
388
|
+
? this.createUpdatePoolMessage(message)
|
|
389
|
+
: this.createPoolNewMessage(message);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
getCtx(): Telegraf2byteContext {
|
|
393
|
+
return this.ctx;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
getCurrentSection(): RunnedSection {
|
|
397
|
+
return this.app.getRunnedSection(this.ctx.user);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
getPreviousSection(): RunnedSection | undefined {
|
|
401
|
+
return this.ctx.userSession.previousSection;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async sleepProgressBar(messageWait: string, ms: number): Promise<void> {
|
|
405
|
+
const { promise, resolve, reject } = Promise.withResolvers<void>();
|
|
406
|
+
const pgIcons = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
407
|
+
|
|
408
|
+
let pgIndex = 0;
|
|
409
|
+
message += `[pg]${pgIcons[pgIndex]} ${message}`;
|
|
410
|
+
|
|
411
|
+
const pgIntervalTimer = setInterval(() => {
|
|
412
|
+
// Update progress message here
|
|
413
|
+
message = message.replace(/\[pg\].*/, `[pg]${pgIcons[pgIndex]} ${messageWait}`);
|
|
414
|
+
pgIndex = (pgIndex + 1) % pgIcons.length;
|
|
415
|
+
|
|
416
|
+
this.message(message)
|
|
417
|
+
.send()
|
|
418
|
+
.catch((err) => {
|
|
419
|
+
clearInterval(pgIntervalTimer);
|
|
420
|
+
reject(err);
|
|
421
|
+
});
|
|
422
|
+
}, 1000);
|
|
423
|
+
setTimeout(() => {
|
|
424
|
+
message = message.replace(/\[pg\].*/, ``);
|
|
425
|
+
clearInterval(pgIntervalTimer);
|
|
426
|
+
resolve();
|
|
427
|
+
}, ms);
|
|
428
|
+
return promise;
|
|
429
|
+
};
|
|
430
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { TelegrafContextCustom } from './Telegraf2byteContext';
|
|
2
|
+
import { Section } from './Section';
|
|
3
|
+
import { ComponentOptions } from '../types';
|
|
4
|
+
|
|
5
|
+
export class SectionComponent {
|
|
6
|
+
static readonly TYPE_SYNC = 'sync';
|
|
7
|
+
static readonly TYPE_PENDINGS = 'pendings';
|
|
8
|
+
static readonly STATUS_PROCESSED = 'processed';
|
|
9
|
+
static readonly STATUS_PENDING = 'pending';
|
|
10
|
+
|
|
11
|
+
protected _ctx: TelegrafContextCustom;
|
|
12
|
+
protected _app: any; // App instance
|
|
13
|
+
protected _section: Section;
|
|
14
|
+
|
|
15
|
+
protected _type: string = SectionComponent.TYPE_SYNC;
|
|
16
|
+
protected _status: string = SectionComponent.STATUS_PROCESSED;
|
|
17
|
+
|
|
18
|
+
protected _name: string = 'SectionComponent';
|
|
19
|
+
protected _actions: Record<string, string> = {};
|
|
20
|
+
protected _isCallbackQuery: boolean = true;
|
|
21
|
+
|
|
22
|
+
constructor(options: ComponentOptions) {
|
|
23
|
+
this._ctx = options.ctx;
|
|
24
|
+
this._app = options.app;
|
|
25
|
+
this._section = options.section;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static init(options: ComponentOptions): SectionComponent {
|
|
29
|
+
return new this(options);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async default(): Promise<{ text: string, [key: string]: any }> {
|
|
33
|
+
return { text: 'Section component' };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async run(): Promise<any> {
|
|
37
|
+
// this._app.registerComponent(this);
|
|
38
|
+
|
|
39
|
+
switch (this._type) {
|
|
40
|
+
case SectionComponent.TYPE_PENDINGS:
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
default:
|
|
44
|
+
return this.default();
|
|
45
|
+
}
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get name(): string {
|
|
50
|
+
return this._name;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get actions(): Record<string, string> {
|
|
54
|
+
return this._actions;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get type(): string {
|
|
58
|
+
return this._type;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get status(): string {
|
|
62
|
+
return this._status;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Context } from 'telegraf';
|
|
2
|
+
import { UserModel } from '../user/UserModel';
|
|
3
|
+
import { UserStore } from '../user/UserStore';
|
|
4
|
+
import { UserSession } from '../types';
|
|
5
|
+
|
|
6
|
+
export interface ITelegraf2byteContextExtraMethods {
|
|
7
|
+
deleteLastMessage(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Telegraf2byteContext extends Context, ITelegraf2byteContextExtraMethods {
|
|
11
|
+
user: UserModel;
|
|
12
|
+
userStorage: UserStore;
|
|
13
|
+
userSession: UserSession;
|
|
14
|
+
// msgId?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const Telegraf2byteContextExtraMethods = {
|
|
18
|
+
async deleteLastMessage(this: Telegraf2byteContext): Promise<void> {
|
|
19
|
+
const lastMessageId = this.user.lastMessageId;
|
|
20
|
+
if (lastMessageId) {
|
|
21
|
+
try {
|
|
22
|
+
|
|
23
|
+
console.log('Deleting last message with ID:', lastMessageId);
|
|
24
|
+
|
|
25
|
+
await this.deleteMessage(lastMessageId);
|
|
26
|
+
|
|
27
|
+
this.user.removeMessageId(lastMessageId);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error('Failed to delete last message:', error)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Core classes
|
|
2
|
+
export { App } from './core/App';
|
|
3
|
+
export { BotArtisan } from './core/BotArtisan';
|
|
4
|
+
export { BotMigration } from './core/BotMigration';
|
|
5
|
+
export { BotSeeder } from './core/BotSeeder';
|
|
6
|
+
|
|
7
|
+
// Framework classes
|
|
8
|
+
export { Section } from './illumination/Section';
|
|
9
|
+
export { Artisan } from './illumination/Artisan';
|
|
10
|
+
export { Migration } from './illumination/Migration';
|
|
11
|
+
export { InlineKeyboard } from './illumination/InlineKeyboard';
|
|
12
|
+
export { default as Message2Byte } from './illumination/Message2Byte';
|
|
13
|
+
export { RunSectionRoute } from './illumination/RunSectionRoute';
|
|
14
|
+
export { SectionComponent } from './illumination/SectionComponent';
|
|
15
|
+
export type { Telegraf2byteContext } from './illumination/Telegraf2byteContext';
|
|
16
|
+
|
|
17
|
+
// Console utilities
|
|
18
|
+
export { setupMigrations } from './console/migrate';
|
|
19
|
+
|
|
20
|
+
// Types
|
|
21
|
+
export * from './types';
|
|
22
|
+
|
|
23
|
+
// CLI Commands (for internal use)
|
|
24
|
+
export { CreateBotCommand } from './cli/CreateBotCommand';
|
|
25
|
+
export { InitCommand } from './cli/InitCommand';
|
|
26
|
+
export { GenerateCommand } from './cli/GenerateCommand';
|
|
27
|
+
|
|
28
|
+
// User exports
|
|
29
|
+
export { UserModel } from './user/UserModel';
|
|
30
|
+
export { UserStore } from './user/UserStore';
|
|
31
|
+
|
|
32
|
+
// Type exports
|
|
33
|
+
export * from './types';
|