chz-telegram-bot 0.5.5 → 0.6.8
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 +41 -31
- package/dist/entities/actions/commandAction.d.ts.map +1 -1
- package/dist/entities/actions/commandAction.js +11 -1
- package/dist/entities/actions/inlineQueryAction.d.ts.map +1 -1
- package/dist/entities/actions/inlineQueryAction.js +9 -1
- package/dist/entities/actions/replyCaptureAction.d.ts.map +1 -1
- package/dist/entities/actions/replyCaptureAction.js +9 -1
- package/dist/entities/actions/scheduledAction.d.ts.map +1 -1
- package/dist/entities/actions/scheduledAction.js +24 -4
- package/dist/entities/botInstance.d.ts +3 -4
- package/dist/entities/botInstance.d.ts.map +1 -1
- package/dist/entities/botInstance.js +13 -11
- package/dist/entities/context/baseContext.d.ts +4 -4
- package/dist/entities/context/baseContext.d.ts.map +1 -1
- package/dist/entities/context/baseContext.js +3 -2
- package/dist/eslint.config.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/main.d.ts +0 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -2
- package/dist/services/actionProcessingService.d.ts +4 -4
- package/dist/services/actionProcessingService.d.ts.map +1 -1
- package/dist/services/actionProcessingService.js +10 -10
- package/dist/services/actionProcessors/baseProcessor.d.ts +3 -3
- package/dist/services/actionProcessors/baseProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/baseProcessor.js +9 -5
- package/dist/services/actionProcessors/commandActionProcessor.d.ts +2 -3
- package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/commandActionProcessor.js +32 -18
- package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/inlineQueryActionProcessor.js +16 -8
- package/dist/services/actionProcessors/scheduledActionProcessor.d.ts +2 -2
- package/dist/services/actionProcessors/scheduledActionProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/scheduledActionProcessor.js +3 -4
- package/dist/services/jsonFileStorage.d.ts +3 -1
- package/dist/services/jsonFileStorage.d.ts.map +1 -1
- package/dist/services/jsonFileStorage.js +26 -2
- package/dist/services/nodeTimeoutScheduler.d.ts +3 -3
- package/dist/services/nodeTimeoutScheduler.d.ts.map +1 -1
- package/dist/services/nodeTimeoutScheduler.js +27 -8
- package/dist/services/telegramApi.d.ts +4 -4
- package/dist/services/telegramApi.d.ts.map +1 -1
- package/dist/services/telegramApi.js +39 -9
- package/dist/types/events.d.ts +193 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +69 -0
- package/dist/types/logger.d.ts +0 -12
- package/dist/types/logger.d.ts.map +1 -1
- package/dist/types/logger.js +1 -1
- package/entities/actions/commandAction.ts +11 -3
- package/entities/actions/inlineQueryAction.ts +9 -1
- package/entities/actions/replyCaptureAction.ts +9 -3
- package/entities/actions/scheduledAction.ts +31 -10
- package/entities/botInstance.ts +18 -25
- package/entities/context/baseContext.ts +9 -4
- package/index.ts +1 -1
- package/main.ts +1 -10
- package/package.json +1 -1
- package/services/actionProcessingService.ts +11 -15
- package/services/actionProcessors/baseProcessor.ts +9 -9
- package/services/actionProcessors/commandActionProcessor.ts +35 -46
- package/services/actionProcessors/inlineQueryActionProcessor.ts +24 -20
- package/services/actionProcessors/scheduledActionProcessor.ts +5 -10
- package/services/jsonFileStorage.ts +27 -1
- package/services/nodeTimeoutScheduler.ts +22 -22
- package/services/telegramApi.ts +53 -23
- package/types/events.ts +285 -0
- package/dist/services/jsonLogger.d.ts +0 -11
- package/dist/services/jsonLogger.d.ts.map +0 -1
- package/dist/services/jsonLogger.js +0 -66
- package/services/jsonLogger.ts +0 -112
- package/types/logger.ts +0 -39
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { ResponseProcessingQueue } from './responseProcessingQueue';
|
|
2
|
+
import { BotEventType } from '../types/events';
|
|
2
3
|
export const TELEGRAM_ERROR_QUOTE_INVALID = 'QUOTE_TEXT_INVALID';
|
|
3
4
|
export class TelegramApiService {
|
|
4
5
|
queue = new ResponseProcessingQueue();
|
|
5
6
|
telegram;
|
|
6
7
|
storage;
|
|
7
|
-
|
|
8
|
+
eventEmitter;
|
|
8
9
|
captureRegistrationCallback;
|
|
9
10
|
botName;
|
|
10
|
-
|
|
11
|
+
methodMap = {
|
|
12
|
+
inlineQuery: 'answerInlineQuery',
|
|
13
|
+
text: 'sendMessage',
|
|
14
|
+
react: 'setMessageReaction',
|
|
15
|
+
unpin: 'unpinChatMessage',
|
|
16
|
+
pin: 'pinChatMessage',
|
|
17
|
+
image: 'sendPhoto',
|
|
18
|
+
video: 'sendVideo',
|
|
19
|
+
delay: null
|
|
20
|
+
};
|
|
21
|
+
constructor(botName, telegram, storage, eventEmitter, captureRegistrationCallback) {
|
|
11
22
|
this.telegram = telegram;
|
|
12
23
|
this.botName = botName;
|
|
13
24
|
this.storage = storage;
|
|
14
|
-
this.
|
|
25
|
+
this.eventEmitter = eventEmitter;
|
|
15
26
|
this.captureRegistrationCallback = captureRegistrationCallback;
|
|
16
27
|
}
|
|
17
28
|
enqueueBatchedResponses(responses) {
|
|
@@ -23,9 +34,6 @@ export class TelegramApiService {
|
|
|
23
34
|
}
|
|
24
35
|
const queueItem = {
|
|
25
36
|
callback: async () => {
|
|
26
|
-
const scopedLogger = this.logger.createScope(this.botName, response.traceId, 'chatInfo' in response
|
|
27
|
-
? response.chatInfo.name
|
|
28
|
-
: 'Unknown');
|
|
29
37
|
try {
|
|
30
38
|
await this.processResponse(response);
|
|
31
39
|
}
|
|
@@ -33,17 +41,23 @@ export class TelegramApiService {
|
|
|
33
41
|
if ('message' in error) {
|
|
34
42
|
const telegramResponse = error;
|
|
35
43
|
if (telegramResponse.message.includes(TELEGRAM_ERROR_QUOTE_INVALID)) {
|
|
36
|
-
|
|
44
|
+
this.eventEmitter.emit(BotEventType.error, {
|
|
45
|
+
error: new Error('Quote error recieved, retrying without quote')
|
|
46
|
+
});
|
|
37
47
|
try {
|
|
38
48
|
await this.processResponse(response, true);
|
|
39
49
|
}
|
|
40
50
|
catch (error) {
|
|
41
|
-
|
|
51
|
+
this.eventEmitter.emit(BotEventType.error, {
|
|
52
|
+
error: error
|
|
53
|
+
});
|
|
42
54
|
}
|
|
43
55
|
return;
|
|
44
56
|
}
|
|
45
57
|
}
|
|
46
|
-
|
|
58
|
+
this.eventEmitter.emit(BotEventType.error, {
|
|
59
|
+
error: error
|
|
60
|
+
});
|
|
47
61
|
}
|
|
48
62
|
},
|
|
49
63
|
priority: response.createdAt + offset
|
|
@@ -56,7 +70,15 @@ export class TelegramApiService {
|
|
|
56
70
|
}
|
|
57
71
|
async pinIfShould(response, message) {
|
|
58
72
|
if (response.shouldPin) {
|
|
73
|
+
this.eventEmitter.emit(BotEventType.apiRequestSending, {
|
|
74
|
+
response: null,
|
|
75
|
+
telegramMethod: this.methodMap['pin']
|
|
76
|
+
});
|
|
59
77
|
await this.telegram.pinChatMessage(response.chatInfo.id, message.message_id, { disable_notification: true });
|
|
78
|
+
this.eventEmitter.emit(BotEventType.apiRequestSent, {
|
|
79
|
+
response: null,
|
|
80
|
+
telegramMethod: this.methodMap['pin']
|
|
81
|
+
});
|
|
60
82
|
await this.storage.updateStateFor(response.action, response.chatInfo.id, (state) => {
|
|
61
83
|
state.pinnedMessages.push(message.message_id);
|
|
62
84
|
});
|
|
@@ -64,6 +86,10 @@ export class TelegramApiService {
|
|
|
64
86
|
}
|
|
65
87
|
async processResponse(response, ignoreQuote = false) {
|
|
66
88
|
const sentMessage = await this.sendApiRequest(response, ignoreQuote);
|
|
89
|
+
this.eventEmitter.emit(BotEventType.apiRequestSent, {
|
|
90
|
+
response,
|
|
91
|
+
telegramMethod: this.methodMap[response.kind]
|
|
92
|
+
});
|
|
67
93
|
if (sentMessage && 'content' in response) {
|
|
68
94
|
await this.pinIfShould(response, sentMessage);
|
|
69
95
|
for (const capture of response.captures) {
|
|
@@ -72,6 +98,10 @@ export class TelegramApiService {
|
|
|
72
98
|
}
|
|
73
99
|
}
|
|
74
100
|
async sendApiRequest(response, ignoreQuote) {
|
|
101
|
+
this.eventEmitter.emit(BotEventType.apiRequestSending, {
|
|
102
|
+
response,
|
|
103
|
+
telegramMethod: this.methodMap[response.kind]
|
|
104
|
+
});
|
|
75
105
|
switch (response.kind) {
|
|
76
106
|
case 'text':
|
|
77
107
|
return await this.telegram.sendMessage(response.chatInfo.id, response.content, {
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { ChatInfo } from '../dtos/chatInfo';
|
|
2
|
+
import { IncomingMessage } from '../dtos/incomingMessage';
|
|
3
|
+
import { IncomingInlineQuery } from '../dtos/incomingQuery';
|
|
4
|
+
import { CommandAction } from '../entities/actions/commandAction';
|
|
5
|
+
import { ChatContext } from '../entities/context/chatContext';
|
|
6
|
+
import { InlineQueryContext } from '../entities/context/inlineQueryContext';
|
|
7
|
+
import { MessageContext } from '../entities/context/messageContext';
|
|
8
|
+
import { ReplyContext } from '../entities/context/replyContext';
|
|
9
|
+
import { ActionKey, IAction, IActionWithState } from './action';
|
|
10
|
+
import { IActionState } from './actionState';
|
|
11
|
+
import { BotInfo } from './externalAliases';
|
|
12
|
+
import { BotResponse } from './response';
|
|
13
|
+
import { Milliseconds } from './timeValues';
|
|
14
|
+
export declare const BotEventType: {
|
|
15
|
+
readonly error: "error.generic";
|
|
16
|
+
readonly messageRecieved: "message.recieved";
|
|
17
|
+
readonly messageProcessingStarted: "message.processingStarted";
|
|
18
|
+
readonly messageProcessingFinished: "message.processingFinished";
|
|
19
|
+
readonly beforeActionsExecuting: "message.beforeActionsExecuting";
|
|
20
|
+
readonly commandActionExecuting: "command.actionExecuting";
|
|
21
|
+
readonly commandActionExecuted: "command.actionExecuted";
|
|
22
|
+
readonly commandActionCaptureStarted: "command.captionStarted";
|
|
23
|
+
readonly commandActionCaptureAborted: "command.captionAborted";
|
|
24
|
+
readonly replyActionExecuting: "reply.actionExecuting";
|
|
25
|
+
readonly replyActionExecuted: "reply.actionExecuted";
|
|
26
|
+
readonly inlineActionExecuting: "inline.actionExecuting";
|
|
27
|
+
readonly inlineActionExecuted: "inline.actionExecuted";
|
|
28
|
+
readonly inlineProcessingStarted: "inline.processingStarted";
|
|
29
|
+
readonly inlineProcessingAborting: "inline.processingAborting";
|
|
30
|
+
readonly inlineProcessingAborted: "inline.processingAborted";
|
|
31
|
+
readonly scheduledActionExecuting: "scheduled.actionExecuting";
|
|
32
|
+
readonly scheduledActionExecuted: "scheduled.actionExecuted";
|
|
33
|
+
readonly scheduledActionCacheValueReturned: "scheduled.cachedValueReturned";
|
|
34
|
+
readonly scheduledActionCacheValueCreating: "scheduled.cachedValueCreating";
|
|
35
|
+
readonly apiRequestSending: "api.requestSending";
|
|
36
|
+
readonly apiRequestSent: "api.requestSent";
|
|
37
|
+
readonly storageLockAcquiring: "storage.lockAcquiring";
|
|
38
|
+
readonly storageLockAcquired: "storage.lockAcquired";
|
|
39
|
+
readonly storageLockReleased: "storage.lockReleased";
|
|
40
|
+
readonly storageStateSaving: "storage.stateSaving";
|
|
41
|
+
readonly storageStateSaved: "storage.stateSaved";
|
|
42
|
+
readonly storageStateLoading: "storage.stateLoading";
|
|
43
|
+
readonly storageStateLoaded: "storage.stateLoaded";
|
|
44
|
+
readonly taskCreated: "task.created";
|
|
45
|
+
readonly taskRun: "task.run";
|
|
46
|
+
readonly botStarting: "bot.starting";
|
|
47
|
+
readonly botStopping: "bot.stopping";
|
|
48
|
+
};
|
|
49
|
+
type BotEventTypeKeys = (typeof BotEventType)[keyof typeof BotEventType];
|
|
50
|
+
export type BotEventMap = {
|
|
51
|
+
[BotEventType.error]: {
|
|
52
|
+
error: Error;
|
|
53
|
+
};
|
|
54
|
+
[BotEventType.messageRecieved]: {
|
|
55
|
+
botInfo: BotInfo;
|
|
56
|
+
message: IncomingMessage;
|
|
57
|
+
};
|
|
58
|
+
[BotEventType.messageProcessingStarted]: {
|
|
59
|
+
botInfo: BotInfo;
|
|
60
|
+
message: IncomingMessage;
|
|
61
|
+
};
|
|
62
|
+
[BotEventType.messageProcessingFinished]: {
|
|
63
|
+
botInfo: BotInfo;
|
|
64
|
+
message: IncomingMessage;
|
|
65
|
+
};
|
|
66
|
+
[BotEventType.beforeActionsExecuting]: {
|
|
67
|
+
botInfo: BotInfo;
|
|
68
|
+
message: IncomingMessage;
|
|
69
|
+
commands: Set<CommandAction<IActionState>>;
|
|
70
|
+
};
|
|
71
|
+
[BotEventType.commandActionExecuting]: {
|
|
72
|
+
action: IActionWithState<IActionState>;
|
|
73
|
+
ctx: MessageContext<IActionState>;
|
|
74
|
+
state: IActionState;
|
|
75
|
+
};
|
|
76
|
+
[BotEventType.commandActionExecuted]: {
|
|
77
|
+
action: IActionWithState<IActionState>;
|
|
78
|
+
ctx: MessageContext<IActionState>;
|
|
79
|
+
state: IActionState;
|
|
80
|
+
};
|
|
81
|
+
[BotEventType.commandActionCaptureStarted]: {
|
|
82
|
+
parentMessageId: number;
|
|
83
|
+
chatInfo: ChatInfo;
|
|
84
|
+
};
|
|
85
|
+
[BotEventType.commandActionCaptureAborted]: {
|
|
86
|
+
parentMessageId: number;
|
|
87
|
+
chatInfo: ChatInfo;
|
|
88
|
+
};
|
|
89
|
+
[BotEventType.replyActionExecuting]: {
|
|
90
|
+
action: IAction;
|
|
91
|
+
ctx: ReplyContext<IActionState>;
|
|
92
|
+
};
|
|
93
|
+
[BotEventType.replyActionExecuted]: {
|
|
94
|
+
action: IAction;
|
|
95
|
+
ctx: ReplyContext<IActionState>;
|
|
96
|
+
};
|
|
97
|
+
[BotEventType.inlineActionExecuting]: {
|
|
98
|
+
action: IAction;
|
|
99
|
+
ctx: InlineQueryContext;
|
|
100
|
+
};
|
|
101
|
+
[BotEventType.inlineActionExecuted]: {
|
|
102
|
+
action: IAction;
|
|
103
|
+
ctx: InlineQueryContext;
|
|
104
|
+
};
|
|
105
|
+
[BotEventType.inlineProcessingStarted]: {
|
|
106
|
+
query: IncomingInlineQuery;
|
|
107
|
+
};
|
|
108
|
+
[BotEventType.inlineProcessingAborting]: {
|
|
109
|
+
abortedQuery: IncomingInlineQuery;
|
|
110
|
+
newQuery: IncomingInlineQuery;
|
|
111
|
+
};
|
|
112
|
+
[BotEventType.inlineProcessingAborted]: {
|
|
113
|
+
abortedQuery: IncomingInlineQuery;
|
|
114
|
+
};
|
|
115
|
+
[BotEventType.scheduledActionExecuting]: {
|
|
116
|
+
action: IAction;
|
|
117
|
+
ctx: ChatContext<IActionState>;
|
|
118
|
+
state: IActionState;
|
|
119
|
+
};
|
|
120
|
+
[BotEventType.scheduledActionExecuted]: {
|
|
121
|
+
action: IAction;
|
|
122
|
+
ctx: ChatContext<IActionState>;
|
|
123
|
+
state: IActionState;
|
|
124
|
+
};
|
|
125
|
+
[BotEventType.scheduledActionCacheValueCreating]: {
|
|
126
|
+
action: IAction;
|
|
127
|
+
ctx: ChatContext<IActionState>;
|
|
128
|
+
key: string;
|
|
129
|
+
};
|
|
130
|
+
[BotEventType.scheduledActionCacheValueReturned]: {
|
|
131
|
+
action: IAction;
|
|
132
|
+
ctx: ChatContext<IActionState>;
|
|
133
|
+
key: string;
|
|
134
|
+
};
|
|
135
|
+
[BotEventType.apiRequestSending]: {
|
|
136
|
+
response: BotResponse | null;
|
|
137
|
+
telegramMethod: string | null;
|
|
138
|
+
};
|
|
139
|
+
[BotEventType.apiRequestSent]: {
|
|
140
|
+
response: BotResponse | null;
|
|
141
|
+
telegramMethod: string | null;
|
|
142
|
+
};
|
|
143
|
+
[BotEventType.storageLockAcquiring]: ActionKey;
|
|
144
|
+
[BotEventType.storageLockAcquired]: ActionKey;
|
|
145
|
+
[BotEventType.storageLockReleased]: ActionKey;
|
|
146
|
+
[BotEventType.storageStateSaved]: {
|
|
147
|
+
key: ActionKey;
|
|
148
|
+
data: Record<number, unknown>;
|
|
149
|
+
};
|
|
150
|
+
[BotEventType.storageStateSaving]: {
|
|
151
|
+
key: ActionKey;
|
|
152
|
+
data: Record<number, unknown>;
|
|
153
|
+
};
|
|
154
|
+
[BotEventType.storageStateLoading]: {
|
|
155
|
+
action: IActionWithState<IActionState>;
|
|
156
|
+
chatId: number;
|
|
157
|
+
};
|
|
158
|
+
[BotEventType.storageStateLoaded]: {
|
|
159
|
+
action: IActionWithState<IActionState>;
|
|
160
|
+
chatId: number;
|
|
161
|
+
state: IActionState;
|
|
162
|
+
};
|
|
163
|
+
[BotEventType.taskCreated]: {
|
|
164
|
+
name: string;
|
|
165
|
+
ownerName: string;
|
|
166
|
+
delay?: Milliseconds;
|
|
167
|
+
interval?: Milliseconds;
|
|
168
|
+
};
|
|
169
|
+
[BotEventType.taskRun]: {
|
|
170
|
+
name: string;
|
|
171
|
+
ownerName: string;
|
|
172
|
+
delay?: Milliseconds;
|
|
173
|
+
interval?: Milliseconds;
|
|
174
|
+
};
|
|
175
|
+
[BotEventType.botStarting]: {
|
|
176
|
+
botName: string;
|
|
177
|
+
};
|
|
178
|
+
[BotEventType.botStopping]: {
|
|
179
|
+
botName: string;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
type ListenerArgs<K extends keyof BotEventMap> = BotEventMap[K] extends undefined ? [] : [BotEventMap[K]];
|
|
183
|
+
export type Listener<K extends keyof BotEventMap> = (timestamp: number, ...args: ListenerArgs<K>) => void;
|
|
184
|
+
export type EachListener = (event: BotEventTypeKeys, timestamp: number, data: unknown) => void;
|
|
185
|
+
export declare class TypedEventEmitter {
|
|
186
|
+
private readonly listeners;
|
|
187
|
+
on<K extends keyof BotEventMap>(event: K, fn: Listener<K>): void;
|
|
188
|
+
onEach(fn: EachListener): void;
|
|
189
|
+
emit<K extends keyof BotEventMap>(event: K, ...args: ListenerArgs<K>): void;
|
|
190
|
+
events(): (keyof BotEventMap | '*')[];
|
|
191
|
+
}
|
|
192
|
+
export {};
|
|
193
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../types/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export const BotEventType = {
|
|
2
|
+
error: 'error.generic',
|
|
3
|
+
messageRecieved: 'message.recieved',
|
|
4
|
+
messageProcessingStarted: 'message.processingStarted',
|
|
5
|
+
messageProcessingFinished: 'message.processingFinished',
|
|
6
|
+
beforeActionsExecuting: 'message.beforeActionsExecuting',
|
|
7
|
+
commandActionExecuting: 'command.actionExecuting',
|
|
8
|
+
commandActionExecuted: 'command.actionExecuted',
|
|
9
|
+
commandActionCaptureStarted: 'command.captionStarted',
|
|
10
|
+
commandActionCaptureAborted: 'command.captionAborted',
|
|
11
|
+
replyActionExecuting: 'reply.actionExecuting',
|
|
12
|
+
replyActionExecuted: 'reply.actionExecuted',
|
|
13
|
+
inlineActionExecuting: 'inline.actionExecuting',
|
|
14
|
+
inlineActionExecuted: 'inline.actionExecuted',
|
|
15
|
+
inlineProcessingStarted: 'inline.processingStarted',
|
|
16
|
+
inlineProcessingAborting: 'inline.processingAborting',
|
|
17
|
+
inlineProcessingAborted: 'inline.processingAborted',
|
|
18
|
+
scheduledActionExecuting: 'scheduled.actionExecuting',
|
|
19
|
+
scheduledActionExecuted: 'scheduled.actionExecuted',
|
|
20
|
+
scheduledActionCacheValueReturned: 'scheduled.cachedValueReturned',
|
|
21
|
+
scheduledActionCacheValueCreating: 'scheduled.cachedValueCreating',
|
|
22
|
+
apiRequestSending: 'api.requestSending',
|
|
23
|
+
apiRequestSent: 'api.requestSent',
|
|
24
|
+
storageLockAcquiring: 'storage.lockAcquiring',
|
|
25
|
+
storageLockAcquired: 'storage.lockAcquired',
|
|
26
|
+
storageLockReleased: 'storage.lockReleased',
|
|
27
|
+
storageStateSaving: 'storage.stateSaving',
|
|
28
|
+
storageStateSaved: 'storage.stateSaved',
|
|
29
|
+
storageStateLoading: 'storage.stateLoading',
|
|
30
|
+
storageStateLoaded: 'storage.stateLoaded',
|
|
31
|
+
taskCreated: 'task.created',
|
|
32
|
+
taskRun: 'task.run',
|
|
33
|
+
botStarting: 'bot.starting',
|
|
34
|
+
botStopping: 'bot.stopping'
|
|
35
|
+
};
|
|
36
|
+
// Exhaustiveness validation
|
|
37
|
+
const _checkBotEventMapExhaustive = null;
|
|
38
|
+
export class TypedEventEmitter {
|
|
39
|
+
listeners = new Map();
|
|
40
|
+
on(event, fn) {
|
|
41
|
+
const set = this.listeners.get(event) ?? new Set();
|
|
42
|
+
set.add(fn);
|
|
43
|
+
this.listeners.set(event, set);
|
|
44
|
+
}
|
|
45
|
+
onEach(fn) {
|
|
46
|
+
const event = '*';
|
|
47
|
+
const set = this.listeners.get(event) ?? new Set();
|
|
48
|
+
set.add(fn);
|
|
49
|
+
this.listeners.set(event, set);
|
|
50
|
+
}
|
|
51
|
+
emit(event, ...args) {
|
|
52
|
+
const timestamp = Date.now();
|
|
53
|
+
const specific = this.listeners.get(event);
|
|
54
|
+
if (specific) {
|
|
55
|
+
for (const fn of specific) {
|
|
56
|
+
fn(timestamp, ...args);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const anySet = this.listeners.get('*');
|
|
60
|
+
if (anySet) {
|
|
61
|
+
for (const fn of anySet) {
|
|
62
|
+
fn(event, timestamp, ...args);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
events() {
|
|
67
|
+
return [...this.listeners.keys()];
|
|
68
|
+
}
|
|
69
|
+
}
|
package/dist/types/logger.d.ts
CHANGED
|
@@ -1,13 +1 @@
|
|
|
1
|
-
import { TraceId } from './trace';
|
|
2
|
-
export interface IScopedLogger {
|
|
3
|
-
logObjectWithTraceId(data: unknown): void;
|
|
4
|
-
logWithTraceId(text: string): void;
|
|
5
|
-
errorWithTraceId(errorObj: unknown, extraData?: unknown): void;
|
|
6
|
-
}
|
|
7
|
-
export interface ILogger {
|
|
8
|
-
createScope(botName: string, traceId: TraceId, chatName: string): IScopedLogger;
|
|
9
|
-
logObjectWithTraceId(botName: string, traceId: TraceId, chatName: string, data: unknown): void;
|
|
10
|
-
logWithTraceId(botName: string, traceId: TraceId, chatName: string, text: string): void;
|
|
11
|
-
errorWithTraceId(botName: string, traceId: TraceId, chatName: string, errorObj: unknown, extraData?: unknown): void;
|
|
12
|
-
}
|
|
13
1
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../types/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../types/logger.ts"],"names":[],"mappings":""}
|
package/dist/types/logger.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
@@ -19,6 +19,7 @@ import { Seconds } from '../../types/timeValues';
|
|
|
19
19
|
import { CommandActionPropertyProvider } from '../../types/propertyProvider';
|
|
20
20
|
import { CommandActionProviders } from '../../dtos/propertyProviderSets';
|
|
21
21
|
import { BotResponse } from '../../types/response';
|
|
22
|
+
import { BotEventType } from '../../types/events';
|
|
22
23
|
|
|
23
24
|
export class CommandAction<TActionState extends IActionState>
|
|
24
25
|
implements IActionWithState<TActionState>
|
|
@@ -133,9 +134,11 @@ export class CommandAction<TActionState extends IActionState>
|
|
|
133
134
|
return Noop.NoResponse;
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
ctx.
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
ctx.eventEmitter.emit(BotEventType.commandActionExecuting, {
|
|
138
|
+
action: this,
|
|
139
|
+
ctx,
|
|
140
|
+
state
|
|
141
|
+
});
|
|
139
142
|
ctx.matchResults = matchResults;
|
|
140
143
|
|
|
141
144
|
await this.handler(ctx, state);
|
|
@@ -156,6 +159,11 @@ export class CommandAction<TActionState extends IActionState>
|
|
|
156
159
|
state
|
|
157
160
|
);
|
|
158
161
|
|
|
162
|
+
ctx.eventEmitter.emit(BotEventType.commandActionExecuted, {
|
|
163
|
+
action: this,
|
|
164
|
+
ctx,
|
|
165
|
+
state
|
|
166
|
+
});
|
|
159
167
|
return ctx.responses;
|
|
160
168
|
} finally {
|
|
161
169
|
lock?.release();
|
|
@@ -3,6 +3,7 @@ import { ActionKey, IAction } from '../../types/action';
|
|
|
3
3
|
import { InlineQueryContextInternal } from '../context/inlineQueryContext';
|
|
4
4
|
import { InlineQueryHandler } from '../../types/handlers';
|
|
5
5
|
import { InlineActionPropertyProvider } from '../../types/propertyProvider';
|
|
6
|
+
import { BotEventType } from '../../types/events';
|
|
6
7
|
|
|
7
8
|
export class InlineQueryAction implements IAction {
|
|
8
9
|
readonly key: ActionKey;
|
|
@@ -58,10 +59,17 @@ export class InlineQueryAction implements IAction {
|
|
|
58
59
|
|
|
59
60
|
ctx.matchResults = matchResults;
|
|
60
61
|
|
|
61
|
-
ctx.
|
|
62
|
+
ctx.eventEmitter.emit(BotEventType.inlineActionExecuting, {
|
|
63
|
+
action: this,
|
|
64
|
+
ctx
|
|
65
|
+
});
|
|
62
66
|
|
|
63
67
|
await this.handler(ctx);
|
|
64
68
|
|
|
69
|
+
ctx.eventEmitter.emit(BotEventType.inlineActionExecuted, {
|
|
70
|
+
action: this,
|
|
71
|
+
ctx
|
|
72
|
+
});
|
|
65
73
|
return ctx.responses;
|
|
66
74
|
}
|
|
67
75
|
}
|
|
@@ -4,6 +4,7 @@ import { IActionState } from '../../types/actionState';
|
|
|
4
4
|
import { CommandTrigger } from '../../types/commandTrigger';
|
|
5
5
|
import { ActionKey, IAction } from '../../types/action';
|
|
6
6
|
import { ReplyContextInternal } from '../context/replyContext';
|
|
7
|
+
import { BotEventType } from '../../types/events';
|
|
7
8
|
|
|
8
9
|
export class ReplyCaptureAction<TParentActionState extends IActionState>
|
|
9
10
|
implements IAction
|
|
@@ -50,13 +51,18 @@ export class ReplyCaptureAction<TParentActionState extends IActionState>
|
|
|
50
51
|
|
|
51
52
|
if (!shouldExecute) return Noop.NoResponse;
|
|
52
53
|
|
|
53
|
-
ctx.
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
ctx.eventEmitter.emit(BotEventType.replyActionExecuting, {
|
|
55
|
+
action: this,
|
|
56
|
+
ctx
|
|
57
|
+
});
|
|
56
58
|
ctx.matchResults = matchResults;
|
|
57
59
|
|
|
58
60
|
await this.handler(ctx);
|
|
59
61
|
|
|
62
|
+
ctx.eventEmitter.emit(BotEventType.replyActionExecuted, {
|
|
63
|
+
action: this,
|
|
64
|
+
ctx
|
|
65
|
+
});
|
|
60
66
|
return ctx.responses;
|
|
61
67
|
}
|
|
62
68
|
|
|
@@ -8,10 +8,10 @@ import { IActionWithState, ActionKey } from '../../types/action';
|
|
|
8
8
|
import { CachedStateFactory } from '../cachedStateFactory';
|
|
9
9
|
import { ChatContextInternal } from '../context/chatContext';
|
|
10
10
|
import { Noop } from '../../helpers/noop';
|
|
11
|
-
import { IScheduler } from '../../types/scheduler';
|
|
12
11
|
import { getOrSetIfNotExists, getOrThrow } from '../../helpers/mapUtils';
|
|
13
12
|
import { ScheduledActionPropertyProvider } from '../../types/propertyProvider';
|
|
14
13
|
import { ScheduledActionProviders } from '../../dtos/propertyProviderSets';
|
|
14
|
+
import { BotEventType } from '../../types/events';
|
|
15
15
|
|
|
16
16
|
export class ScheduledAction<TActionState extends IActionState>
|
|
17
17
|
implements IActionWithState<TActionState>
|
|
@@ -71,14 +71,15 @@ export class ScheduledAction<TActionState extends IActionState>
|
|
|
71
71
|
const isAllowedToTrigger = this.checkIfShouldBeExecuted(state, ctx);
|
|
72
72
|
if (!isAllowedToTrigger) return Noop.NoResponse;
|
|
73
73
|
|
|
74
|
-
ctx.
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
ctx.eventEmitter.emit(BotEventType.scheduledActionExecuting, {
|
|
75
|
+
action: this,
|
|
76
|
+
ctx,
|
|
77
|
+
state
|
|
78
|
+
});
|
|
77
79
|
|
|
78
80
|
await this.handler(
|
|
79
81
|
ctx,
|
|
80
|
-
<TResult>(key: string) =>
|
|
81
|
-
this.getCachedValue<TResult>(key, ctx.botName, ctx.scheduler),
|
|
82
|
+
<TResult>(key: string) => this.getCachedValue<TResult>(key, ctx),
|
|
82
83
|
state
|
|
83
84
|
);
|
|
84
85
|
|
|
@@ -90,13 +91,17 @@ export class ScheduledAction<TActionState extends IActionState>
|
|
|
90
91
|
state
|
|
91
92
|
);
|
|
92
93
|
|
|
94
|
+
ctx.eventEmitter.emit(BotEventType.scheduledActionExecuted, {
|
|
95
|
+
action: this,
|
|
96
|
+
ctx,
|
|
97
|
+
state
|
|
98
|
+
});
|
|
93
99
|
return ctx.responses;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
private async getCachedValue<TResult>(
|
|
97
103
|
key: string,
|
|
98
|
-
|
|
99
|
-
scheduler: IScheduler
|
|
104
|
+
ctx: ChatContextInternal<TActionState>
|
|
100
105
|
): Promise<TResult> {
|
|
101
106
|
const cachedItemFactory = getOrThrow(
|
|
102
107
|
this.cachedStateFactories,
|
|
@@ -118,21 +123,37 @@ export class ScheduledAction<TActionState extends IActionState>
|
|
|
118
123
|
return this.cachedState.get(key) as TResult;
|
|
119
124
|
}
|
|
120
125
|
|
|
126
|
+
ctx.eventEmitter.emit(
|
|
127
|
+
BotEventType.scheduledActionCacheValueCreating,
|
|
128
|
+
{
|
|
129
|
+
action: this,
|
|
130
|
+
ctx,
|
|
131
|
+
key
|
|
132
|
+
}
|
|
133
|
+
);
|
|
121
134
|
const value = await cachedItemFactory.getValue();
|
|
122
135
|
|
|
123
136
|
this.cachedState.set(key, value);
|
|
124
137
|
|
|
125
|
-
scheduler.createOnetimeTask(
|
|
138
|
+
ctx.scheduler.createOnetimeTask(
|
|
126
139
|
`Drop cached value [${this.name} : ${key}]`,
|
|
127
140
|
() => this.cachedState.delete(key),
|
|
128
141
|
hoursToMilliseconds(
|
|
129
142
|
cachedItemFactory.invalidationTimeoutInHours
|
|
130
143
|
),
|
|
131
|
-
botName
|
|
144
|
+
ctx.botName
|
|
132
145
|
);
|
|
133
146
|
|
|
134
147
|
return value as TResult;
|
|
135
148
|
} finally {
|
|
149
|
+
ctx.eventEmitter.emit(
|
|
150
|
+
BotEventType.scheduledActionCacheValueReturned,
|
|
151
|
+
{
|
|
152
|
+
action: this,
|
|
153
|
+
ctx,
|
|
154
|
+
key
|
|
155
|
+
}
|
|
156
|
+
);
|
|
136
157
|
semaphore.release();
|
|
137
158
|
}
|
|
138
159
|
}
|