@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.
- package/README.md +300 -300
- package/bin/2byte-cli.ts +97 -97
- package/package.json +54 -54
- package/src/cli/CreateBotCommand.ts +181 -181
- package/src/cli/GenerateCommand.ts +195 -195
- package/src/cli/InitCommand.ts +107 -107
- package/src/cli/TgAccountManager.ts +50 -50
- package/src/console/migrate.ts +82 -82
- package/src/core/ApiService.ts +20 -20
- package/src/core/ApiServiceManager.ts +63 -63
- package/src/core/App.ts +1157 -1143
- package/src/core/BotArtisan.ts +79 -79
- package/src/core/BotMigration.ts +30 -30
- package/src/core/BotSeeder.ts +66 -66
- package/src/core/Model.ts +84 -84
- package/src/core/utils.ts +2 -2
- package/src/illumination/Artisan.ts +149 -149
- package/src/illumination/InlineKeyboard.ts +61 -61
- package/src/illumination/Message2Byte.ts +255 -255
- package/src/illumination/Message2ByteLiveProgressive.ts +278 -278
- package/src/illumination/Message2bytePool.ts +107 -107
- package/src/illumination/Migration.ts +186 -186
- package/src/illumination/RunSectionRoute.ts +85 -85
- package/src/illumination/Section.ts +410 -410
- package/src/illumination/SectionComponent.ts +64 -64
- package/src/illumination/Telegraf2byteContext.ts +32 -32
- package/src/index.ts +42 -42
- package/src/libs/TelegramAccountControl.ts +1140 -1140
- package/src/libs/TgSender.ts +53 -53
- package/src/models/Model.ts +67 -67
- package/src/models/Proxy.ts +217 -217
- package/src/models/TgAccount.ts +362 -362
- package/src/models/index.ts +2 -2
- package/src/types.ts +191 -191
- package/src/user/UserModel.ts +297 -297
- package/src/user/UserStore.ts +119 -119
- package/src/workflow/services/MassSendApiService.ts +80 -80
- package/templates/bot/.env.example +34 -23
- package/templates/bot/artisan.ts +8 -8
- package/templates/bot/bot.ts +82 -82
- package/templates/bot/database/dbConnector.ts +4 -4
- package/templates/bot/database/migrate.ts +9 -9
- package/templates/bot/database/migrations/001_create_users.sql +18 -18
- package/templates/bot/database/migrations/007_proxy.sql +27 -27
- package/templates/bot/database/migrations/008_tg_accounts.sql +32 -32
- package/templates/bot/database/seed.ts +14 -14
- package/templates/bot/docs/CLI_SERVICES.md +536 -536
- package/templates/bot/docs/INPUT_SYSTEM.md +211 -211
- package/templates/bot/docs/SERVICE_EXAMPLES.md +384 -384
- package/templates/bot/docs/TASK_SYSTEM.md +156 -156
- package/templates/bot/models/Model.ts +7 -7
- package/templates/bot/models/index.ts +1 -1
- package/templates/bot/package.json +30 -30
- package/templates/bot/sectionList.ts +9 -9
- package/templates/bot/sections/ExampleInputSection.ts +85 -85
- package/templates/bot/sections/ExampleLiveTaskerSection.ts +60 -60
- package/templates/bot/sections/HomeSection.ts +63 -63
- package/templates/bot/workflow/services/ExampleService.ts +23 -23
package/src/user/UserStore.ts
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
import { UserModel } from './UserModel';
|
|
2
|
-
import { UserSession } from '../types';
|
|
3
|
-
import { EnvVars } from '../types';
|
|
4
|
-
|
|
5
|
-
interface ApiConfig {
|
|
6
|
-
apiUrl: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface Api {
|
|
10
|
-
fetch(endpoint: string, method?: string, data?: any): Promise<any>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class UserStore {
|
|
14
|
-
private usersMap: Map<string, UserModel> = new Map();
|
|
15
|
-
private usersSession: Map<UserModel, UserSession> = new Map();
|
|
16
|
-
private api: Api | null = null;
|
|
17
|
-
|
|
18
|
-
constructor(envConfig?: EnvVars) {
|
|
19
|
-
if (envConfig) {
|
|
20
|
-
let url = envConfig.BOT_API_URL || '';
|
|
21
|
-
|
|
22
|
-
// Здесь должна быть инициализация API, но мы оставим это для будущей реализации
|
|
23
|
-
// this.api = new Api({
|
|
24
|
-
// apiUrl: url.endsWith('/') ? url : url + '/',
|
|
25
|
-
// });
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async checkOrRegister(params: { tgUsername: string, tgId: number, tgName: string }): Promise<any> {
|
|
30
|
-
if (!this.usersMap.has(params.tgUsername) && this.api) {
|
|
31
|
-
let userData = null;
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
let resApi = await this.api.fetch('user/get/' + params.tgUsername);
|
|
35
|
-
userData = resApi.data;
|
|
36
|
-
} catch (err) {
|
|
37
|
-
let resApi = await this.api.fetch('user/register', 'post', {
|
|
38
|
-
tg_username: params.tgUsername,
|
|
39
|
-
tg_id: params.tgId,
|
|
40
|
-
name: params.tgName,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
userData = resApi.data;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (userData !== null) {
|
|
47
|
-
this.add(params.tgUsername, userData);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return userData;
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
find(tgUsername: string): UserModel {
|
|
56
|
-
return this.usersMap.get(tgUsername) as UserModel;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
findSession(userModel: UserModel): UserSession {
|
|
60
|
-
return this.usersSession.get(userModel) || {};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
exists(tgUsername: string): boolean {
|
|
64
|
-
return this.usersMap.has(tgUsername);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
add(tgUsername: string, data: UserModel | any): boolean {
|
|
68
|
-
if (data instanceof UserModel) {
|
|
69
|
-
this.usersMap.set(tgUsername, data);
|
|
70
|
-
} else {
|
|
71
|
-
this.usersMap.set(tgUsername, new UserModel(data));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
this.usersSession.set(this.usersMap.get(tgUsername) as UserModel, {});
|
|
75
|
-
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
upActive(tgUsername: string): this {
|
|
80
|
-
const user = this.usersMap.get(tgUsername);
|
|
81
|
-
if (user) {
|
|
82
|
-
user.upActive();
|
|
83
|
-
}
|
|
84
|
-
return this;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
storeMessageId(tgUsername: string, messageId: number, limit: number): this {
|
|
88
|
-
const user = this.usersMap.get(tgUsername);
|
|
89
|
-
if (user) {
|
|
90
|
-
user.storeMessageId(messageId, limit);
|
|
91
|
-
}
|
|
92
|
-
return this;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
getLastMessageId(tgUsername: string): number | undefined {
|
|
96
|
-
const user = this.usersMap.get(tgUsername);
|
|
97
|
-
if (user) {
|
|
98
|
-
const ids = user.lastMessageIds;
|
|
99
|
-
return ids.length ? ids[ids.length - 1] : undefined;
|
|
100
|
-
}
|
|
101
|
-
return undefined;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
autocleanup(minutes: number = 1): void {
|
|
105
|
-
const getNotActiveUsers = (): [string, UserModel][] => {
|
|
106
|
-
return Array.from(this.usersMap).filter(([tgUsername, data]) => {
|
|
107
|
-
return (
|
|
108
|
-
data.serviceAttributes.lastActive.getTime() <= Date.now() - minutes * 60 * 1000
|
|
109
|
-
);
|
|
110
|
-
});
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
setInterval(() => {
|
|
114
|
-
getNotActiveUsers().forEach(([tgUsername]) => {
|
|
115
|
-
this.usersMap.delete(tgUsername);
|
|
116
|
-
});
|
|
117
|
-
}, 60 * 1000);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
1
|
+
import { UserModel } from './UserModel';
|
|
2
|
+
import { UserSession } from '../types';
|
|
3
|
+
import { EnvVars } from '../types';
|
|
4
|
+
|
|
5
|
+
interface ApiConfig {
|
|
6
|
+
apiUrl: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Api {
|
|
10
|
+
fetch(endpoint: string, method?: string, data?: any): Promise<any>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class UserStore {
|
|
14
|
+
private usersMap: Map<string, UserModel> = new Map();
|
|
15
|
+
private usersSession: Map<UserModel, UserSession> = new Map();
|
|
16
|
+
private api: Api | null = null;
|
|
17
|
+
|
|
18
|
+
constructor(envConfig?: EnvVars) {
|
|
19
|
+
if (envConfig) {
|
|
20
|
+
let url = envConfig.BOT_API_URL || '';
|
|
21
|
+
|
|
22
|
+
// Здесь должна быть инициализация API, но мы оставим это для будущей реализации
|
|
23
|
+
// this.api = new Api({
|
|
24
|
+
// apiUrl: url.endsWith('/') ? url : url + '/',
|
|
25
|
+
// });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async checkOrRegister(params: { tgUsername: string, tgId: number, tgName: string }): Promise<any> {
|
|
30
|
+
if (!this.usersMap.has(params.tgUsername) && this.api) {
|
|
31
|
+
let userData = null;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
let resApi = await this.api.fetch('user/get/' + params.tgUsername);
|
|
35
|
+
userData = resApi.data;
|
|
36
|
+
} catch (err) {
|
|
37
|
+
let resApi = await this.api.fetch('user/register', 'post', {
|
|
38
|
+
tg_username: params.tgUsername,
|
|
39
|
+
tg_id: params.tgId,
|
|
40
|
+
name: params.tgName,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
userData = resApi.data;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (userData !== null) {
|
|
47
|
+
this.add(params.tgUsername, userData);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return userData;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
find(tgUsername: string): UserModel {
|
|
56
|
+
return this.usersMap.get(tgUsername) as UserModel;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
findSession(userModel: UserModel): UserSession {
|
|
60
|
+
return this.usersSession.get(userModel) || {};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exists(tgUsername: string): boolean {
|
|
64
|
+
return this.usersMap.has(tgUsername);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
add(tgUsername: string, data: UserModel | any): boolean {
|
|
68
|
+
if (data instanceof UserModel) {
|
|
69
|
+
this.usersMap.set(tgUsername, data);
|
|
70
|
+
} else {
|
|
71
|
+
this.usersMap.set(tgUsername, new UserModel(data));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.usersSession.set(this.usersMap.get(tgUsername) as UserModel, {});
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
upActive(tgUsername: string): this {
|
|
80
|
+
const user = this.usersMap.get(tgUsername);
|
|
81
|
+
if (user) {
|
|
82
|
+
user.upActive();
|
|
83
|
+
}
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
storeMessageId(tgUsername: string, messageId: number, limit: number): this {
|
|
88
|
+
const user = this.usersMap.get(tgUsername);
|
|
89
|
+
if (user) {
|
|
90
|
+
user.storeMessageId(messageId, limit);
|
|
91
|
+
}
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getLastMessageId(tgUsername: string): number | undefined {
|
|
96
|
+
const user = this.usersMap.get(tgUsername);
|
|
97
|
+
if (user) {
|
|
98
|
+
const ids = user.lastMessageIds;
|
|
99
|
+
return ids.length ? ids[ids.length - 1] : undefined;
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
autocleanup(minutes: number = 1): void {
|
|
105
|
+
const getNotActiveUsers = (): [string, UserModel][] => {
|
|
106
|
+
return Array.from(this.usersMap).filter(([tgUsername, data]) => {
|
|
107
|
+
return (
|
|
108
|
+
data.serviceAttributes.lastActive.getTime() <= Date.now() - minutes * 60 * 1000
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
setInterval(() => {
|
|
114
|
+
getNotActiveUsers().forEach(([tgUsername]) => {
|
|
115
|
+
this.usersMap.delete(tgUsername);
|
|
116
|
+
});
|
|
117
|
+
}, 60 * 1000);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import { ApiService} from '../../core/ApiService';
|
|
2
|
-
import { App } from '../../core/App';
|
|
3
|
-
import { UserModel } from '../../user/UserModel';
|
|
4
|
-
|
|
5
|
-
export default class MassSendApiService extends ApiService {
|
|
6
|
-
|
|
7
|
-
private bunServerInstance: any;
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
10
|
-
protected app: App,
|
|
11
|
-
public name: string = "MassSendApiService"
|
|
12
|
-
) {
|
|
13
|
-
super(app, name);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public async setup(): Promise<void> {
|
|
17
|
-
return Promise.resolve();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public async unsetup(): Promise<void> {
|
|
21
|
-
return Promise.resolve();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public async run(): Promise<void> {
|
|
25
|
-
this.bunServerInstance = Bun.serve({
|
|
26
|
-
port: this.app.configApp.envConfig.BOT_APP_API_PORT || 3033,
|
|
27
|
-
routes: {
|
|
28
|
-
'/': async (req) => {
|
|
29
|
-
const receivedData = (await req.json()) as { userIds?: number[]; message?: string };
|
|
30
|
-
this.app.debugLog("Received data for mass message:", receivedData);
|
|
31
|
-
|
|
32
|
-
let userIds: number[] = [];
|
|
33
|
-
let message: string = "Hello from MassSendApiService";
|
|
34
|
-
|
|
35
|
-
if (receivedData && typeof receivedData == 'object') {
|
|
36
|
-
userIds = receivedData?.userIds || [];
|
|
37
|
-
message = receivedData?.message || "Hello from MassSendApiService";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
this.sendMassMessage(userIds, message);
|
|
41
|
-
|
|
42
|
-
return Response.json({ status: 200, body: 'Mass message sending initiated.' });
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
this.app.debugLog(`MassSendApiService Bun server running at http://localhost:${this.bunServerInstance.port}/`);
|
|
48
|
-
|
|
49
|
-
return Promise.resolve();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private async sendMassMessage(userIds: number[] = [], message: string): Promise<void> {
|
|
53
|
-
if (userIds.length === 0) {
|
|
54
|
-
|
|
55
|
-
if (!db) {
|
|
56
|
-
throw new Error("Database connection is not established.");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
UserModel.setDatabase(db);
|
|
60
|
-
|
|
61
|
-
this.app.debugLog("Fetching all users for mass message...");
|
|
62
|
-
const users = UserModel.getAll();
|
|
63
|
-
|
|
64
|
-
this.app.debugLog("Fetched users for mass message:", users);
|
|
65
|
-
|
|
66
|
-
if (users && users.length > 0) {
|
|
67
|
-
for (const user of users) {
|
|
68
|
-
this.app.debugLog(`Sending message to user ID: ${user.tgId} username: ${user.username}`);
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
await this.app.bot.telegram.sendMessage(user.tgId, message);
|
|
72
|
-
this.app.debugLog(`Message sent to user ID: ${user.tgId} username: ${user.username}`);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
this.app.debugLog(`Failed to send message to user ID: ${user.tgId} username: ${user.username}`, error);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
1
|
+
import { ApiService} from '../../core/ApiService';
|
|
2
|
+
import { App } from '../../core/App';
|
|
3
|
+
import { UserModel } from '../../user/UserModel';
|
|
4
|
+
|
|
5
|
+
export default class MassSendApiService extends ApiService {
|
|
6
|
+
|
|
7
|
+
private bunServerInstance: any;
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
protected app: App,
|
|
11
|
+
public name: string = "MassSendApiService"
|
|
12
|
+
) {
|
|
13
|
+
super(app, name);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public async setup(): Promise<void> {
|
|
17
|
+
return Promise.resolve();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public async unsetup(): Promise<void> {
|
|
21
|
+
return Promise.resolve();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public async run(): Promise<void> {
|
|
25
|
+
this.bunServerInstance = Bun.serve({
|
|
26
|
+
port: this.app.configApp.envConfig.BOT_APP_API_PORT || 3033,
|
|
27
|
+
routes: {
|
|
28
|
+
'/': async (req) => {
|
|
29
|
+
const receivedData = (await req.json()) as { userIds?: number[]; message?: string };
|
|
30
|
+
this.app.debugLog("Received data for mass message:", receivedData);
|
|
31
|
+
|
|
32
|
+
let userIds: number[] = [];
|
|
33
|
+
let message: string = "Hello from MassSendApiService";
|
|
34
|
+
|
|
35
|
+
if (receivedData && typeof receivedData == 'object') {
|
|
36
|
+
userIds = receivedData?.userIds || [];
|
|
37
|
+
message = receivedData?.message || "Hello from MassSendApiService";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.sendMassMessage(userIds, message);
|
|
41
|
+
|
|
42
|
+
return Response.json({ status: 200, body: 'Mass message sending initiated.' });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
this.app.debugLog(`MassSendApiService Bun server running at http://localhost:${this.bunServerInstance.port}/`);
|
|
48
|
+
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private async sendMassMessage(userIds: number[] = [], message: string): Promise<void> {
|
|
53
|
+
if (userIds.length === 0) {
|
|
54
|
+
|
|
55
|
+
if (!db) {
|
|
56
|
+
throw new Error("Database connection is not established.");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
UserModel.setDatabase(db);
|
|
60
|
+
|
|
61
|
+
this.app.debugLog("Fetching all users for mass message...");
|
|
62
|
+
const users = UserModel.getAll();
|
|
63
|
+
|
|
64
|
+
this.app.debugLog("Fetched users for mass message:", users);
|
|
65
|
+
|
|
66
|
+
if (users && users.length > 0) {
|
|
67
|
+
for (const user of users) {
|
|
68
|
+
this.app.debugLog(`Sending message to user ID: ${user.tgId} username: ${user.username}`);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
await this.app.bot.telegram.sendMessage(user.tgId, message);
|
|
72
|
+
this.app.debugLog(`Message sent to user ID: ${user.tgId} username: ${user.username}`);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
this.app.debugLog(`Failed to send message to user ID: ${user.tgId} username: ${user.username}`, error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,23 +1,34 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
BOT_TOKEN=
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
DATABASE_PATH=./database/database.sqlite
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
LOG_LEVEL=info
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
# Environment variables for Rewardbot Bot
|
|
2
|
+
|
|
3
|
+
# token from @BotFather
|
|
4
|
+
BOT_TOKEN=8333709720:AAEk3AzAmt1JS0XQJQWqUDI
|
|
5
|
+
|
|
6
|
+
# Path to the database
|
|
7
|
+
DATABASE_PATH=./database/database.sqlite
|
|
8
|
+
|
|
9
|
+
# log level: error, warn, info, debug
|
|
10
|
+
LOG_LEVEL=info
|
|
11
|
+
|
|
12
|
+
# port for the bot's application server
|
|
13
|
+
BOT_APP_API_PORT=3033
|
|
14
|
+
# Port for the bot's API server
|
|
15
|
+
BOT_API_URL=https://localhost:3000
|
|
16
|
+
APP_ENV=local
|
|
17
|
+
# enable hot reload for development sections
|
|
18
|
+
BOT_DEV_HOT_RELOAD_SECTIONS=true
|
|
19
|
+
# Bot access mode: public or private
|
|
20
|
+
BOT_ACCESS=private
|
|
21
|
+
# Comma-separated list of access keys for private bot access
|
|
22
|
+
BOT_ACCESS_KEYS=
|
|
23
|
+
# Comma-separated list of Telegram usernames allowed to access the bot (without @)
|
|
24
|
+
ACCESS_USERNAMES=
|
|
25
|
+
# Domain and port for webhook setup
|
|
26
|
+
BOT_HOOK_DOMAIN=example.com
|
|
27
|
+
# Port for webhook setup
|
|
28
|
+
BOT_HOOK_PORT=3000
|
|
29
|
+
# URL for gift page
|
|
30
|
+
GIFT_PAGE=https://reward.com
|
|
31
|
+
|
|
32
|
+
# Telegram API credentials
|
|
33
|
+
TG_APP_ID=2040
|
|
34
|
+
TG_APP_HASH=b18441a1ff607e10a989891a5462e627
|
package/templates/bot/artisan.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { BotArtisan } from '@2byte/tgbot-framework';
|
|
3
|
-
|
|
4
|
-
const artisan = new BotArtisan(__dirname, {
|
|
5
|
-
botName: '{{botName}}',
|
|
6
|
-
sectionsPath: './sections'
|
|
7
|
-
});
|
|
8
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { BotArtisan } from '@2byte/tgbot-framework';
|
|
3
|
+
|
|
4
|
+
const artisan = new BotArtisan(__dirname, {
|
|
5
|
+
botName: '{{botName}}',
|
|
6
|
+
sectionsPath: './sections'
|
|
7
|
+
});
|
|
8
|
+
|
|
9
9
|
artisan.run();
|
package/templates/bot/bot.ts
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import { App } from '@2byte/tgbot-framework';
|
|
2
|
-
import { UserStore } from "@2byte/tgbot-framework";
|
|
3
|
-
import { sectionList } from "./sectionList";
|
|
4
|
-
import { Database } from 'bun:sqlite';
|
|
5
|
-
import { EnvVars } from "@2byte/tgbot-framework";
|
|
6
|
-
|
|
7
|
-
if (import.meta.dirname === undefined) {
|
|
8
|
-
throw new Error("import.meta.dirname is not defined. Ensure you are using a module environment.");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// check if the environment is set up correctly
|
|
12
|
-
const requiredEnvVars: (keyof EnvVars)[] = [
|
|
13
|
-
"BOT_TOKEN",
|
|
14
|
-
"BOT_API_URL",
|
|
15
|
-
"BOT_HOOK_DOMAIN",
|
|
16
|
-
"BOT_HOOK_PORT",
|
|
17
|
-
"BOT_ACCESS",
|
|
18
|
-
"ACCESS_USERNAMES",
|
|
19
|
-
"BOT_ACCESS_KEYS",
|
|
20
|
-
"BOT_APP_API_PORT",
|
|
21
|
-
"TG_APP_ID",
|
|
22
|
-
"TG_APP_HASH",
|
|
23
|
-
];
|
|
24
|
-
for (const envVar of requiredEnvVars) {
|
|
25
|
-
if (!process.env[envVar]) {
|
|
26
|
-
throw new Error(`${envVar} is not set in the environment variables.`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
declare global {
|
|
31
|
-
var userStorage: UserStore;
|
|
32
|
-
var db: Database;
|
|
33
|
-
var settings: Record<string, any>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Initialize global variables
|
|
37
|
-
global.userStorage = new UserStore(process.env as EnvVars);
|
|
38
|
-
global.db = new Database(import.meta.dirname +'/database/database.sqlite');
|
|
39
|
-
global.settings = {
|
|
40
|
-
paging: {
|
|
41
|
-
taskListPerPage: 3, // Number items per page
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// Autoclean storage user by timeout
|
|
46
|
-
userStorage.autocleanup(10);
|
|
47
|
-
|
|
48
|
-
const appController = new App.Builder()
|
|
49
|
-
.botCwd(import.meta.dirname)
|
|
50
|
-
.envConfig(process.env as EnvVars)
|
|
51
|
-
.botToken(process.env.BOT_TOKEN as string)
|
|
52
|
-
.telegrafConfigLaunch({
|
|
53
|
-
// webhook: {
|
|
54
|
-
// // Public domain for webhook; e.g.: example.com
|
|
55
|
-
// domain: process.env.BOT_HOOK_DOMAIN,
|
|
56
|
-
// // Port to listen on; e.g.: 8080
|
|
57
|
-
// port: +process.env.BOT_HOOK_PORT,
|
|
58
|
-
// // Path to listen on nginx
|
|
59
|
-
// path: "/super-mega-tgbot",
|
|
60
|
-
// secretToken: process.env.BOT_HOOK_SECRET_TOKEN,
|
|
61
|
-
// },
|
|
62
|
-
})
|
|
63
|
-
.accessPublic(process.env.BOT_ACCESS === "public")
|
|
64
|
-
.apiUrl(process.env.BOT_API_URL as string)
|
|
65
|
-
.settings(settings)
|
|
66
|
-
.userStorage(userStorage)
|
|
67
|
-
.sections(sectionList)
|
|
68
|
-
.keepSectionInstances(true)
|
|
69
|
-
.debug()
|
|
70
|
-
//.telegrafLog()
|
|
71
|
-
.devHotReloadSections(process.env.BOT_DEV_HOT_RELOAD_SECTIONS === "true")
|
|
72
|
-
.mainMenuKeyboard([
|
|
73
|
-
["🏠 Лобби"],
|
|
74
|
-
])
|
|
75
|
-
.hears({
|
|
76
|
-
"🏠 Лобби": "home",
|
|
77
|
-
})
|
|
78
|
-
.terminateSigInt()
|
|
79
|
-
.terminateSigTerm()
|
|
80
|
-
.build();
|
|
81
|
-
|
|
82
|
-
(await appController.init()).launch();
|
|
1
|
+
import { App } from '@2byte/tgbot-framework';
|
|
2
|
+
import { UserStore } from "@2byte/tgbot-framework";
|
|
3
|
+
import { sectionList } from "./sectionList";
|
|
4
|
+
import { Database } from 'bun:sqlite';
|
|
5
|
+
import { EnvVars } from "@2byte/tgbot-framework";
|
|
6
|
+
|
|
7
|
+
if (import.meta.dirname === undefined) {
|
|
8
|
+
throw new Error("import.meta.dirname is not defined. Ensure you are using a module environment.");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// check if the environment is set up correctly
|
|
12
|
+
const requiredEnvVars: (keyof EnvVars)[] = [
|
|
13
|
+
"BOT_TOKEN",
|
|
14
|
+
"BOT_API_URL",
|
|
15
|
+
"BOT_HOOK_DOMAIN",
|
|
16
|
+
"BOT_HOOK_PORT",
|
|
17
|
+
"BOT_ACCESS",
|
|
18
|
+
"ACCESS_USERNAMES",
|
|
19
|
+
"BOT_ACCESS_KEYS",
|
|
20
|
+
"BOT_APP_API_PORT",
|
|
21
|
+
"TG_APP_ID",
|
|
22
|
+
"TG_APP_HASH",
|
|
23
|
+
];
|
|
24
|
+
for (const envVar of requiredEnvVars) {
|
|
25
|
+
if (!process.env[envVar]) {
|
|
26
|
+
throw new Error(`${envVar} is not set in the environment variables.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare global {
|
|
31
|
+
var userStorage: UserStore;
|
|
32
|
+
var db: Database;
|
|
33
|
+
var settings: Record<string, any>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Initialize global variables
|
|
37
|
+
global.userStorage = new UserStore(process.env as EnvVars);
|
|
38
|
+
global.db = new Database(import.meta.dirname +'/database/database.sqlite');
|
|
39
|
+
global.settings = {
|
|
40
|
+
paging: {
|
|
41
|
+
taskListPerPage: 3, // Number items per page
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Autoclean storage user by timeout
|
|
46
|
+
userStorage.autocleanup(10);
|
|
47
|
+
|
|
48
|
+
const appController = new App.Builder()
|
|
49
|
+
.botCwd(import.meta.dirname)
|
|
50
|
+
.envConfig(process.env as EnvVars)
|
|
51
|
+
.botToken(process.env.BOT_TOKEN as string)
|
|
52
|
+
.telegrafConfigLaunch({
|
|
53
|
+
// webhook: {
|
|
54
|
+
// // Public domain for webhook; e.g.: example.com
|
|
55
|
+
// domain: process.env.BOT_HOOK_DOMAIN,
|
|
56
|
+
// // Port to listen on; e.g.: 8080
|
|
57
|
+
// port: +process.env.BOT_HOOK_PORT,
|
|
58
|
+
// // Path to listen on nginx
|
|
59
|
+
// path: "/super-mega-tgbot",
|
|
60
|
+
// secretToken: process.env.BOT_HOOK_SECRET_TOKEN,
|
|
61
|
+
// },
|
|
62
|
+
})
|
|
63
|
+
.accessPublic(process.env.BOT_ACCESS === "public")
|
|
64
|
+
.apiUrl(process.env.BOT_API_URL as string)
|
|
65
|
+
.settings(settings)
|
|
66
|
+
.userStorage(userStorage)
|
|
67
|
+
.sections(sectionList)
|
|
68
|
+
.keepSectionInstances(true)
|
|
69
|
+
.debug()
|
|
70
|
+
//.telegrafLog()
|
|
71
|
+
.devHotReloadSections(process.env.BOT_DEV_HOT_RELOAD_SECTIONS === "true")
|
|
72
|
+
.mainMenuKeyboard([
|
|
73
|
+
["🏠 Лобби"],
|
|
74
|
+
])
|
|
75
|
+
.hears({
|
|
76
|
+
"🏠 Лобби": "home",
|
|
77
|
+
})
|
|
78
|
+
.terminateSigInt()
|
|
79
|
+
.terminateSigTerm()
|
|
80
|
+
.build();
|
|
81
|
+
|
|
82
|
+
(await appController.init()).launch();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Database } from 'bun:sqlite';
|
|
2
|
-
|
|
3
|
-
export default () => {
|
|
4
|
-
return new Database(import.meta.dirname + '/database.sqlite');
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
|
|
3
|
+
export default () => {
|
|
4
|
+
return new Database(import.meta.dirname + '/database.sqlite');
|
|
5
5
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { BotMigration } from '@2byte/tgbot-framework';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
const migration = new BotMigration({
|
|
5
|
-
botPath: __dirname,
|
|
6
|
-
migrationsPath: path.join(__dirname, 'migrations'),
|
|
7
|
-
databasePath: path.join(__dirname, 'database.sqlite')
|
|
8
|
-
});
|
|
9
|
-
|
|
1
|
+
import { BotMigration } from '@2byte/tgbot-framework';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const migration = new BotMigration({
|
|
5
|
+
botPath: __dirname,
|
|
6
|
+
migrationsPath: path.join(__dirname, 'migrations'),
|
|
7
|
+
databasePath: path.join(__dirname, 'database.sqlite')
|
|
8
|
+
});
|
|
9
|
+
|
|
10
10
|
migration.run();
|