@2byte/tgbot-framework 1.0.3 → 1.0.4

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 +6 -5
  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 -0
  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 +1143 -1113
  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 -35
  28. package/src/libs/TelegramAccountControl.ts +1140 -738
  29. package/src/libs/TgSender.ts +53 -0
  30. package/src/models/Model.ts +67 -0
  31. package/src/models/Proxy.ts +218 -0
  32. package/src/models/TgAccount.ts +362 -0
  33. package/src/models/index.ts +3 -0
  34. package/src/types.ts +191 -188
  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 +23 -19
  39. package/templates/bot/artisan.ts +8 -8
  40. package/templates/bot/bot.ts +82 -79
  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 -0
  45. package/templates/bot/database/migrations/008_tg_accounts.sql +32 -0
  46. package/templates/bot/database/seed.ts +14 -14
  47. package/templates/bot/docs/CLI_SERVICES.md +536 -0
  48. package/templates/bot/docs/INPUT_SYSTEM.md +211 -0
  49. package/templates/bot/docs/SERVICE_EXAMPLES.md +384 -0
  50. package/templates/bot/docs/TASK_SYSTEM.md +156 -0
  51. package/templates/bot/models/Model.ts +7 -0
  52. package/templates/bot/models/index.ts +2 -0
  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/{ExampleServise.ts → ExampleService.ts} +23 -23
package/bin/2byte-cli.ts CHANGED
@@ -1,98 +1,98 @@
1
- #!/usr/bin/env bun
2
-
3
- import { Command } from 'commander';
4
- import { CreateBotCommand } from '../src/cli/CreateBotCommand';
5
- import { InitCommand } from'../src/cli/InitCommand';
6
- import { GenerateCommand } from '../src/cli/GenerateCommand';
7
- import chalk from 'chalk';
8
-
9
- const program = new Command();
10
-
11
- program
12
- .name('2byte')
13
- .description('CLI for 2byte Telegram Bot Framework')
14
- .version('1.0.0');
15
-
16
- // Create Bot command
17
- program
18
- .command('create-bot <name>')
19
- .description('Create a new telegram bot with sections-based architecture')
20
- .option('-p, --path [path]', 'Target directory path', process.cwd())
21
- .option('--no-database', 'Skip database setup')
22
- .action(async (name, options) => {
23
- try {
24
- const command = new CreateBotCommand();
25
- await command.execute(name, options);
26
- } catch (error) {
27
- console.error(chalk.red('❌ Error:'), error.message);
28
- process.exit(1);
29
- }
30
- });
31
-
32
- // Init command
33
- program
34
- .command('init')
35
- .description('Initialize 2byte bot in current directory')
36
- .option('-f, --force', 'Override existing files')
37
- .action(async (options) => {
38
- try {
39
- const command = new InitCommand();
40
- await command.execute(options);
41
- } catch (error) {
42
- console.error(chalk.red('❌ Error:'), error.message);
43
- process.exit(1);
44
- }
45
- });
46
-
47
- // Generate commands
48
- const generate = program
49
- .command('generate')
50
- .alias('g')
51
- .description('Generate various bot components');
52
-
53
- generate
54
- .command('section <name>')
55
- .description('Generate a new section')
56
- .action(async (name) => {
57
- try {
58
- const command = new GenerateCommand();
59
- await command.generateSection(name);
60
- } catch (error) {
61
- console.error(chalk.red('❌ Error:'), error.message);
62
- process.exit(1);
63
- }
64
- });
65
-
66
- generate
67
- .command('service <name>')
68
- .description('Generate a new API service')
69
- .action(async (name) => {
70
- try {
71
- const command = new GenerateCommand();
72
- await command.generateService(name);
73
- } catch (error) {
74
- console.error(chalk.red('❌ Error:'), error.message);
75
- process.exit(1);
76
- }
77
- });
78
-
79
- generate
80
- .command('migration <name>')
81
- .description('Generate a new migration')
82
- .action(async (name) => {
83
- try {
84
- const command = new GenerateCommand();
85
- await command.generateMigration(name);
86
- } catch (error) {
87
- console.error(chalk.red('❌ Error:'), error.message);
88
- process.exit(1);
89
- }
90
- });
91
-
92
- // Parse arguments
93
- program.parse(process.argv);
94
-
95
- // Show help if no command provided
96
- if (!process.argv.slice(2).length) {
97
- program.outputHelp();
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander';
4
+ import { CreateBotCommand } from '../src/cli/CreateBotCommand';
5
+ import { InitCommand } from'../src/cli/InitCommand';
6
+ import { GenerateCommand } from '../src/cli/GenerateCommand';
7
+ import chalk from 'chalk';
8
+
9
+ const program = new Command();
10
+
11
+ program
12
+ .name('2byte')
13
+ .description('CLI for 2byte Telegram Bot Framework')
14
+ .version('1.0.0');
15
+
16
+ // Create Bot command
17
+ program
18
+ .command('create-bot <name>')
19
+ .description('Create a new telegram bot with sections-based architecture')
20
+ .option('-p, --path [path]', 'Target directory path', process.cwd())
21
+ .option('--no-database', 'Skip database setup')
22
+ .action(async (name, options) => {
23
+ try {
24
+ const command = new CreateBotCommand();
25
+ await command.execute(name, options);
26
+ } catch (error) {
27
+ console.error(chalk.red('❌ Error:'), error.message);
28
+ process.exit(1);
29
+ }
30
+ });
31
+
32
+ // Init command
33
+ program
34
+ .command('init')
35
+ .description('Initialize 2byte bot in current directory')
36
+ .option('-f, --force', 'Override existing files')
37
+ .action(async (options) => {
38
+ try {
39
+ const command = new InitCommand();
40
+ await command.execute(options);
41
+ } catch (error) {
42
+ console.error(chalk.red('❌ Error:'), error.message);
43
+ process.exit(1);
44
+ }
45
+ });
46
+
47
+ // Generate commands
48
+ const generate = program
49
+ .command('generate')
50
+ .alias('g')
51
+ .description('Generate various bot components');
52
+
53
+ generate
54
+ .command('section <name>')
55
+ .description('Generate a new section')
56
+ .action(async (name) => {
57
+ try {
58
+ const command = new GenerateCommand();
59
+ await command.generateSection(name);
60
+ } catch (error) {
61
+ console.error(chalk.red('❌ Error:'), error.message);
62
+ process.exit(1);
63
+ }
64
+ });
65
+
66
+ generate
67
+ .command('service <name>')
68
+ .description('Generate a new API service')
69
+ .action(async (name) => {
70
+ try {
71
+ const command = new GenerateCommand();
72
+ await command.generateService(name);
73
+ } catch (error) {
74
+ console.error(chalk.red('❌ Error:'), error.message);
75
+ process.exit(1);
76
+ }
77
+ });
78
+
79
+ generate
80
+ .command('migration <name>')
81
+ .description('Generate a new migration')
82
+ .action(async (name) => {
83
+ try {
84
+ const command = new GenerateCommand();
85
+ await command.generateMigration(name);
86
+ } catch (error) {
87
+ console.error(chalk.red('❌ Error:'), error.message);
88
+ process.exit(1);
89
+ }
90
+ });
91
+
92
+ // Parse arguments
93
+ program.parse(process.argv);
94
+
95
+ // Show help if no command provided
96
+ if (!process.argv.slice(2).length) {
97
+ program.outputHelp();
98
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2byte/tgbot-framework",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "A TypeScript framework for creating Telegram bots with sections-based architecture (Bun optimized)",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -29,15 +29,16 @@
29
29
  "author": "2byte",
30
30
  "license": "MIT",
31
31
  "dependencies": {
32
+ "chalk": "^5.6.2",
33
+ "commander": "^14.0.2",
32
34
  "dotenv": "^16.6.1",
35
+ "fs-extra": "^11.3.2",
36
+ "input": "^1.0.1",
33
37
  "inquirer": "^12.9.6",
34
38
  "mustache": "^4.2.0",
35
39
  "socks": "^2.8.6",
36
40
  "telegraf": "^4.16.3",
37
- "telegram": "^2.26.22",
38
- "chalk": "^5.6.2",
39
- "commander": "^14.0.2",
40
- "fs-extra": "^11.3.2"
41
+ "telegram": "^2.26.22"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/bun": "^1.3.1",
@@ -1,182 +1,182 @@
1
- import * as fs from 'fs-extra';
2
- import * as path from 'path';
3
- import inquirer from 'inquirer';
4
- import chalk from 'chalk';
5
- import Mustache from 'mustache';
6
-
7
- export class CreateBotCommand {
8
- private templatesPath: string;
9
-
10
- constructor() {
11
- this.templatesPath = path.join(__dirname, '../../templates');
12
- }
13
-
14
- async execute(botName: string, options: any): Promise<void> {
15
- console.log(chalk.blue(`🚀 Creating new bot: ${botName}`));
16
-
17
- const targetPath = path.join(options.path, botName);
18
-
19
- // Check if directory already exists
20
- if (await fs.pathExists(targetPath)) {
21
- const { overwrite } = await inquirer.prompt([
22
- {
23
- type: 'confirm',
24
- name: 'overwrite',
25
- message: `Directory ${botName} already exists. Overwrite?`,
26
- default: false,
27
- },
28
- ]);
29
-
30
- if (!overwrite) {
31
- console.log(chalk.yellow('⚠️ Operation cancelled'));
32
- return;
33
- }
34
-
35
- await fs.remove(targetPath);
36
- }
37
-
38
- // Create directory
39
- await fs.ensureDir(targetPath);
40
-
41
- // Get bot configuration
42
- const config = await this.getBotConfig(botName, options);
43
-
44
- // Copy templates
45
- await this.copyTemplates(targetPath, config);
46
-
47
- // Install dependencies if requested
48
- if (config.installDeps) {
49
- await this.installDependencies(targetPath);
50
- }
51
-
52
- // Setup database if requested
53
- if (config.useDatabase) {
54
- console.log(chalk.blue('🗄️ Setting up database...'));
55
-
56
- fs.createFileSync(path.join(targetPath, 'database', 'database.sqlite'));
57
-
58
- console.log(chalk.green('✅ Database setup complete!'));
59
- }
60
-
61
- // Rename .env.example to .env
62
- await fs.rename(
63
- path.join(targetPath, '.env.example'),
64
- path.join(targetPath, '.env')
65
- );
66
-
67
- console.log(chalk.green('✅ .env file created! Please update it with your bot token and settings.'));
68
-
69
- console.log(chalk.green(`✅ Bot ${botName} created successfully!`));
70
- console.log(chalk.blue('📋 Next steps:'));
71
- console.log(` cd ${botName}`);
72
- console.log(` ${config.installDeps ? '' : 'bun install'}${config.installDeps ? '' : ' # Install dependencies'}`);
73
- console.log(' bun run migrate # Run migrations');
74
- console.log(' bun run seed # Seed database');
75
- console.log(' bun run dev # Start bot');
76
- }
77
-
78
- private async getBotConfig(botName: string, options: any) {
79
- const questions = [
80
- {
81
- type: 'input',
82
- name: 'description',
83
- message: 'Bot description:',
84
- default: `A telegram bot created with 2byte framework`,
85
- },
86
- {
87
- type: 'input',
88
- name: 'author',
89
- message: 'Author:',
90
- default: '',
91
- },
92
- {
93
- type: 'confirm',
94
- name: 'useDatabase',
95
- message: 'Include sqlite 3 database setup?',
96
- default: !options.noDatabase,
97
- },
98
- {
99
- type: 'confirm',
100
- name: 'installDeps',
101
- message: 'Install dependencies now?',
102
- default: true,
103
- },
104
- ];
105
-
106
- const answers = await inquirer.prompt(questions);
107
-
108
- return {
109
- botName,
110
- ...answers,
111
- className: this.toPascalCase(botName),
112
- kebabName: this.toKebabCase(botName),
113
- };
114
- }
115
-
116
- private async copyTemplates(targetPath: string, config: any): Promise<void> {
117
- const templatePath = path.join(this.templatesPath, 'bot');
118
-
119
- // Copy all files from template
120
- await this.copyTemplateFiles(templatePath, targetPath, config);
121
- }
122
-
123
- private async copyTemplateFiles(sourcePath: string, targetPath: string, config: any): Promise<void> {
124
- const items = await fs.readdir(sourcePath);
125
-
126
- for (const item of items) {
127
- const sourceItemPath = path.join(sourcePath, item);
128
- const targetItemPath = path.join(targetPath, item);
129
-
130
- const stat = await fs.stat(sourceItemPath);
131
-
132
- if (stat.isDirectory()) {
133
- await fs.ensureDir(targetItemPath);
134
- await this.copyTemplateFiles(sourceItemPath, targetItemPath, config);
135
- } else {
136
- // Read file content
137
- let content = await fs.readFile(sourceItemPath, 'utf-8');
138
-
139
- // Process template
140
- content = Mustache.render(content, config);
141
-
142
- // Write processed content
143
- await fs.writeFile(targetItemPath, content);
144
- }
145
- }
146
- }
147
-
148
- private async installDependencies(targetPath: string): Promise<void> {
149
- console.log(chalk.blue('📦 Installing dependencies...'));
150
-
151
- const { spawn } = require('child_process');
152
-
153
- return new Promise((resolve, reject) => {
154
- const install = spawn('bun', ['install'], {
155
- cwd: targetPath,
156
- stdio: 'inherit'
157
- });
158
-
159
- install.on('close', (code) => {
160
- if (code === 0) {
161
- resolve(void 0);
162
- } else {
163
- reject(new Error(`Installation failed with code ${code}`));
164
- }
165
- });
166
- });
167
- }
168
-
169
- private toPascalCase(str: string): string {
170
- return str
171
- .split(/[-_\s]+/)
172
- .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
173
- .join('');
174
- }
175
-
176
- private toKebabCase(str: string): string {
177
- return str
178
- .replace(/([a-z])([A-Z])/g, '$1-$2')
179
- .replace(/[\s_]+/g, '-')
180
- .toLowerCase();
181
- }
1
+ import * as fs from 'fs-extra';
2
+ import * as path from 'path';
3
+ import inquirer from 'inquirer';
4
+ import chalk from 'chalk';
5
+ import Mustache from 'mustache';
6
+
7
+ export class CreateBotCommand {
8
+ private templatesPath: string;
9
+
10
+ constructor() {
11
+ this.templatesPath = path.join(__dirname, '../../templates');
12
+ }
13
+
14
+ async execute(botName: string, options: any): Promise<void> {
15
+ console.log(chalk.blue(`🚀 Creating new bot: ${botName}`));
16
+
17
+ const targetPath = path.join(options.path, botName);
18
+
19
+ // Check if directory already exists
20
+ if (await fs.pathExists(targetPath)) {
21
+ const { overwrite } = await inquirer.prompt([
22
+ {
23
+ type: 'confirm',
24
+ name: 'overwrite',
25
+ message: `Directory ${botName} already exists. Overwrite?`,
26
+ default: false,
27
+ },
28
+ ]);
29
+
30
+ if (!overwrite) {
31
+ console.log(chalk.yellow('⚠️ Operation cancelled'));
32
+ return;
33
+ }
34
+
35
+ await fs.remove(targetPath);
36
+ }
37
+
38
+ // Create directory
39
+ await fs.ensureDir(targetPath);
40
+
41
+ // Get bot configuration
42
+ const config = await this.getBotConfig(botName, options);
43
+
44
+ // Copy templates
45
+ await this.copyTemplates(targetPath, config);
46
+
47
+ // Install dependencies if requested
48
+ if (config.installDeps) {
49
+ await this.installDependencies(targetPath);
50
+ }
51
+
52
+ // Setup database if requested
53
+ if (config.useDatabase) {
54
+ console.log(chalk.blue('🗄️ Setting up database...'));
55
+
56
+ fs.createFileSync(path.join(targetPath, 'database', 'database.sqlite'));
57
+
58
+ console.log(chalk.green('✅ Database setup complete!'));
59
+ }
60
+
61
+ // Rename .env.example to .env
62
+ await fs.rename(
63
+ path.join(targetPath, '.env.example'),
64
+ path.join(targetPath, '.env')
65
+ );
66
+
67
+ console.log(chalk.green('✅ .env file created! Please update it with your bot token and settings.'));
68
+
69
+ console.log(chalk.green(`✅ Bot ${botName} created successfully!`));
70
+ console.log(chalk.blue('📋 Next steps:'));
71
+ console.log(` cd ${botName}`);
72
+ console.log(` ${config.installDeps ? '' : 'bun install'}${config.installDeps ? '' : ' # Install dependencies'}`);
73
+ console.log(' bun run migrate # Run migrations');
74
+ console.log(' bun run seed # Seed database');
75
+ console.log(' bun run dev # Start bot');
76
+ }
77
+
78
+ private async getBotConfig(botName: string, options: any) {
79
+ const questions = [
80
+ {
81
+ type: 'input',
82
+ name: 'description',
83
+ message: 'Bot description:',
84
+ default: `A telegram bot created with 2byte framework`,
85
+ },
86
+ {
87
+ type: 'input',
88
+ name: 'author',
89
+ message: 'Author:',
90
+ default: '',
91
+ },
92
+ {
93
+ type: 'confirm',
94
+ name: 'useDatabase',
95
+ message: 'Include sqlite 3 database setup?',
96
+ default: !options.noDatabase,
97
+ },
98
+ {
99
+ type: 'confirm',
100
+ name: 'installDeps',
101
+ message: 'Install dependencies now?',
102
+ default: true,
103
+ },
104
+ ];
105
+
106
+ const answers = await inquirer.prompt(questions);
107
+
108
+ return {
109
+ botName,
110
+ ...answers,
111
+ className: this.toPascalCase(botName),
112
+ kebabName: this.toKebabCase(botName),
113
+ };
114
+ }
115
+
116
+ private async copyTemplates(targetPath: string, config: any): Promise<void> {
117
+ const templatePath = path.join(this.templatesPath, 'bot');
118
+
119
+ // Copy all files from template
120
+ await this.copyTemplateFiles(templatePath, targetPath, config);
121
+ }
122
+
123
+ private async copyTemplateFiles(sourcePath: string, targetPath: string, config: any): Promise<void> {
124
+ const items = await fs.readdir(sourcePath);
125
+
126
+ for (const item of items) {
127
+ const sourceItemPath = path.join(sourcePath, item);
128
+ const targetItemPath = path.join(targetPath, item);
129
+
130
+ const stat = await fs.stat(sourceItemPath);
131
+
132
+ if (stat.isDirectory()) {
133
+ await fs.ensureDir(targetItemPath);
134
+ await this.copyTemplateFiles(sourceItemPath, targetItemPath, config);
135
+ } else {
136
+ // Read file content
137
+ let content = await fs.readFile(sourceItemPath, 'utf-8');
138
+
139
+ // Process template
140
+ content = Mustache.render(content, config);
141
+
142
+ // Write processed content
143
+ await fs.writeFile(targetItemPath, content);
144
+ }
145
+ }
146
+ }
147
+
148
+ private async installDependencies(targetPath: string): Promise<void> {
149
+ console.log(chalk.blue('📦 Installing dependencies...'));
150
+
151
+ const { spawn } = require('child_process');
152
+
153
+ return new Promise((resolve, reject) => {
154
+ const install = spawn('bun', ['install'], {
155
+ cwd: targetPath,
156
+ stdio: 'inherit'
157
+ });
158
+
159
+ install.on('close', (code) => {
160
+ if (code === 0) {
161
+ resolve(void 0);
162
+ } else {
163
+ reject(new Error(`Installation failed with code ${code}`));
164
+ }
165
+ });
166
+ });
167
+ }
168
+
169
+ private toPascalCase(str: string): string {
170
+ return str
171
+ .split(/[-_\s]+/)
172
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
173
+ .join('');
174
+ }
175
+
176
+ private toKebabCase(str: string): string {
177
+ return str
178
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
179
+ .replace(/[\s_]+/g, '-')
180
+ .toLowerCase();
181
+ }
182
182
  }