@2byte/tgbot-framework 1.0.6 → 1.0.7

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 (58) hide show
  1. package/README.md +300 -300
  2. package/bin/2byte-cli.ts +97 -97
  3. package/package.json +54 -54
  4. package/src/cli/CreateBotCommand.ts +181 -181
  5. package/src/cli/GenerateCommand.ts +195 -195
  6. package/src/cli/InitCommand.ts +107 -107
  7. package/src/cli/TgAccountManager.ts +50 -50
  8. package/src/console/migrate.ts +82 -82
  9. package/src/core/ApiService.ts +20 -20
  10. package/src/core/ApiServiceManager.ts +63 -63
  11. package/src/core/App.ts +1157 -1143
  12. package/src/core/BotArtisan.ts +79 -79
  13. package/src/core/BotMigration.ts +30 -30
  14. package/src/core/BotSeeder.ts +66 -66
  15. package/src/core/Model.ts +84 -84
  16. package/src/core/utils.ts +2 -2
  17. package/src/illumination/Artisan.ts +149 -149
  18. package/src/illumination/InlineKeyboard.ts +61 -61
  19. package/src/illumination/Message2Byte.ts +255 -255
  20. package/src/illumination/Message2ByteLiveProgressive.ts +278 -278
  21. package/src/illumination/Message2bytePool.ts +107 -107
  22. package/src/illumination/Migration.ts +186 -186
  23. package/src/illumination/RunSectionRoute.ts +85 -85
  24. package/src/illumination/Section.ts +410 -410
  25. package/src/illumination/SectionComponent.ts +64 -64
  26. package/src/illumination/Telegraf2byteContext.ts +32 -32
  27. package/src/index.ts +42 -42
  28. package/src/libs/TelegramAccountControl.ts +1140 -1140
  29. package/src/libs/TgSender.ts +53 -53
  30. package/src/models/Model.ts +67 -67
  31. package/src/models/Proxy.ts +217 -217
  32. package/src/models/TgAccount.ts +362 -362
  33. package/src/models/index.ts +2 -2
  34. package/src/types.ts +191 -191
  35. package/src/user/UserModel.ts +297 -297
  36. package/src/user/UserStore.ts +119 -119
  37. package/src/workflow/services/MassSendApiService.ts +80 -80
  38. package/templates/bot/.env.example +33 -33
  39. package/templates/bot/artisan.ts +8 -8
  40. package/templates/bot/bot.ts +82 -82
  41. package/templates/bot/database/dbConnector.ts +4 -4
  42. package/templates/bot/database/migrate.ts +9 -9
  43. package/templates/bot/database/migrations/001_create_users.sql +18 -18
  44. package/templates/bot/database/migrations/007_proxy.sql +27 -27
  45. package/templates/bot/database/migrations/008_tg_accounts.sql +32 -32
  46. package/templates/bot/database/seed.ts +14 -14
  47. package/templates/bot/docs/CLI_SERVICES.md +536 -536
  48. package/templates/bot/docs/INPUT_SYSTEM.md +211 -211
  49. package/templates/bot/docs/SERVICE_EXAMPLES.md +384 -384
  50. package/templates/bot/docs/TASK_SYSTEM.md +156 -156
  51. package/templates/bot/models/Model.ts +7 -7
  52. package/templates/bot/models/index.ts +1 -1
  53. package/templates/bot/package.json +30 -30
  54. package/templates/bot/sectionList.ts +9 -9
  55. package/templates/bot/sections/ExampleInputSection.ts +85 -85
  56. package/templates/bot/sections/ExampleLiveTaskerSection.ts +60 -60
  57. package/templates/bot/sections/HomeSection.ts +63 -63
  58. package/templates/bot/workflow/services/ExampleService.ts +23 -23
@@ -1,255 +1,255 @@
1
- import { Telegraf2byteContext } from "./Telegraf2byteContext";
2
- import { Input, Markup } from "telegraf";
3
- import type { ReplyKeyboardMarkup } from 'telegraf/core/types/telegram';
4
- import { InlineKeyboard } from "./InlineKeyboard";
5
- import { RequestInputOptions } from "../types";
6
- import { Message } from "telegraf/types";
7
- import Message2bytePool from "./Message2bytePool";
8
- import { Section } from "./Section";
9
-
10
- export default class Message2byte {
11
- public messageValue: string = "";
12
- public messageExtra: any = {};
13
- public isUpdate: boolean = false;
14
- private ctx: Telegraf2byteContext;
15
- private imagePath: string | null = null;
16
- private imageCaption: string | null = null;
17
- private messageId: number | null = null;
18
- private doAnswerCbQuery: boolean = true;
19
- private section: Section;
20
-
21
- constructor(ctx: Telegraf2byteContext, section: Section) {
22
- this.ctx = ctx;
23
- this.section = section;
24
- }
25
-
26
- static init(ctx: Telegraf2byteContext, section: Section) {
27
- return new Message2byte(ctx, section);
28
- }
29
-
30
- setNotAnswerCbQuery(): this {
31
- this.doAnswerCbQuery = false;
32
- return this;
33
- }
34
-
35
- message(message: string): this {
36
- this.messageValue = message;
37
- return this;
38
- }
39
-
40
- createPoolMessage(message: string): Message2bytePool {
41
- this.doAnswerCbQuery = false;
42
- this.messageValue = message;
43
- return Message2bytePool.init(this, this.ctx, this.section);
44
- }
45
-
46
- createUpdatePoolMessage(message: string): Message2bytePool {
47
- this.isUpdate = true;
48
- this.messageValue = message;
49
- return Message2bytePool.init(this, this.ctx, this.section);
50
- }
51
-
52
- updateMessage(message: string): this {
53
- this.messageValue = message;
54
- this.isUpdate = true;
55
- this.messageExtra.message_id &&= this.messageId;
56
- return this;
57
- }
58
-
59
- markdown(): this {
60
- this.messageExtra.parse_mode = "markdown";
61
- return this;
62
- }
63
-
64
- html(): this {
65
- this.messageExtra.parse_mode = "html";
66
- return this;
67
- }
68
-
69
- extra(extra: Object): this {
70
- this.messageExtra = extra;
71
- return this;
72
- }
73
-
74
- keyboard(keyboard: ReplyKeyboardMarkup): this {
75
- this.messageExtra.reply_markup = {
76
- keyboard: keyboard.keyboard,
77
- resize_keyboard: keyboard.resize_keyboard,
78
- one_time_keyboard: keyboard.one_time_keyboard,
79
- };
80
- return this;
81
- }
82
-
83
- inlineKeyboard(keyboard: any[][] | InlineKeyboard) {
84
- let keyboardArray: any[][];
85
-
86
- if (keyboard instanceof InlineKeyboard) {
87
- keyboardArray = keyboard.valueOf();
88
- } else {
89
- keyboardArray = keyboard;
90
- }
91
-
92
- Object.assign(this.messageExtra, {
93
- ...Markup.inlineKeyboard(keyboardArray),
94
- });
95
-
96
- return this;
97
- }
98
-
99
- requestInput(inputKey: string, options: RequestInputOptions = {}): this {
100
- // Устанавливаем значения по умолчанию
101
- const allowCancel = options.allowCancel !== false; // по умолчанию true
102
- const cancelButtonText = options.cancelButtonText || "Отмена";
103
- const cancelAction = options.cancelAction || "home.index[cancel_wait=1]";
104
-
105
- // Если разрешена отмена, добавляем кнопку отмены к клавиатуре
106
- if (allowCancel && this.messageExtra && "reply_markup" in this.messageExtra) {
107
- const replyMarkup = (this.messageExtra as any).reply_markup;
108
- if (replyMarkup && replyMarkup.inline_keyboard) {
109
- // Добавляем кнопку отмены в начало клавиатуры
110
- replyMarkup.inline_keyboard.unshift([
111
- {
112
- text: `❌ ${cancelButtonText}`,
113
- callback_data: cancelAction,
114
- },
115
- ]);
116
- }
117
- }
118
-
119
- // Сохраняем информацию о запрашиваемом вводе в сессии пользователя
120
- this.ctx.userSession.awaitingInput = {
121
- key: inputKey,
122
- validator: options.validator,
123
- errorMessage: options.errorMessage || "Неверный формат ввода",
124
- allowCancel,
125
- cancelButtonText: `❌ ${cancelButtonText}`,
126
- cancelAction,
127
- fileValidation: options.fileValidation,
128
- runSection: options.runSection,
129
- retryCount: 0,
130
- };
131
-
132
- return this;
133
- }
134
-
135
- async requestInputWithAwait(
136
- inputKey: string,
137
- options: RequestInputOptions = {}
138
- ): Promise<string | any> {
139
- // Устанавливаем значения по умолчанию
140
- const allowCancel = options.allowCancel !== false; // по умолчанию true
141
- const cancelButtonText = options.cancelButtonText || "Отмена";
142
- const cancelAction = options.cancelAction || "home.index[cancel_wait=1]";
143
-
144
- // Если разрешена отмена, добавляем кнопку отмены к клавиатуре
145
- if (allowCancel && this.messageExtra && "reply_markup" in this.messageExtra) {
146
- const replyMarkup = (this.messageExtra as any).reply_markup;
147
- if (replyMarkup && replyMarkup.inline_keyboard) {
148
- // Добавляем кнопку отмены в начало клавиатуры
149
- replyMarkup.inline_keyboard.unshift([
150
- {
151
- text: `❌ ${cancelButtonText}`,
152
- callback_data: cancelAction,
153
- },
154
- ]);
155
- }
156
- }
157
-
158
- // Отправляем сообщение
159
- await this.send();
160
-
161
- // Возвращаем Promise, который будет разрешен когда пользователь введет данные
162
- return new Promise((resolve, reject) => {
163
- this.ctx.userSession.awaitingInputPromise = {
164
- key: inputKey,
165
- validator: options.validator,
166
- errorMessage: options.errorMessage || "Неверный формат ввода",
167
- allowCancel,
168
- cancelButtonText: `❌ ${cancelButtonText}`,
169
- cancelAction,
170
- fileValidation: options.fileValidation,
171
- retryCount: 0,
172
- resolve,
173
- reject,
174
- };
175
- });
176
- }
177
-
178
- image(pathImage: string): this {
179
- this.imagePath = pathImage;
180
- this.imageCaption = this.messageValue;
181
- this.messageExtra.caption = this.imageCaption;
182
- return this;
183
- }
184
-
185
- editMessageCaption(message: string, extra: any = {}) {
186
- return this.ctx.editMessageCaption(message, extra);
187
- }
188
-
189
- editMessageText(message: string, extra: any = {}) {
190
- return this.ctx.editMessageText(message, extra);
191
- }
192
-
193
- async send() {
194
- // console.log("Sending message:", this.messageValue, ' Extra:', this.messageExtra, 'IsUpdate:', this.isUpdate);
195
- if (this.isUpdate) {
196
- if (this.section.route.runIsCallbackQuery && this.doAnswerCbQuery) {
197
- await this.ctx.answerCbQuery();
198
- }
199
-
200
- const message = this.ctx.callbackQuery?.message as Message;
201
-
202
- if (message) {
203
- if ('media_group_id' in message || 'caption' in message) {
204
- const editMessageCaption = this.editMessageCaption(this.messageValue, this.messageExtra);
205
-
206
- if (editMessageCaption && 'message_id' in editMessageCaption) {
207
- this.messageId = editMessageCaption.message_id as number;
208
- }
209
-
210
- return editMessageCaption;
211
- } else {
212
-
213
- const editedText = this.editMessageText(this.messageValue, this.messageExtra);
214
-
215
- if (editedText && 'message_id' in editedText) {
216
- this.messageId = editedText.message_id as number;
217
- }
218
-
219
- return editedText;
220
- }
221
- } else {
222
- this.messageExtra.message_id = this.messageId;
223
-
224
- const messageEntity = await this.editMessageText(this.messageValue, this.messageExtra);
225
-
226
- if (typeof messageEntity === "object" && 'message_id' in messageEntity) {
227
- this.messageId = messageEntity.message_id as number;
228
- }
229
-
230
- return messageEntity;
231
- }
232
- }
233
-
234
- if (this.imagePath) {
235
- return this.ctx.replyWithPhoto(Input.fromLocalFile(this.imagePath), this.messageExtra);
236
- }
237
-
238
- const replyEntity = this.ctx.reply(this.messageValue, this.messageExtra);
239
-
240
- this.messageId = (await replyEntity).message_id;
241
-
242
- return replyEntity;
243
- }
244
-
245
- sendReturnThis(): this {
246
- this.send();
247
- return this;
248
- }
249
-
250
- setMessageId(messageId: number): this {
251
- this.messageId = messageId;
252
- this.messageExtra.message_id = messageId;
253
- return this;
254
- }
255
- }
1
+ import { Telegraf2byteContext } from "./Telegraf2byteContext";
2
+ import { Input, Markup } from "telegraf";
3
+ import type { ReplyKeyboardMarkup } from 'telegraf/core/types/telegram';
4
+ import { InlineKeyboard } from "./InlineKeyboard";
5
+ import { RequestInputOptions } from "../types";
6
+ import { Message } from "telegraf/types";
7
+ import Message2bytePool from "./Message2bytePool";
8
+ import { Section } from "./Section";
9
+
10
+ export default class Message2byte {
11
+ public messageValue: string = "";
12
+ public messageExtra: any = {};
13
+ public isUpdate: boolean = false;
14
+ private ctx: Telegraf2byteContext;
15
+ private imagePath: string | null = null;
16
+ private imageCaption: string | null = null;
17
+ private messageId: number | null = null;
18
+ private doAnswerCbQuery: boolean = true;
19
+ private section: Section;
20
+
21
+ constructor(ctx: Telegraf2byteContext, section: Section) {
22
+ this.ctx = ctx;
23
+ this.section = section;
24
+ }
25
+
26
+ static init(ctx: Telegraf2byteContext, section: Section) {
27
+ return new Message2byte(ctx, section);
28
+ }
29
+
30
+ setNotAnswerCbQuery(): this {
31
+ this.doAnswerCbQuery = false;
32
+ return this;
33
+ }
34
+
35
+ message(message: string): this {
36
+ this.messageValue = message;
37
+ return this;
38
+ }
39
+
40
+ createPoolMessage(message: string): Message2bytePool {
41
+ this.doAnswerCbQuery = false;
42
+ this.messageValue = message;
43
+ return Message2bytePool.init(this, this.ctx, this.section);
44
+ }
45
+
46
+ createUpdatePoolMessage(message: string): Message2bytePool {
47
+ this.isUpdate = true;
48
+ this.messageValue = message;
49
+ return Message2bytePool.init(this, this.ctx, this.section);
50
+ }
51
+
52
+ updateMessage(message: string): this {
53
+ this.messageValue = message;
54
+ this.isUpdate = true;
55
+ this.messageExtra.message_id &&= this.messageId;
56
+ return this;
57
+ }
58
+
59
+ markdown(): this {
60
+ this.messageExtra.parse_mode = "markdown";
61
+ return this;
62
+ }
63
+
64
+ html(): this {
65
+ this.messageExtra.parse_mode = "html";
66
+ return this;
67
+ }
68
+
69
+ extra(extra: Object): this {
70
+ this.messageExtra = extra;
71
+ return this;
72
+ }
73
+
74
+ keyboard(keyboard: ReplyKeyboardMarkup): this {
75
+ this.messageExtra.reply_markup = {
76
+ keyboard: keyboard.keyboard,
77
+ resize_keyboard: keyboard.resize_keyboard,
78
+ one_time_keyboard: keyboard.one_time_keyboard,
79
+ };
80
+ return this;
81
+ }
82
+
83
+ inlineKeyboard(keyboard: any[][] | InlineKeyboard) {
84
+ let keyboardArray: any[][];
85
+
86
+ if (keyboard instanceof InlineKeyboard) {
87
+ keyboardArray = keyboard.valueOf();
88
+ } else {
89
+ keyboardArray = keyboard;
90
+ }
91
+
92
+ Object.assign(this.messageExtra, {
93
+ ...Markup.inlineKeyboard(keyboardArray),
94
+ });
95
+
96
+ return this;
97
+ }
98
+
99
+ requestInput(inputKey: string, options: RequestInputOptions = {}): this {
100
+ // Устанавливаем значения по умолчанию
101
+ const allowCancel = options.allowCancel !== false; // по умолчанию true
102
+ const cancelButtonText = options.cancelButtonText || "Отмена";
103
+ const cancelAction = options.cancelAction || "home.index[cancel_wait=1]";
104
+
105
+ // Если разрешена отмена, добавляем кнопку отмены к клавиатуре
106
+ if (allowCancel && this.messageExtra && "reply_markup" in this.messageExtra) {
107
+ const replyMarkup = (this.messageExtra as any).reply_markup;
108
+ if (replyMarkup && replyMarkup.inline_keyboard) {
109
+ // Добавляем кнопку отмены в начало клавиатуры
110
+ replyMarkup.inline_keyboard.unshift([
111
+ {
112
+ text: `❌ ${cancelButtonText}`,
113
+ callback_data: cancelAction,
114
+ },
115
+ ]);
116
+ }
117
+ }
118
+
119
+ // Сохраняем информацию о запрашиваемом вводе в сессии пользователя
120
+ this.ctx.userSession.awaitingInput = {
121
+ key: inputKey,
122
+ validator: options.validator,
123
+ errorMessage: options.errorMessage || "Неверный формат ввода",
124
+ allowCancel,
125
+ cancelButtonText: `❌ ${cancelButtonText}`,
126
+ cancelAction,
127
+ fileValidation: options.fileValidation,
128
+ runSection: options.runSection,
129
+ retryCount: 0,
130
+ };
131
+
132
+ return this;
133
+ }
134
+
135
+ async requestInputWithAwait(
136
+ inputKey: string,
137
+ options: RequestInputOptions = {}
138
+ ): Promise<string | any> {
139
+ // Устанавливаем значения по умолчанию
140
+ const allowCancel = options.allowCancel !== false; // по умолчанию true
141
+ const cancelButtonText = options.cancelButtonText || "Отмена";
142
+ const cancelAction = options.cancelAction || "home.index[cancel_wait=1]";
143
+
144
+ // Если разрешена отмена, добавляем кнопку отмены к клавиатуре
145
+ if (allowCancel && this.messageExtra && "reply_markup" in this.messageExtra) {
146
+ const replyMarkup = (this.messageExtra as any).reply_markup;
147
+ if (replyMarkup && replyMarkup.inline_keyboard) {
148
+ // Добавляем кнопку отмены в начало клавиатуры
149
+ replyMarkup.inline_keyboard.unshift([
150
+ {
151
+ text: `❌ ${cancelButtonText}`,
152
+ callback_data: cancelAction,
153
+ },
154
+ ]);
155
+ }
156
+ }
157
+
158
+ // Отправляем сообщение
159
+ await this.send();
160
+
161
+ // Возвращаем Promise, который будет разрешен когда пользователь введет данные
162
+ return new Promise((resolve, reject) => {
163
+ this.ctx.userSession.awaitingInputPromise = {
164
+ key: inputKey,
165
+ validator: options.validator,
166
+ errorMessage: options.errorMessage || "Неверный формат ввода",
167
+ allowCancel,
168
+ cancelButtonText: `❌ ${cancelButtonText}`,
169
+ cancelAction,
170
+ fileValidation: options.fileValidation,
171
+ retryCount: 0,
172
+ resolve,
173
+ reject,
174
+ };
175
+ });
176
+ }
177
+
178
+ image(pathImage: string): this {
179
+ this.imagePath = pathImage;
180
+ this.imageCaption = this.messageValue;
181
+ this.messageExtra.caption = this.imageCaption;
182
+ return this;
183
+ }
184
+
185
+ editMessageCaption(message: string, extra: any = {}) {
186
+ return this.ctx.editMessageCaption(message, extra);
187
+ }
188
+
189
+ editMessageText(message: string, extra: any = {}) {
190
+ return this.ctx.editMessageText(message, extra);
191
+ }
192
+
193
+ async send() {
194
+ // console.log("Sending message:", this.messageValue, ' Extra:', this.messageExtra, 'IsUpdate:', this.isUpdate);
195
+ if (this.isUpdate) {
196
+ if (this.section.route.runIsCallbackQuery && this.doAnswerCbQuery) {
197
+ await this.ctx.answerCbQuery();
198
+ }
199
+
200
+ const message = this.ctx.callbackQuery?.message as Message;
201
+
202
+ if (message) {
203
+ if ('media_group_id' in message || 'caption' in message) {
204
+ const editMessageCaption = this.editMessageCaption(this.messageValue, this.messageExtra);
205
+
206
+ if (editMessageCaption && 'message_id' in editMessageCaption) {
207
+ this.messageId = editMessageCaption.message_id as number;
208
+ }
209
+
210
+ return editMessageCaption;
211
+ } else {
212
+
213
+ const editedText = this.editMessageText(this.messageValue, this.messageExtra);
214
+
215
+ if (editedText && 'message_id' in editedText) {
216
+ this.messageId = editedText.message_id as number;
217
+ }
218
+
219
+ return editedText;
220
+ }
221
+ } else {
222
+ this.messageExtra.message_id = this.messageId;
223
+
224
+ const messageEntity = await this.editMessageText(this.messageValue, this.messageExtra);
225
+
226
+ if (typeof messageEntity === "object" && 'message_id' in messageEntity) {
227
+ this.messageId = messageEntity.message_id as number;
228
+ }
229
+
230
+ return messageEntity;
231
+ }
232
+ }
233
+
234
+ if (this.imagePath) {
235
+ return this.ctx.replyWithPhoto(Input.fromLocalFile(this.imagePath), this.messageExtra);
236
+ }
237
+
238
+ const replyEntity = this.ctx.reply(this.messageValue, this.messageExtra);
239
+
240
+ this.messageId = (await replyEntity).message_id;
241
+
242
+ return replyEntity;
243
+ }
244
+
245
+ sendReturnThis(): this {
246
+ this.send();
247
+ return this;
248
+ }
249
+
250
+ setMessageId(messageId: number): this {
251
+ this.messageId = messageId;
252
+ this.messageExtra.message_id = messageId;
253
+ return this;
254
+ }
255
+ }