@2byte/tgbot-framework 1.0.5 → 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 +34 -23
  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,80 +1,80 @@
1
- import * as path from 'path';
2
- import chalk from 'chalk';
3
- import { Artisan } from '../illumination/Artisan';
4
-
5
- export interface BotArtisanOptions {
6
- botName: string;
7
- sectionsPath?: string;
8
- }
9
-
10
- export class BotArtisan {
11
- private artisan: Artisan;
12
- private options: BotArtisanOptions;
13
-
14
- constructor(botPath: string, options: BotArtisanOptions) {
15
- this.options = options;
16
- this.artisan = new Artisan(botPath);
17
- }
18
-
19
- async run(): Promise<void> {
20
- const command = process.argv[2];
21
- const args = process.argv.slice(3);
22
-
23
- if (!command) {
24
- this.showHelp();
25
- return;
26
- }
27
-
28
- try {
29
- switch (command) {
30
- case 'make:section':
31
- if (args.length === 0) {
32
- console.error(chalk.red('❌ Error: Section name is required'));
33
- console.log('Usage: artisan make:section SectionName');
34
- return;
35
- }
36
- await this.artisan.createSection(args[0]);
37
- break;
38
-
39
- case 'add:method':
40
- if (args.length < 2) {
41
- console.error(chalk.red('❌ Error: Section name and method name are required'));
42
- console.log('Usage: artisan add:method SectionName methodName');
43
- return;
44
- }
45
- await this.artisan.addMethod(args[0], args[1]);
46
- break;
47
-
48
- case 'list:sections':
49
- await this.artisan.listSections();
50
- break;
51
-
52
- default:
53
- console.error(chalk.red(`❌ Unknown command: ${command}`));
54
- this.showHelp();
55
- }
56
- } catch (error) {
57
- if (error instanceof Error) {
58
- console.error(chalk.red(`❌ Error: ${error.message}`));
59
- } else {
60
- console.error(chalk.red('❌ An unknown error occurred'));
61
- }
62
- }
63
- }
64
-
65
- private showHelp(): void {
66
- console.log(`
67
- 🔧 ${this.options.botName} Artisan CLI
68
-
69
- Available commands:
70
- make:section <name> Create a new section
71
- add:method <section> <name> Add a new method to existing section
72
- list:sections List all sections
73
-
74
- Examples:
75
- artisan make:section Auth Create new AuthSection
76
- artisan add:method Auth login Add login method to AuthSection
77
- artisan list:sections Show all available sections
78
- `);
79
- }
1
+ import * as path from 'path';
2
+ import chalk from 'chalk';
3
+ import { Artisan } from '../illumination/Artisan';
4
+
5
+ export interface BotArtisanOptions {
6
+ botName: string;
7
+ sectionsPath?: string;
8
+ }
9
+
10
+ export class BotArtisan {
11
+ private artisan: Artisan;
12
+ private options: BotArtisanOptions;
13
+
14
+ constructor(botPath: string, options: BotArtisanOptions) {
15
+ this.options = options;
16
+ this.artisan = new Artisan(botPath);
17
+ }
18
+
19
+ async run(): Promise<void> {
20
+ const command = process.argv[2];
21
+ const args = process.argv.slice(3);
22
+
23
+ if (!command) {
24
+ this.showHelp();
25
+ return;
26
+ }
27
+
28
+ try {
29
+ switch (command) {
30
+ case 'make:section':
31
+ if (args.length === 0) {
32
+ console.error(chalk.red('❌ Error: Section name is required'));
33
+ console.log('Usage: artisan make:section SectionName');
34
+ return;
35
+ }
36
+ await this.artisan.createSection(args[0]);
37
+ break;
38
+
39
+ case 'add:method':
40
+ if (args.length < 2) {
41
+ console.error(chalk.red('❌ Error: Section name and method name are required'));
42
+ console.log('Usage: artisan add:method SectionName methodName');
43
+ return;
44
+ }
45
+ await this.artisan.addMethod(args[0], args[1]);
46
+ break;
47
+
48
+ case 'list:sections':
49
+ await this.artisan.listSections();
50
+ break;
51
+
52
+ default:
53
+ console.error(chalk.red(`❌ Unknown command: ${command}`));
54
+ this.showHelp();
55
+ }
56
+ } catch (error) {
57
+ if (error instanceof Error) {
58
+ console.error(chalk.red(`❌ Error: ${error.message}`));
59
+ } else {
60
+ console.error(chalk.red('❌ An unknown error occurred'));
61
+ }
62
+ }
63
+ }
64
+
65
+ private showHelp(): void {
66
+ console.log(`
67
+ 🔧 ${this.options.botName} Artisan CLI
68
+
69
+ Available commands:
70
+ make:section <name> Create a new section
71
+ add:method <section> <name> Add a new method to existing section
72
+ list:sections List all sections
73
+
74
+ Examples:
75
+ artisan make:section Auth Create new AuthSection
76
+ artisan add:method Auth login Add login method to AuthSection
77
+ artisan list:sections Show all available sections
78
+ `);
79
+ }
80
80
  }
@@ -1,31 +1,31 @@
1
- import * as path from 'path';
2
- import chalk from 'chalk';
3
- import { setupMigrations } from '../console/migrate';
4
-
5
- export interface BotMigrationOptions {
6
- botPath: string;
7
- migrationsPath: string;
8
- databasePath: string;
9
- }
10
-
11
- export class BotMigration {
12
- private options: BotMigrationOptions;
13
-
14
- constructor(options: BotMigrationOptions) {
15
- this.options = options;
16
- }
17
-
18
- async run(): Promise<void> {
19
- console.log(chalk.blue(`🗃️ Running migrations for bot...`));
20
-
21
- try {
22
- await setupMigrations({
23
- pathMigrations: this.options.migrationsPath,
24
- pathDatabase: this.options.databasePath
25
- });
26
- } catch (error) {
27
- console.error(chalk.red('❌ Migration failed:'), error);
28
- throw error;
29
- }
30
- }
1
+ import * as path from 'path';
2
+ import chalk from 'chalk';
3
+ import { setupMigrations } from '../console/migrate';
4
+
5
+ export interface BotMigrationOptions {
6
+ botPath: string;
7
+ migrationsPath: string;
8
+ databasePath: string;
9
+ }
10
+
11
+ export class BotMigration {
12
+ private options: BotMigrationOptions;
13
+
14
+ constructor(options: BotMigrationOptions) {
15
+ this.options = options;
16
+ }
17
+
18
+ async run(): Promise<void> {
19
+ console.log(chalk.blue(`🗃️ Running migrations for bot...`));
20
+
21
+ try {
22
+ await setupMigrations({
23
+ pathMigrations: this.options.migrationsPath,
24
+ pathDatabase: this.options.databasePath
25
+ });
26
+ } catch (error) {
27
+ console.error(chalk.red('❌ Migration failed:'), error);
28
+ throw error;
29
+ }
30
+ }
31
31
  }
@@ -1,67 +1,67 @@
1
- import * as path from 'path';
2
- import chalk from 'chalk';
3
- import { Database } from 'bun:sqlite';
4
-
5
- export interface BotSeederOptions {
6
- botPath: string;
7
- databasePath: string;
8
- seeders: Array<(db: Database) => Promise<void> | void>;
9
- }
10
-
11
- export class BotSeeder {
12
- private options: BotSeederOptions;
13
-
14
- constructor(options: BotSeederOptions) {
15
- this.options = options;
16
- }
17
-
18
- async run(): Promise<void> {
19
- const args = process.argv.slice(2);
20
- const isCleanOnly = args.includes('--clean-only');
21
- const isClear = args.includes('--clear');
22
-
23
- console.log(chalk.blue(`🌱 Running seeders for bot...`));
24
-
25
- const db = new Database(this.options.databasePath);
26
-
27
- try {
28
- if (isCleanOnly) {
29
- console.log(chalk.yellow('🧹 Cleaning database...'));
30
- await this.cleanDatabase(db);
31
- console.log(chalk.green('✅ Database cleaned successfully!'));
32
- return;
33
- }
34
-
35
- if (isClear) {
36
- console.log(chalk.yellow('🧹 Clearing and reseeding database...'));
37
- await this.cleanDatabase(db);
38
- }
39
-
40
- console.log(chalk.blue('🌱 Seeding database...'));
41
- for (const seeder of this.options.seeders) {
42
- await seeder(db);
43
- }
44
-
45
- console.log(chalk.green('✅ Database seeded successfully!'));
46
- } catch (error) {
47
- console.error(chalk.red('❌ Seeding failed:'), error);
48
- throw error;
49
- } finally {
50
- db.close();
51
- }
52
- }
53
-
54
- private async cleanDatabase(db: Database): Promise<void> {
55
- // Get all tables
56
- const tables = db.query(`
57
- SELECT name FROM sqlite_master
58
- WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name != 'migrations'
59
- `).all() as Array<{ name: string }>;
60
-
61
- // Clear all tables except migrations
62
- for (const table of tables) {
63
- db.query(`DELETE FROM ${table.name}`).run();
64
- console.log(chalk.yellow(`🧹 Cleared table: ${table.name}`));
65
- }
66
- }
1
+ import * as path from 'path';
2
+ import chalk from 'chalk';
3
+ import { Database } from 'bun:sqlite';
4
+
5
+ export interface BotSeederOptions {
6
+ botPath: string;
7
+ databasePath: string;
8
+ seeders: Array<(db: Database) => Promise<void> | void>;
9
+ }
10
+
11
+ export class BotSeeder {
12
+ private options: BotSeederOptions;
13
+
14
+ constructor(options: BotSeederOptions) {
15
+ this.options = options;
16
+ }
17
+
18
+ async run(): Promise<void> {
19
+ const args = process.argv.slice(2);
20
+ const isCleanOnly = args.includes('--clean-only');
21
+ const isClear = args.includes('--clear');
22
+
23
+ console.log(chalk.blue(`🌱 Running seeders for bot...`));
24
+
25
+ const db = new Database(this.options.databasePath);
26
+
27
+ try {
28
+ if (isCleanOnly) {
29
+ console.log(chalk.yellow('🧹 Cleaning database...'));
30
+ await this.cleanDatabase(db);
31
+ console.log(chalk.green('✅ Database cleaned successfully!'));
32
+ return;
33
+ }
34
+
35
+ if (isClear) {
36
+ console.log(chalk.yellow('🧹 Clearing and reseeding database...'));
37
+ await this.cleanDatabase(db);
38
+ }
39
+
40
+ console.log(chalk.blue('🌱 Seeding database...'));
41
+ for (const seeder of this.options.seeders) {
42
+ await seeder(db);
43
+ }
44
+
45
+ console.log(chalk.green('✅ Database seeded successfully!'));
46
+ } catch (error) {
47
+ console.error(chalk.red('❌ Seeding failed:'), error);
48
+ throw error;
49
+ } finally {
50
+ db.close();
51
+ }
52
+ }
53
+
54
+ private async cleanDatabase(db: Database): Promise<void> {
55
+ // Get all tables
56
+ const tables = db.query(`
57
+ SELECT name FROM sqlite_master
58
+ WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name != 'migrations'
59
+ `).all() as Array<{ name: string }>;
60
+
61
+ // Clear all tables except migrations
62
+ for (const table of tables) {
63
+ db.query(`DELETE FROM ${table.name}`).run();
64
+ console.log(chalk.yellow(`🧹 Cleared table: ${table.name}`));
65
+ }
66
+ }
67
67
  }
package/src/core/Model.ts CHANGED
@@ -1,84 +1,84 @@
1
- import type { Database } from "bun:sqlite";
2
- import { MakeManualPaginateButtonsParams, ModelPaginateParams, PaginateResult } from "../types";
3
- import { Section } from "../illumination/Section";
4
-
5
- declare global {
6
- var db: Database;
7
- }
8
-
9
- export abstract class Model {
10
- protected static db: Database;
11
- protected static tableName: string;
12
-
13
- static setDatabase(database: Database) {
14
- this.db = database;
15
- }
16
-
17
- protected static resolveDb(): Database {
18
- if (globalThis.db) {
19
- this.db = globalThis.db;
20
- } else {
21
- throw new Error("Database connection is not set.");
22
- }
23
- return this.db;
24
- }
25
-
26
- protected static query(sql: string, params: any[] = []): any {
27
- const stmt = this.db.prepare(sql);
28
- return stmt.all(...params);
29
- }
30
-
31
- protected static run(sql: string, params: any[] = []): { lastInsertRowid: number, changes: number } {
32
- const stmt = this.db.prepare(sql);
33
- return stmt.run(...params);
34
- }
35
-
36
- protected static queryOne(sql: string, params: any[] = []): any {
37
- const stmt = this.db.prepare(sql);
38
- return stmt.get(...params);
39
- }
40
-
41
- protected static execute(sql: string, params: any[] = []): void {
42
- const stmt = this.db.prepare(sql);
43
- stmt.run(...params);
44
- }
45
-
46
- protected static exists(whereSql: string, whereParams: any[] = []): boolean {
47
- const sql = `SELECT 1 FROM ${this.tableName} ${whereSql} LIMIT 1`;
48
- const result = this.queryOne(sql, whereParams);
49
- return !!result;
50
- }
51
-
52
- protected static transaction<T>(callback: () => T): T {
53
- return this.db.transaction(callback)();
54
- }
55
-
56
- public static async paginate(paginateParams: ModelPaginateParams): Promise<PaginateResult> {
57
- const { page, route, routeParams, limit, whereSql, whereParams } = paginateParams;
58
- const offset = (page - 1) * limit;
59
- const sql = `SELECT * FROM ${this.tableName} ${whereSql} LIMIT ${offset}, ${limit}`;
60
-
61
- const result = await this.query(sql, whereParams);
62
- const queryTotal = await this.queryOne(`SELECT COUNT(*) as count FROM ${this.tableName} ${whereSql}`, whereParams);
63
- const total = queryTotal ? queryTotal.count : 0;
64
- const totalPages = Math.ceil(total / limit);
65
- const hasPreviousPage = page > 1;
66
- const hasNextPage = page < totalPages;
67
-
68
- return {
69
- items: result,
70
- paginateButtons: Section.makeManualPaginateButtons({
71
- callbackDataAction: route,
72
- paramsQuery: routeParams || {},
73
- currentPage: page,
74
- totalRecords: total,
75
- perPage: limit,
76
- } as MakeManualPaginateButtonsParams),
77
- total,
78
- totalPages,
79
- hasPreviousPage,
80
- hasNextPage,
81
- currentPage: page,
82
- } as PaginateResult;
83
- }
84
- }
1
+ import type { Database } from "bun:sqlite";
2
+ import { MakeManualPaginateButtonsParams, ModelPaginateParams, PaginateResult } from "../types";
3
+ import { Section } from "../illumination/Section";
4
+
5
+ declare global {
6
+ var db: Database;
7
+ }
8
+
9
+ export abstract class Model {
10
+ protected static db: Database;
11
+ protected static tableName: string;
12
+
13
+ static setDatabase(database: Database) {
14
+ this.db = database;
15
+ }
16
+
17
+ protected static resolveDb(): Database {
18
+ if (globalThis.db) {
19
+ this.db = globalThis.db;
20
+ } else {
21
+ throw new Error("Database connection is not set.");
22
+ }
23
+ return this.db;
24
+ }
25
+
26
+ protected static query(sql: string, params: any[] = []): any {
27
+ const stmt = this.db.prepare(sql);
28
+ return stmt.all(...params);
29
+ }
30
+
31
+ protected static run(sql: string, params: any[] = []): { lastInsertRowid: number, changes: number } {
32
+ const stmt = this.db.prepare(sql);
33
+ return stmt.run(...params);
34
+ }
35
+
36
+ protected static queryOne(sql: string, params: any[] = []): any {
37
+ const stmt = this.db.prepare(sql);
38
+ return stmt.get(...params);
39
+ }
40
+
41
+ protected static execute(sql: string, params: any[] = []): void {
42
+ const stmt = this.db.prepare(sql);
43
+ stmt.run(...params);
44
+ }
45
+
46
+ protected static exists(whereSql: string, whereParams: any[] = []): boolean {
47
+ const sql = `SELECT 1 FROM ${this.tableName} ${whereSql} LIMIT 1`;
48
+ const result = this.queryOne(sql, whereParams);
49
+ return !!result;
50
+ }
51
+
52
+ protected static transaction<T>(callback: () => T): T {
53
+ return this.db.transaction(callback)();
54
+ }
55
+
56
+ public static async paginate(paginateParams: ModelPaginateParams): Promise<PaginateResult> {
57
+ const { page, route, routeParams, limit, whereSql, whereParams } = paginateParams;
58
+ const offset = (page - 1) * limit;
59
+ const sql = `SELECT * FROM ${this.tableName} ${whereSql} LIMIT ${offset}, ${limit}`;
60
+
61
+ const result = await this.query(sql, whereParams);
62
+ const queryTotal = await this.queryOne(`SELECT COUNT(*) as count FROM ${this.tableName} ${whereSql}`, whereParams);
63
+ const total = queryTotal ? queryTotal.count : 0;
64
+ const totalPages = Math.ceil(total / limit);
65
+ const hasPreviousPage = page > 1;
66
+ const hasNextPage = page < totalPages;
67
+
68
+ return {
69
+ items: result,
70
+ paginateButtons: Section.makeManualPaginateButtons({
71
+ callbackDataAction: route,
72
+ paramsQuery: routeParams || {},
73
+ currentPage: page,
74
+ totalRecords: total,
75
+ perPage: limit,
76
+ } as MakeManualPaginateButtonsParams),
77
+ total,
78
+ totalPages,
79
+ hasPreviousPage,
80
+ hasNextPage,
81
+ currentPage: page,
82
+ } as PaginateResult;
83
+ }
84
+ }
package/src/core/utils.ts CHANGED
@@ -1,3 +1,3 @@
1
- export function nameToCapitalize(name: string): string {
2
- return name.charAt(0).toUpperCase() + name.slice(1);
1
+ export function nameToCapitalize(name: string): string {
2
+ return name.charAt(0).toUpperCase() + name.slice(1);
3
3
  }