chz-telegram-bot 0.0.23 → 0.0.25
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/dist/entities/actions/scheduledAction.d.ts +1 -1
- package/dist/entities/actions/scheduledAction.d.ts.map +1 -1
- package/dist/entities/actions/scheduledAction.js +1 -0
- package/dist/entities/botInstance.d.ts +1 -1
- package/dist/entities/botInstance.d.ts.map +1 -1
- package/dist/entities/botInstance.js +30 -12
- package/dist/entities/context/chatContext.d.ts +37 -4
- package/dist/entities/context/chatContext.d.ts.map +1 -1
- package/dist/entities/context/chatContext.js +30 -0
- package/dist/entities/context/messageContext.d.ts +34 -3
- package/dist/entities/context/messageContext.d.ts.map +1 -1
- package/dist/entities/context/messageContext.js +29 -4
- package/dist/helpers/builders/commandActionBuilder.d.ts +38 -0
- package/dist/helpers/builders/commandActionBuilder.d.ts.map +1 -1
- package/dist/helpers/builders/commandActionBuilder.js +38 -0
- package/dist/helpers/builders/scheduledActionBuilder.d.ts +34 -0
- package/dist/helpers/builders/scheduledActionBuilder.d.ts.map +1 -1
- package/dist/helpers/builders/scheduledActionBuilder.js +34 -0
- package/dist/helpers/reverseRecord.d.ts +2 -0
- package/dist/helpers/reverseRecord.d.ts.map +1 -0
- package/dist/helpers/reverseRecord.js +6 -0
- package/dist/main.d.ts +14 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +7 -1
- package/dist/services/taskScheduler.d.ts.map +1 -1
- package/dist/services/taskScheduler.js +1 -2
- package/dist/services/telegramApi.d.ts +7 -4
- package/dist/services/telegramApi.d.ts.map +1 -1
- package/dist/services/telegramApi.js +8 -7
- package/dist/types/handlers.d.ts +12 -2
- package/dist/types/handlers.d.ts.map +1 -1
- package/entities/actions/scheduledAction.ts +2 -1
- package/entities/botInstance.ts +52 -17
- package/entities/context/chatContext.ts +42 -4
- package/entities/context/messageContext.ts +34 -8
- package/helpers/builders/commandActionBuilder.ts +38 -0
- package/helpers/builders/scheduledActionBuilder.ts +34 -0
- package/helpers/reverseRecord.ts +7 -0
- package/main.ts +15 -2
- package/package.json +1 -1
- package/services/taskScheduler.ts +2 -3
- package/services/telegramApi.ts +22 -14
- package/types/handlers.ts +6 -1
- package/helpers/reverseMap.ts +0 -3
|
@@ -7,6 +7,9 @@ import { IActionState } from '../../types/actionState';
|
|
|
7
7
|
import { toArray } from '../toArray';
|
|
8
8
|
import { Noop } from '../noop';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Builder for `CommandAction` with state represented by `TActionState`
|
|
12
|
+
*/
|
|
10
13
|
export class CommandActionBuilderWithState<TActionState extends IActionState> {
|
|
11
14
|
name: string;
|
|
12
15
|
trigger: string | RegExp | Array<string> | Array<RegExp> = [];
|
|
@@ -19,53 +22,82 @@ export class CommandActionBuilderWithState<TActionState extends IActionState> {
|
|
|
19
22
|
handler: CommandHandler<TActionState> = Noop.call;
|
|
20
23
|
condition: CommandCondition<TActionState> = Noop.true;
|
|
21
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Builder for `CommandAction` with state represented by `TActionState`
|
|
27
|
+
* @param name Action name, will be used for logging and storage
|
|
28
|
+
* @param stateConstructor Function that creates default state object
|
|
29
|
+
*/
|
|
22
30
|
constructor(name: string, stateConstructor: () => TActionState) {
|
|
23
31
|
this.name = name;
|
|
24
32
|
this.stateConstructor = stateConstructor;
|
|
25
33
|
}
|
|
26
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Defines action trigger
|
|
37
|
+
* @param trigger If `string` or `string[]` is provided, will be triggered only on exact message match.
|
|
38
|
+
*
|
|
39
|
+
* If `RegExp` or `RegExp[]` is provided, will be triggered on successful match.
|
|
40
|
+
*/
|
|
27
41
|
on(trigger: string | RegExp | Array<string> | Array<RegExp>) {
|
|
28
42
|
this.trigger = trigger;
|
|
29
43
|
|
|
30
44
|
return this;
|
|
31
45
|
}
|
|
32
46
|
|
|
47
|
+
/** Defines id (or ids) of users that are allowed to trigger this action.
|
|
48
|
+
* @param id User id or ids
|
|
49
|
+
*/
|
|
33
50
|
from(id: number | Array<number>) {
|
|
34
51
|
this.allowedUsers = toArray(id);
|
|
35
52
|
|
|
36
53
|
return this;
|
|
37
54
|
}
|
|
38
55
|
|
|
56
|
+
/** Defines action logic itself, will be executed on trigger.
|
|
57
|
+
* @param handler Callback that will be called on trigger
|
|
58
|
+
*/
|
|
39
59
|
do(handler: CommandHandler<TActionState>) {
|
|
40
60
|
this.handler = handler;
|
|
41
61
|
|
|
42
62
|
return this;
|
|
43
63
|
}
|
|
44
64
|
|
|
65
|
+
/** Defines condition that will be checked before trigger match check is executed.
|
|
66
|
+
* @param condition Condition check predicate
|
|
67
|
+
*/
|
|
45
68
|
when(condition: CommandCondition<TActionState>) {
|
|
46
69
|
this.condition = condition;
|
|
47
70
|
|
|
48
71
|
return this;
|
|
49
72
|
}
|
|
50
73
|
|
|
74
|
+
/** If called during building, action is marked as disabled and never checked. */
|
|
51
75
|
disabled() {
|
|
52
76
|
this.active = false;
|
|
53
77
|
|
|
54
78
|
return this;
|
|
55
79
|
}
|
|
56
80
|
|
|
81
|
+
/** Sets action cooldown.
|
|
82
|
+
* @param seconds Cooldown in seconds.
|
|
83
|
+
*/
|
|
57
84
|
cooldown(seconds: Seconds) {
|
|
58
85
|
this.cooldownSeconds = seconds;
|
|
59
86
|
|
|
60
87
|
return this;
|
|
61
88
|
}
|
|
62
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Adds a chat to ignore list for this action.
|
|
92
|
+
* @param chatId Chat id to ignore.
|
|
93
|
+
*/
|
|
63
94
|
ignoreChat(chatId: number) {
|
|
64
95
|
this.blacklist.push(chatId);
|
|
65
96
|
|
|
66
97
|
return this;
|
|
67
98
|
}
|
|
68
99
|
|
|
100
|
+
/** Builds action */
|
|
69
101
|
build() {
|
|
70
102
|
return new CommandAction(
|
|
71
103
|
this.trigger,
|
|
@@ -81,7 +113,13 @@ export class CommandActionBuilderWithState<TActionState extends IActionState> {
|
|
|
81
113
|
}
|
|
82
114
|
}
|
|
83
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Builder for `CommandAction` with state represented by default state (containing only last execution date).
|
|
118
|
+
*/
|
|
84
119
|
export class CommandActionBuilder extends CommandActionBuilderWithState<ActionStateBase> {
|
|
120
|
+
/**
|
|
121
|
+
* Builder for `CommandAction` with state represented by default state (containing only last execution date).
|
|
122
|
+
*/
|
|
85
123
|
constructor(name: string) {
|
|
86
124
|
super(name, () => new ActionStateBase());
|
|
87
125
|
}
|
|
@@ -6,6 +6,9 @@ import { ScheduledHandler } from '../../types/handlers';
|
|
|
6
6
|
import { Hours, HoursOfDay } from '../../types/timeValues';
|
|
7
7
|
import { Noop } from '../noop';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Builder for `ScheduledAction` with state represented by `TActionState`
|
|
11
|
+
*/
|
|
9
12
|
export class ScheduledActionBuilderWithState<
|
|
10
13
|
TActionState extends IActionState
|
|
11
14
|
> {
|
|
@@ -18,29 +21,52 @@ export class ScheduledActionBuilderWithState<
|
|
|
18
21
|
|
|
19
22
|
name: string;
|
|
20
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Builder for `ScheduledAction` with state represented by `TActionState`
|
|
26
|
+
* @param name Action name, will be used for logging and storage
|
|
27
|
+
* @param stateConstructor Function that creates default state object
|
|
28
|
+
*/
|
|
21
29
|
constructor(name: string, stateConstructor: () => TActionState) {
|
|
22
30
|
this.name = name;
|
|
23
31
|
this.stateConstructor = stateConstructor;
|
|
24
32
|
}
|
|
25
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Adds a chat to whitelist for this action.
|
|
36
|
+
* @param chatId Chat id to execute in.
|
|
37
|
+
*/
|
|
26
38
|
allowIn(chatId: number) {
|
|
27
39
|
this.whitelist.push(chatId);
|
|
28
40
|
|
|
29
41
|
return this;
|
|
30
42
|
}
|
|
31
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Defines time for scheduled item execution.
|
|
46
|
+
* @param time Time of day (0 - 23) to execute action.
|
|
47
|
+
*/
|
|
32
48
|
runAt(time: HoursOfDay) {
|
|
33
49
|
this.time = time;
|
|
34
50
|
|
|
35
51
|
return this;
|
|
36
52
|
}
|
|
37
53
|
|
|
54
|
+
/** Defines action logic itself, will be executed on timer.
|
|
55
|
+
* @param handler Callback that will be called on timer.
|
|
56
|
+
*/
|
|
38
57
|
do(handler: ScheduledHandler<TActionState>) {
|
|
39
58
|
this.handler = handler;
|
|
40
59
|
|
|
41
60
|
return this;
|
|
42
61
|
}
|
|
43
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Defines process-wide cache, that is shared by all actions of this type (even in different bot instances).
|
|
65
|
+
* Can be used for fetch request de-duping, etc.
|
|
66
|
+
* @param key Key that will be used to retrieve value from cache.
|
|
67
|
+
* @param itemFactory Callback that will be executed once to create cached value.
|
|
68
|
+
* @param invalidationTimeoutInHours Timeout for cache invalidation.
|
|
69
|
+
*/
|
|
44
70
|
withSharedCache(
|
|
45
71
|
key: string,
|
|
46
72
|
itemFactory: () => Promise<unknown>,
|
|
@@ -54,12 +80,14 @@ export class ScheduledActionBuilderWithState<
|
|
|
54
80
|
return this;
|
|
55
81
|
}
|
|
56
82
|
|
|
83
|
+
/** If called during building, action is marked as disabled and never checked. */
|
|
57
84
|
disabled() {
|
|
58
85
|
this.active = false;
|
|
59
86
|
|
|
60
87
|
return this;
|
|
61
88
|
}
|
|
62
89
|
|
|
90
|
+
/** Builds action */
|
|
63
91
|
build() {
|
|
64
92
|
return new ScheduledAction<TActionState>(
|
|
65
93
|
this.name,
|
|
@@ -73,7 +101,13 @@ export class ScheduledActionBuilderWithState<
|
|
|
73
101
|
}
|
|
74
102
|
}
|
|
75
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Builder for `ScheduledAction` with state represented by default state (containing only last execution date).
|
|
106
|
+
*/
|
|
76
107
|
export class ScheduledActionBuilder extends ScheduledActionBuilderWithState<ActionStateBase> {
|
|
108
|
+
/**
|
|
109
|
+
* Builder for `ScheduledAction` with state represented by default state (containing only last execution date).
|
|
110
|
+
*/
|
|
77
111
|
constructor(name: string) {
|
|
78
112
|
super(name, () => new ActionStateBase());
|
|
79
113
|
}
|
package/main.ts
CHANGED
|
@@ -13,13 +13,23 @@ function log(text: string) {
|
|
|
13
13
|
Logger.logWithTraceId('ALL BOTS', 'System:Bot', 'System', text);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Starts bot
|
|
18
|
+
*/
|
|
16
19
|
async function startBot(options: {
|
|
20
|
+
/** Bot name, used in logging */
|
|
17
21
|
name: string;
|
|
22
|
+
/** Path to file containing Telegram Bot token. */
|
|
18
23
|
tokenFilePath: string;
|
|
24
|
+
/** Collection of actions that will be executed as a response to message from used. Created using `CommandActionBuilder`.*/
|
|
19
25
|
commands: CommandAction<IActionState>[];
|
|
26
|
+
/** Collection of actions that will be executed on timer. Created using `ScheduledActionBuilder`.*/
|
|
20
27
|
scheduled: ScheduledAction<IActionState>[];
|
|
21
|
-
|
|
28
|
+
/** Object containing chat name and chat id pairs. Used for logging and execution of scheduled action. */
|
|
29
|
+
chats: Record<string, number>;
|
|
30
|
+
/** Storage client for bot state storage. If not provided, default `JsonFileStorage` will be used. */
|
|
22
31
|
storageClient?: IStorageClient;
|
|
32
|
+
/** Storage path for default `JsonFileStorage` client. Will be used only if `storageClient` is not provided. If not provided, default value of `./storage/` will be used.*/
|
|
23
33
|
storagePath?: string;
|
|
24
34
|
}) {
|
|
25
35
|
const token = await readFile(options.tokenFilePath, 'utf8');
|
|
@@ -37,6 +47,9 @@ async function startBot(options: {
|
|
|
37
47
|
return bot;
|
|
38
48
|
}
|
|
39
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Terminates all scheduled tasks, closes storage connections and stops all bots.
|
|
52
|
+
*/
|
|
40
53
|
async function stopBots(reason: string) {
|
|
41
54
|
log(`Recieved termination code: ${reason}`);
|
|
42
55
|
Scheduler.stopAll();
|
|
@@ -44,7 +57,7 @@ async function stopBots(reason: string) {
|
|
|
44
57
|
|
|
45
58
|
log('Stopping bots...');
|
|
46
59
|
for (const bot of bots) {
|
|
47
|
-
bot.stop(reason);
|
|
60
|
+
await bot.stop(reason);
|
|
48
61
|
}
|
|
49
62
|
}
|
|
50
63
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { TaskRecord } from '../entities/taskRecord';
|
|
2
|
-
import {
|
|
3
|
-
import { Milliseconds, Seconds } from '../types/timeValues';
|
|
2
|
+
import { Milliseconds } from '../types/timeValues';
|
|
4
3
|
import { Logger } from './logger';
|
|
5
4
|
|
|
6
5
|
class TaskScheduler {
|
|
@@ -24,7 +23,7 @@ class TaskScheduler {
|
|
|
24
23
|
const task = new TaskRecord(name, taskId, interval);
|
|
25
24
|
|
|
26
25
|
if (executeRightAway) {
|
|
27
|
-
|
|
26
|
+
setImmediate(action);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
Logger.logWithTraceId(
|
package/services/telegramApi.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InputFile, Message } from 'telegraf/types';
|
|
2
2
|
import { ChatContext } from '../entities/context/chatContext';
|
|
3
3
|
import { MessageContext } from '../entities/context/messageContext';
|
|
4
|
-
import {
|
|
4
|
+
import { reverseRecord } from '../helpers/reverseRecord';
|
|
5
5
|
import { IStorageClient } from '../types/storage';
|
|
6
6
|
import { Logger } from './logger';
|
|
7
7
|
import { Reaction } from '../entities/responses/reaction';
|
|
@@ -14,6 +14,9 @@ import { ImageMessage } from '../entities/responses/imageMessage';
|
|
|
14
14
|
import { Telegram } from 'telegraf/typings/telegram';
|
|
15
15
|
import { setTimeout } from 'timers/promises';
|
|
16
16
|
import { Milliseconds } from '../types/timeValues';
|
|
17
|
+
import { ScheduledAction } from '../entities/actions/scheduledAction';
|
|
18
|
+
import { IActionState } from '../types/actionState';
|
|
19
|
+
import { CommandAction } from '../entities/actions/commandAction';
|
|
17
20
|
|
|
18
21
|
export class TelegramApiService {
|
|
19
22
|
isFlushing = false;
|
|
@@ -21,24 +24,26 @@ export class TelegramApiService {
|
|
|
21
24
|
|
|
22
25
|
botName: string;
|
|
23
26
|
telegram: Telegram;
|
|
24
|
-
chats:
|
|
27
|
+
chats: Record<number, string>;
|
|
25
28
|
storage: IStorageClient;
|
|
26
29
|
|
|
27
30
|
constructor(
|
|
28
31
|
botName: string,
|
|
29
32
|
telegram: Telegram,
|
|
30
33
|
storage: IStorageClient,
|
|
31
|
-
chats:
|
|
34
|
+
chats: Record<string, number>
|
|
32
35
|
) {
|
|
33
36
|
this.telegram = telegram;
|
|
34
37
|
this.botName = botName;
|
|
35
|
-
this.chats =
|
|
38
|
+
this.chats = reverseRecord(chats);
|
|
36
39
|
this.storage = storage;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
async flushResponses() {
|
|
40
43
|
if (this.isFlushing) return;
|
|
41
44
|
|
|
45
|
+
this.isFlushing = true;
|
|
46
|
+
|
|
42
47
|
while (this.messageQueue.length) {
|
|
43
48
|
const message = this.messageQueue.pop();
|
|
44
49
|
|
|
@@ -51,7 +56,7 @@ export class TelegramApiService {
|
|
|
51
56
|
Logger.errorWithTraceId(
|
|
52
57
|
this.botName,
|
|
53
58
|
message.traceId,
|
|
54
|
-
this.chats
|
|
59
|
+
this.chats[message.chatId],
|
|
55
60
|
error,
|
|
56
61
|
message
|
|
57
62
|
);
|
|
@@ -169,18 +174,18 @@ export class TelegramApiService {
|
|
|
169
174
|
} as IBotApiInteractions;
|
|
170
175
|
}
|
|
171
176
|
|
|
172
|
-
createContextForMessage(
|
|
177
|
+
createContextForMessage<TActionState extends IActionState>(
|
|
173
178
|
incomingMessage: IncomingMessage,
|
|
174
|
-
|
|
179
|
+
command: CommandAction<TActionState>
|
|
175
180
|
) {
|
|
176
181
|
const firstName = incomingMessage.from?.first_name ?? 'Unknown user';
|
|
177
182
|
const lastName = incomingMessage.from?.last_name
|
|
178
183
|
? ` ${incomingMessage.from?.last_name}`
|
|
179
184
|
: '';
|
|
180
185
|
|
|
181
|
-
return new MessageContext(
|
|
186
|
+
return new MessageContext<TActionState>(
|
|
182
187
|
this.botName,
|
|
183
|
-
|
|
188
|
+
command.key,
|
|
184
189
|
this.getInteractions(),
|
|
185
190
|
incomingMessage.chat.id,
|
|
186
191
|
incomingMessage.chatName,
|
|
@@ -193,14 +198,17 @@ export class TelegramApiService {
|
|
|
193
198
|
);
|
|
194
199
|
}
|
|
195
200
|
|
|
196
|
-
createContextForChat
|
|
197
|
-
|
|
201
|
+
createContextForChat<TActionState extends IActionState>(
|
|
202
|
+
chatId: number,
|
|
203
|
+
scheduledAction: ScheduledAction<TActionState>
|
|
204
|
+
) {
|
|
205
|
+
return new ChatContext<TActionState>(
|
|
198
206
|
this.botName,
|
|
199
|
-
|
|
207
|
+
scheduledAction.key,
|
|
200
208
|
this.getInteractions(),
|
|
201
209
|
chatId,
|
|
202
|
-
this.chats
|
|
203
|
-
`Scheduled:${
|
|
210
|
+
this.chats[chatId],
|
|
211
|
+
`Scheduled:${scheduledAction.key}:${chatId}`,
|
|
204
212
|
this.storage
|
|
205
213
|
);
|
|
206
214
|
}
|
package/types/handlers.ts
CHANGED
|
@@ -4,12 +4,17 @@ import { IActionState } from './actionState';
|
|
|
4
4
|
import { CachedValueAccessor } from './cachedValueAccessor';
|
|
5
5
|
|
|
6
6
|
export type CommandHandler<TActionState extends IActionState> = (
|
|
7
|
+
/** Context of action executed in chat, in response to a message. */
|
|
7
8
|
ctx: MessageContext<TActionState>,
|
|
9
|
+
/** State of an action being executed. */
|
|
8
10
|
state: TActionState
|
|
9
11
|
) => Promise<void>;
|
|
10
12
|
|
|
11
13
|
export type ScheduledHandler<TActionState extends IActionState> = (
|
|
12
|
-
|
|
14
|
+
/** Context of action executed in chat. */
|
|
15
|
+
ctx: ChatContext<TActionState>,
|
|
16
|
+
/** Function that will attempt to get value from cache. If there is no value found, corresponding cached state factory will be called. */
|
|
13
17
|
getCached: CachedValueAccessor,
|
|
18
|
+
/** State of an action being executed. */
|
|
14
19
|
state: TActionState
|
|
15
20
|
) => Promise<void>;
|
package/helpers/reverseMap.ts
DELETED