chz-telegram-bot 0.0.50 → 0.0.52
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/dtos/actionExecutionResult.d.ts +7 -0
- package/dist/dtos/actionExecutionResult.d.ts.map +1 -0
- package/dist/dtos/actionExecutionResult.js +10 -0
- package/dist/dtos/chatInfo.d.ts +8 -0
- package/dist/dtos/chatInfo.d.ts.map +1 -0
- package/dist/dtos/chatInfo.js +10 -0
- package/dist/dtos/commandTriggerCheckResult.d.ts +10 -0
- package/dist/dtos/commandTriggerCheckResult.d.ts.map +1 -0
- package/dist/dtos/commandTriggerCheckResult.js +20 -0
- package/dist/dtos/incomingMessage.d.ts +14 -0
- package/dist/dtos/incomingMessage.d.ts.map +1 -0
- package/dist/dtos/incomingMessage.js +44 -0
- package/dist/dtos/responses/delay.d.ts +14 -0
- package/dist/dtos/responses/delay.d.ts.map +1 -0
- package/dist/dtos/responses/delay.js +14 -0
- package/dist/dtos/responses/imageMessage.d.ts +18 -0
- package/dist/dtos/responses/imageMessage.d.ts.map +1 -0
- package/dist/dtos/responses/imageMessage.js +17 -0
- package/dist/dtos/responses/reaction.d.ts +15 -0
- package/dist/dtos/responses/reaction.d.ts.map +1 -0
- package/dist/dtos/responses/reaction.js +15 -0
- package/dist/dtos/responses/textMessage.d.ts +17 -0
- package/dist/dtos/responses/textMessage.d.ts.map +1 -0
- package/dist/dtos/responses/textMessage.js +17 -0
- package/dist/dtos/responses/unpin.d.ts +13 -0
- package/dist/dtos/responses/unpin.d.ts.map +1 -0
- package/dist/dtos/responses/unpin.js +14 -0
- package/dist/dtos/responses/videoMessage.d.ts +18 -0
- package/dist/dtos/responses/videoMessage.d.ts.map +1 -0
- package/dist/dtos/responses/videoMessage.js +17 -0
- package/dist/entities/actions/commandAction.d.ts +11 -10
- package/dist/entities/actions/commandAction.d.ts.map +1 -1
- package/dist/entities/actions/commandAction.js +41 -40
- package/dist/entities/actions/scheduledAction.d.ts +11 -11
- package/dist/entities/actions/scheduledAction.d.ts.map +1 -1
- package/dist/entities/actions/scheduledAction.js +14 -18
- package/dist/entities/botInstance.d.ts +16 -8
- package/dist/entities/botInstance.d.ts.map +1 -1
- package/dist/entities/botInstance.js +26 -18
- package/dist/entities/cachedStateFactory.d.ts +2 -2
- package/dist/entities/cachedStateFactory.d.ts.map +1 -1
- package/dist/entities/context/chatContext.d.ts +13 -14
- package/dist/entities/context/chatContext.d.ts.map +1 -1
- package/dist/entities/context/chatContext.js +16 -24
- package/dist/entities/context/messageContext.d.ts +5 -3
- package/dist/entities/context/messageContext.d.ts.map +1 -1
- package/dist/entities/context/messageContext.js +13 -13
- package/dist/entities/taskRecord.d.ts +3 -3
- package/dist/entities/taskRecord.d.ts.map +1 -1
- package/dist/helpers/noop.d.ts +4 -2
- package/dist/helpers/noop.d.ts.map +1 -1
- package/dist/helpers/noop.js +3 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/main.d.ts +10 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +6 -11
- package/dist/services/jsonFileStorage.d.ts +5 -6
- package/dist/services/jsonFileStorage.d.ts.map +1 -1
- package/dist/services/jsonFileStorage.js +3 -5
- package/dist/services/jsonLogger.d.ts +8 -0
- package/dist/services/jsonLogger.d.ts.map +1 -0
- package/dist/services/jsonLogger.js +28 -0
- package/dist/services/nodeTimeoutScheduler.d.ts +13 -0
- package/dist/services/nodeTimeoutScheduler.d.ts.map +1 -0
- package/dist/services/nodeTimeoutScheduler.js +33 -0
- package/dist/services/taskScheduler.d.ts +1 -1
- package/dist/services/taskScheduler.d.ts.map +1 -1
- package/dist/services/telegramApi.d.ts +7 -14
- package/dist/services/telegramApi.d.ts.map +1 -1
- package/dist/services/telegramApi.js +12 -20
- package/dist/types/actionWithState.d.ts +2 -2
- package/dist/types/actionWithState.d.ts.map +1 -1
- package/dist/types/commandCondition.d.ts +1 -1
- package/dist/types/commandCondition.d.ts.map +1 -1
- package/dist/types/logger.d.ts +6 -0
- package/dist/types/logger.d.ts.map +1 -0
- package/dist/types/logger.js +2 -0
- package/dist/types/response.d.ts +15 -14
- package/dist/types/response.d.ts.map +1 -1
- package/dist/types/scheduler.d.ts +7 -0
- package/dist/types/scheduler.d.ts.map +1 -0
- package/dist/types/scheduler.js +2 -0
- package/dist/types/storage.d.ts +1 -2
- package/dist/types/storage.d.ts.map +1 -1
- package/dtos/chatInfo.ts +11 -0
- package/{entities → dtos}/commandTriggerCheckResult.ts +10 -10
- package/{entities → dtos}/incomingMessage.ts +13 -12
- package/{entities → dtos}/responses/delay.ts +8 -7
- package/{entities → dtos}/responses/imageMessage.ts +11 -10
- package/{entities → dtos}/responses/reaction.ts +9 -8
- package/{entities → dtos}/responses/textMessage.ts +11 -10
- package/{entities → dtos}/responses/unpin.ts +8 -7
- package/{entities → dtos}/responses/videoMessage.ts +11 -10
- package/entities/actions/commandAction.ts +64 -56
- package/entities/actions/scheduledAction.ts +40 -43
- package/entities/botInstance.ts +64 -35
- package/entities/cachedStateFactory.ts +2 -2
- package/entities/context/chatContext.ts +40 -34
- package/entities/context/messageContext.ts +21 -18
- package/entities/taskRecord.ts +3 -3
- package/helpers/noop.ts +5 -2
- package/index.ts +3 -1
- package/main.ts +16 -15
- package/package.json +1 -1
- package/services/jsonFileStorage.ts +8 -10
- package/services/{logger.ts → jsonLogger.ts} +3 -3
- package/services/{taskScheduler.ts → nodeTimeoutScheduler.ts} +12 -8
- package/services/telegramApi.ts +19 -54
- package/types/actionWithState.ts +2 -2
- package/types/commandCondition.ts +1 -1
- package/types/logger.ts +24 -0
- package/types/response.ts +15 -14
- package/types/scheduler.ts +20 -0
- package/types/storage.ts +1 -2
- package/entities/actionExecutionResult.ts +0 -11
- package/helpers/inverseRecord.ts +0 -7
|
@@ -3,28 +3,29 @@ import { BotResponseTypes, IReplyMessage } from '../../types/response';
|
|
|
3
3
|
import { MessageSendingOptions } from '../../types/messageSendingOptions';
|
|
4
4
|
import { IActionWithState } from '../../types/actionWithState';
|
|
5
5
|
import { IActionState } from '../../types/actionState';
|
|
6
|
+
import { ChatInfo } from '../chatInfo';
|
|
6
7
|
|
|
7
8
|
export class ImageMessage implements IReplyMessage<InputFile> {
|
|
8
|
-
kind = BotResponseTypes.image;
|
|
9
|
+
readonly kind = BotResponseTypes.image;
|
|
9
10
|
|
|
10
|
-
content: InputFile;
|
|
11
|
-
|
|
12
|
-
replyId: number | undefined;
|
|
13
|
-
traceId: string | number;
|
|
14
|
-
disableWebPreview = false;
|
|
15
|
-
shouldPin: boolean;
|
|
16
|
-
action: IActionWithState<IActionState>;
|
|
11
|
+
readonly content: InputFile;
|
|
12
|
+
readonly chatInfo: ChatInfo;
|
|
13
|
+
readonly replyId: number | undefined;
|
|
14
|
+
readonly traceId: string | number;
|
|
15
|
+
readonly disableWebPreview = false;
|
|
16
|
+
readonly shouldPin: boolean;
|
|
17
|
+
readonly action: IActionWithState<IActionState>;
|
|
17
18
|
|
|
18
19
|
constructor(
|
|
19
20
|
image: InputFile,
|
|
20
|
-
|
|
21
|
+
chatInfo: ChatInfo,
|
|
21
22
|
replyId: number | undefined,
|
|
22
23
|
traceId: number | string,
|
|
23
24
|
action: IActionWithState<IActionState>,
|
|
24
25
|
options?: MessageSendingOptions
|
|
25
26
|
) {
|
|
26
27
|
this.content = image;
|
|
27
|
-
this.
|
|
28
|
+
this.chatInfo = chatInfo;
|
|
28
29
|
this.replyId = replyId;
|
|
29
30
|
this.traceId = traceId;
|
|
30
31
|
this.shouldPin = options?.pin ?? false;
|
|
@@ -2,24 +2,25 @@ import { TelegramEmoji } from 'telegraf/types';
|
|
|
2
2
|
import { BotResponseTypes, IChatResponse } from '../../types/response';
|
|
3
3
|
import { IActionWithState } from '../../types/actionWithState';
|
|
4
4
|
import { IActionState } from '../../types/actionState';
|
|
5
|
+
import { ChatInfo } from '../chatInfo';
|
|
5
6
|
|
|
6
7
|
export class Reaction implements IChatResponse {
|
|
7
|
-
kind = BotResponseTypes.react;
|
|
8
|
+
readonly kind = BotResponseTypes.react;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
messageId: number;
|
|
11
|
-
traceId: number | string;
|
|
12
|
-
emoji: TelegramEmoji;
|
|
13
|
-
action: IActionWithState<IActionState>;
|
|
10
|
+
readonly chatInfo: ChatInfo;
|
|
11
|
+
readonly messageId: number;
|
|
12
|
+
readonly traceId: number | string;
|
|
13
|
+
readonly emoji: TelegramEmoji;
|
|
14
|
+
readonly action: IActionWithState<IActionState>;
|
|
14
15
|
|
|
15
16
|
constructor(
|
|
16
17
|
traceId: number | string,
|
|
17
|
-
|
|
18
|
+
chatInfo: ChatInfo,
|
|
18
19
|
messageId: number,
|
|
19
20
|
emoji: TelegramEmoji,
|
|
20
21
|
action: IActionWithState<IActionState>
|
|
21
22
|
) {
|
|
22
|
-
this.
|
|
23
|
+
this.chatInfo = chatInfo;
|
|
23
24
|
this.messageId = messageId;
|
|
24
25
|
this.emoji = emoji;
|
|
25
26
|
this.traceId = traceId;
|
|
@@ -2,28 +2,29 @@ import { TextMessageSendingOptions } from '../../types/messageSendingOptions';
|
|
|
2
2
|
import { BotResponseTypes, IReplyMessage } from '../../types/response';
|
|
3
3
|
import { IActionWithState } from '../../types/actionWithState';
|
|
4
4
|
import { IActionState } from '../../types/actionState';
|
|
5
|
+
import { ChatInfo } from '../chatInfo';
|
|
5
6
|
|
|
6
7
|
export class TextMessage implements IReplyMessage<string> {
|
|
7
|
-
kind = BotResponseTypes.text;
|
|
8
|
+
readonly kind = BotResponseTypes.text;
|
|
8
9
|
|
|
9
|
-
content: string;
|
|
10
|
-
|
|
11
|
-
replyId: number | undefined;
|
|
12
|
-
traceId: string | number;
|
|
13
|
-
disableWebPreview: boolean;
|
|
14
|
-
shouldPin: boolean;
|
|
15
|
-
action: IActionWithState<IActionState>;
|
|
10
|
+
readonly content: string;
|
|
11
|
+
readonly chatInfo: ChatInfo;
|
|
12
|
+
readonly replyId: number | undefined;
|
|
13
|
+
readonly traceId: string | number;
|
|
14
|
+
readonly disableWebPreview: boolean;
|
|
15
|
+
readonly shouldPin: boolean;
|
|
16
|
+
readonly action: IActionWithState<IActionState>;
|
|
16
17
|
|
|
17
18
|
constructor(
|
|
18
19
|
text: string,
|
|
19
|
-
|
|
20
|
+
chatInfo: ChatInfo,
|
|
20
21
|
replyId: number | undefined,
|
|
21
22
|
traceId: string | number,
|
|
22
23
|
action: IActionWithState<IActionState>,
|
|
23
24
|
options?: TextMessageSendingOptions
|
|
24
25
|
) {
|
|
25
26
|
this.content = text;
|
|
26
|
-
this.
|
|
27
|
+
this.chatInfo = chatInfo;
|
|
27
28
|
this.replyId = replyId;
|
|
28
29
|
this.traceId = traceId;
|
|
29
30
|
this.disableWebPreview = options?.disableWebPreview ?? false;
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { BotResponseTypes, IChatResponse } from '../../types/response';
|
|
2
2
|
import { IActionWithState } from '../../types/actionWithState';
|
|
3
3
|
import { IActionState } from '../../types/actionState';
|
|
4
|
+
import { ChatInfo } from '../chatInfo';
|
|
4
5
|
|
|
5
6
|
export class UnpinResponse implements IChatResponse {
|
|
6
|
-
kind = BotResponseTypes.unpin;
|
|
7
|
+
readonly kind = BotResponseTypes.unpin;
|
|
7
8
|
|
|
8
|
-
messageId: number;
|
|
9
|
-
|
|
10
|
-
traceId: number | string;
|
|
11
|
-
action: IActionWithState<IActionState>;
|
|
9
|
+
readonly messageId: number;
|
|
10
|
+
readonly chatInfo: ChatInfo;
|
|
11
|
+
readonly traceId: number | string;
|
|
12
|
+
readonly action: IActionWithState<IActionState>;
|
|
12
13
|
|
|
13
14
|
constructor(
|
|
14
15
|
messageId: number,
|
|
15
|
-
|
|
16
|
+
chatInfo: ChatInfo,
|
|
16
17
|
traceId: number | string,
|
|
17
18
|
action: IActionWithState<IActionState>
|
|
18
19
|
) {
|
|
19
20
|
this.messageId = messageId;
|
|
20
|
-
this.
|
|
21
|
+
this.chatInfo = chatInfo;
|
|
21
22
|
this.traceId = traceId;
|
|
22
23
|
this.action = action;
|
|
23
24
|
}
|
|
@@ -3,28 +3,29 @@ import { BotResponseTypes, IReplyMessage } from '../../types/response';
|
|
|
3
3
|
import { MessageSendingOptions } from '../../types/messageSendingOptions';
|
|
4
4
|
import { IActionWithState } from '../../types/actionWithState';
|
|
5
5
|
import { IActionState } from '../../types/actionState';
|
|
6
|
+
import { ChatInfo } from '../chatInfo';
|
|
6
7
|
|
|
7
8
|
export class VideoMessage implements IReplyMessage<InputFile> {
|
|
8
|
-
kind = BotResponseTypes.video;
|
|
9
|
+
readonly kind = BotResponseTypes.video;
|
|
9
10
|
|
|
10
|
-
content: InputFile;
|
|
11
|
-
|
|
12
|
-
replyId: number | undefined;
|
|
13
|
-
traceId: string | number;
|
|
14
|
-
disableWebPreview = false;
|
|
15
|
-
shouldPin: boolean;
|
|
16
|
-
action: IActionWithState<IActionState>;
|
|
11
|
+
readonly content: InputFile;
|
|
12
|
+
readonly chatInfo: ChatInfo;
|
|
13
|
+
readonly replyId: number | undefined;
|
|
14
|
+
readonly traceId: string | number;
|
|
15
|
+
readonly disableWebPreview = false;
|
|
16
|
+
readonly shouldPin: boolean;
|
|
17
|
+
readonly action: IActionWithState<IActionState>;
|
|
17
18
|
|
|
18
19
|
constructor(
|
|
19
20
|
video: InputFile,
|
|
20
|
-
|
|
21
|
+
chatInfo: ChatInfo,
|
|
21
22
|
replyId: number | undefined,
|
|
22
23
|
traceId: number | string,
|
|
23
24
|
action: IActionWithState<IActionState>,
|
|
24
25
|
options?: MessageSendingOptions
|
|
25
26
|
) {
|
|
26
27
|
this.content = video;
|
|
27
|
-
this.
|
|
28
|
+
this.chatInfo = chatInfo;
|
|
28
29
|
this.replyId = replyId;
|
|
29
30
|
this.traceId = traceId;
|
|
30
31
|
this.shouldPin = options?.pin ?? false;
|
|
@@ -6,25 +6,24 @@ import { secondsToMilliseconds } from '../../helpers/timeConvertions';
|
|
|
6
6
|
import { toArray } from '../../helpers/toArray';
|
|
7
7
|
import { IActionState } from '../../types/actionState';
|
|
8
8
|
import { IActionWithState, ActionKey } from '../../types/actionWithState';
|
|
9
|
-
import { CommandTriggerCheckResult } from '
|
|
9
|
+
import { CommandTriggerCheckResult } from '../../dtos/commandTriggerCheckResult';
|
|
10
10
|
import { MessageContext } from '../context/messageContext';
|
|
11
|
-
import { Logger } from '../../services/logger';
|
|
12
|
-
import { ActionExecutionResult } from '../actionExecutionResult';
|
|
13
11
|
import { CommandTrigger } from '../../types/commandTrigger';
|
|
12
|
+
import { Noop } from '../../helpers/noop';
|
|
14
13
|
|
|
15
14
|
export class CommandAction<TActionState extends IActionState>
|
|
16
15
|
implements IActionWithState<TActionState>
|
|
17
16
|
{
|
|
18
|
-
triggers: CommandTrigger[];
|
|
19
|
-
handler: CommandHandler<TActionState>;
|
|
20
|
-
name: string;
|
|
21
|
-
cooldownInSeconds: Seconds;
|
|
22
|
-
active: boolean;
|
|
23
|
-
chatsBlacklist: number[];
|
|
24
|
-
allowedUsers: number[];
|
|
25
|
-
condition: CommandCondition<TActionState>;
|
|
26
|
-
stateConstructor: () => TActionState;
|
|
27
|
-
key: ActionKey;
|
|
17
|
+
readonly triggers: CommandTrigger[];
|
|
18
|
+
readonly handler: CommandHandler<TActionState>;
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly cooldownInSeconds: Seconds;
|
|
21
|
+
readonly active: boolean;
|
|
22
|
+
readonly chatsBlacklist: number[];
|
|
23
|
+
readonly allowedUsers: number[];
|
|
24
|
+
readonly condition: CommandCondition<TActionState>;
|
|
25
|
+
readonly stateConstructor: () => TActionState;
|
|
26
|
+
readonly key: ActionKey;
|
|
28
27
|
|
|
29
28
|
constructor(
|
|
30
29
|
trigger: CommandTrigger | CommandTrigger[],
|
|
@@ -56,31 +55,28 @@ export class CommandAction<TActionState extends IActionState>
|
|
|
56
55
|
`Context for ${this.key} is not initialized or already consumed`
|
|
57
56
|
);
|
|
58
57
|
|
|
59
|
-
if (!this.active || this.chatsBlacklist.includes(ctx.
|
|
60
|
-
|
|
61
|
-
const isConditionMet = await this.condition(ctx);
|
|
62
|
-
|
|
63
|
-
if (!isConditionMet) return [];
|
|
58
|
+
if (!this.active || this.chatsBlacklist.includes(ctx.chatInfo.id))
|
|
59
|
+
return Noop.NoResponse;
|
|
64
60
|
|
|
65
61
|
const state = await ctx.storage.getActionState<TActionState>(
|
|
66
62
|
this,
|
|
67
|
-
ctx.
|
|
63
|
+
ctx.chatInfo.id
|
|
68
64
|
);
|
|
69
65
|
|
|
70
|
-
const {
|
|
71
|
-
.map((x) => this.
|
|
66
|
+
const { shouldExecute, matchResults, skipCooldown } = this.triggers
|
|
67
|
+
.map((x) => this.checkIfShouldBeExecuted(ctx, x, state))
|
|
72
68
|
.reduce(
|
|
73
69
|
(acc, curr) => acc.mergeWith(curr),
|
|
74
70
|
CommandTriggerCheckResult.DoNotTrigger
|
|
75
71
|
);
|
|
76
72
|
|
|
77
|
-
if (!
|
|
73
|
+
if (!shouldExecute) return Noop.NoResponse;
|
|
78
74
|
|
|
79
|
-
|
|
75
|
+
ctx.logger.logWithTraceId(
|
|
80
76
|
ctx.botName,
|
|
81
77
|
ctx.traceId,
|
|
82
|
-
ctx.
|
|
83
|
-
` - Executing [${this.name}] in ${ctx.
|
|
78
|
+
ctx.chatInfo.name,
|
|
79
|
+
` - Executing [${this.name}] in ${ctx.chatInfo.id}`
|
|
84
80
|
);
|
|
85
81
|
ctx.matchResults = matchResults;
|
|
86
82
|
|
|
@@ -94,27 +90,20 @@ export class CommandAction<TActionState extends IActionState>
|
|
|
94
90
|
state.lastExecutedDate = moment().valueOf();
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
ctx.updateActions.forEach((action) => action(state));
|
|
98
|
-
|
|
99
93
|
await ctx.storage.saveActionExecutionResult(
|
|
100
94
|
this,
|
|
101
|
-
ctx.
|
|
102
|
-
|
|
95
|
+
ctx.chatInfo.id,
|
|
96
|
+
state
|
|
103
97
|
);
|
|
104
98
|
|
|
105
|
-
ctx.isInitialized = false;
|
|
106
|
-
|
|
107
99
|
return ctx.responses;
|
|
108
100
|
}
|
|
109
101
|
|
|
110
|
-
private
|
|
102
|
+
private checkIfShouldBeExecuted(
|
|
111
103
|
ctx: MessageContext<TActionState>,
|
|
112
104
|
trigger: CommandTrigger,
|
|
113
105
|
state: IActionState
|
|
114
106
|
) {
|
|
115
|
-
let shouldTrigger = false;
|
|
116
|
-
const matchResults: RegExpExecArray[] = [];
|
|
117
|
-
|
|
118
107
|
if (!ctx.fromUserId)
|
|
119
108
|
return CommandTriggerCheckResult.DontTriggerAndSkipCooldown;
|
|
120
109
|
|
|
@@ -134,28 +123,11 @@ export class CommandAction<TActionState extends IActionState>
|
|
|
134
123
|
|
|
135
124
|
if (onCooldown) return CommandTriggerCheckResult.DoNotTrigger;
|
|
136
125
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
shouldTrigger = ctx.messageText.toLowerCase() == trigger;
|
|
141
|
-
} else {
|
|
142
|
-
trigger.lastIndex = 0;
|
|
143
|
-
|
|
144
|
-
const execResult = trigger.exec(ctx.messageText);
|
|
145
|
-
if (execResult != null) {
|
|
146
|
-
matchResults.push(execResult);
|
|
147
|
-
|
|
148
|
-
if (trigger.global) {
|
|
149
|
-
while (true) {
|
|
150
|
-
const nextResult = trigger.exec(ctx.messageText);
|
|
151
|
-
if (nextResult == null) break;
|
|
152
|
-
matchResults.push(nextResult);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
126
|
+
const isCustomConditionMet = this.condition(ctx);
|
|
127
|
+
if (!isCustomConditionMet)
|
|
128
|
+
return CommandTriggerCheckResult.DontTriggerAndSkipCooldown;
|
|
156
129
|
|
|
157
|
-
|
|
158
|
-
}
|
|
130
|
+
const { shouldTrigger, matchResults } = this.checkTrigger(ctx, trigger);
|
|
159
131
|
|
|
160
132
|
return new CommandTriggerCheckResult(
|
|
161
133
|
shouldTrigger,
|
|
@@ -163,4 +135,40 @@ export class CommandAction<TActionState extends IActionState>
|
|
|
163
135
|
false
|
|
164
136
|
);
|
|
165
137
|
}
|
|
138
|
+
|
|
139
|
+
private checkTrigger(
|
|
140
|
+
ctx: MessageContext<TActionState>,
|
|
141
|
+
trigger: CommandTrigger
|
|
142
|
+
) {
|
|
143
|
+
if (trigger == ctx.messageType)
|
|
144
|
+
return { shouldTrigger: true, matchResults: [] };
|
|
145
|
+
|
|
146
|
+
if (typeof trigger == 'string')
|
|
147
|
+
return {
|
|
148
|
+
shouldTrigger: ctx.messageText.toLowerCase() == trigger,
|
|
149
|
+
matchResults: []
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const matchResults: RegExpExecArray[] = [];
|
|
153
|
+
|
|
154
|
+
trigger.lastIndex = 0;
|
|
155
|
+
|
|
156
|
+
const execResult = trigger.exec(ctx.messageText);
|
|
157
|
+
if (execResult != null) {
|
|
158
|
+
matchResults.push(execResult);
|
|
159
|
+
|
|
160
|
+
if (trigger.global) {
|
|
161
|
+
while (true) {
|
|
162
|
+
const nextResult = trigger.exec(ctx.messageText);
|
|
163
|
+
if (nextResult == null) break;
|
|
164
|
+
matchResults.push(nextResult);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
shouldTrigger: matchResults.length > 0,
|
|
171
|
+
matchResults
|
|
172
|
+
};
|
|
173
|
+
}
|
|
166
174
|
}
|
|
@@ -7,25 +7,24 @@ import { IActionState } from '../../types/actionState';
|
|
|
7
7
|
import { IActionWithState, ActionKey } from '../../types/actionWithState';
|
|
8
8
|
import { CachedStateFactory } from '../cachedStateFactory';
|
|
9
9
|
import { ChatContext } from '../context/chatContext';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { Scheduler } from '../../services/taskScheduler';
|
|
10
|
+
import { Noop } from '../../helpers/noop';
|
|
11
|
+
import { IScheduler } from '../../types/scheduler';
|
|
13
12
|
|
|
14
13
|
export class ScheduledAction<TActionState extends IActionState>
|
|
15
14
|
implements IActionWithState<TActionState>
|
|
16
15
|
{
|
|
17
|
-
static locks = new Map<string, Semaphore>();
|
|
16
|
+
static readonly locks = new Map<string, Semaphore>();
|
|
18
17
|
|
|
19
|
-
name: string;
|
|
20
|
-
timeinHours: HoursOfDay;
|
|
21
|
-
active: boolean;
|
|
22
|
-
chatsWhitelist: number[];
|
|
23
|
-
key: ActionKey;
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly timeinHours: HoursOfDay;
|
|
20
|
+
readonly active: boolean;
|
|
21
|
+
readonly chatsWhitelist: number[];
|
|
22
|
+
readonly key: ActionKey;
|
|
24
23
|
|
|
25
|
-
cachedState = new Map<string, unknown>();
|
|
26
|
-
stateConstructor: () => TActionState;
|
|
27
|
-
cachedStateFactories: Map<string, CachedStateFactory>;
|
|
28
|
-
handler: ScheduledHandler<TActionState>;
|
|
24
|
+
readonly cachedState = new Map<string, unknown>();
|
|
25
|
+
readonly stateConstructor: () => TActionState;
|
|
26
|
+
readonly cachedStateFactories: Map<string, CachedStateFactory>;
|
|
27
|
+
readonly handler: ScheduledHandler<TActionState>;
|
|
29
28
|
|
|
30
29
|
constructor(
|
|
31
30
|
name: string,
|
|
@@ -52,48 +51,46 @@ export class ScheduledAction<TActionState extends IActionState>
|
|
|
52
51
|
`Context for ${this.key} is not initialized or already consumed`
|
|
53
52
|
);
|
|
54
53
|
|
|
55
|
-
if (!this.active || !this.chatsWhitelist.includes(ctx.
|
|
56
|
-
return
|
|
54
|
+
if (!this.active || !this.chatsWhitelist.includes(ctx.chatInfo.id))
|
|
55
|
+
return Noop.NoResponse;
|
|
57
56
|
|
|
58
57
|
const state = await ctx.storage.getActionState<TActionState>(
|
|
59
58
|
this,
|
|
60
|
-
ctx.
|
|
59
|
+
ctx.chatInfo.id
|
|
61
60
|
);
|
|
62
|
-
const isAllowedToTrigger = this.shouldTrigger(state);
|
|
63
|
-
|
|
64
|
-
if (isAllowedToTrigger) {
|
|
65
|
-
Logger.logWithTraceId(
|
|
66
|
-
ctx.botName,
|
|
67
|
-
ctx.traceId,
|
|
68
|
-
ctx.chatName,
|
|
69
|
-
` - Executing [${this.name}] in ${ctx.chatId}`
|
|
70
|
-
);
|
|
71
61
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<TResult>(key: string) =>
|
|
75
|
-
this.getCachedValue<TResult>(key, ctx.botName),
|
|
76
|
-
state
|
|
77
|
-
);
|
|
62
|
+
const isAllowedToTrigger = this.checkIfShouldBeExecuted(state);
|
|
63
|
+
if (!isAllowedToTrigger) return Noop.NoResponse;
|
|
78
64
|
|
|
79
|
-
|
|
65
|
+
ctx.logger.logWithTraceId(
|
|
66
|
+
ctx.botName,
|
|
67
|
+
ctx.traceId,
|
|
68
|
+
ctx.chatInfo.name,
|
|
69
|
+
` - Executing [${this.name}] in ${ctx.chatInfo.id}`
|
|
70
|
+
);
|
|
80
71
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
ctx.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
72
|
+
await this.handler(
|
|
73
|
+
ctx,
|
|
74
|
+
<TResult>(key: string) =>
|
|
75
|
+
this.getCachedValue<TResult>(key, ctx.botName, ctx.scheduler),
|
|
76
|
+
state
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
state.lastExecutedDate = moment().valueOf();
|
|
88
80
|
|
|
89
|
-
ctx.
|
|
81
|
+
await ctx.storage.saveActionExecutionResult(
|
|
82
|
+
this,
|
|
83
|
+
ctx.chatInfo.id,
|
|
84
|
+
state
|
|
85
|
+
);
|
|
90
86
|
|
|
91
87
|
return ctx.responses;
|
|
92
88
|
}
|
|
93
89
|
|
|
94
90
|
private async getCachedValue<TResult>(
|
|
95
91
|
key: string,
|
|
96
|
-
botName: string
|
|
92
|
+
botName: string,
|
|
93
|
+
scheduler: IScheduler
|
|
97
94
|
): Promise<TResult> {
|
|
98
95
|
if (!this.cachedStateFactories.has(key)) {
|
|
99
96
|
throw new Error(
|
|
@@ -122,7 +119,7 @@ export class ScheduledAction<TActionState extends IActionState>
|
|
|
122
119
|
|
|
123
120
|
this.cachedState.set(key, value);
|
|
124
121
|
|
|
125
|
-
|
|
122
|
+
scheduler.createOnetimeTask(
|
|
126
123
|
`Drop cached value [${this.name} : ${key}]`,
|
|
127
124
|
() => this.cachedState.delete(key),
|
|
128
125
|
hoursToMilliseconds(
|
|
@@ -137,7 +134,7 @@ export class ScheduledAction<TActionState extends IActionState>
|
|
|
137
134
|
}
|
|
138
135
|
}
|
|
139
136
|
|
|
140
|
-
private
|
|
137
|
+
private checkIfShouldBeExecuted(state: IActionState): boolean {
|
|
141
138
|
const startOfToday = moment().startOf('day').valueOf();
|
|
142
139
|
const lastExecutedDate = moment(state.lastExecutedDate);
|
|
143
140
|
const currentTime = moment();
|