chz-telegram-bot 0.5.4 → 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.
Files changed (234) hide show
  1. package/README.md +41 -31
  2. package/dist/builtin/helpAction.d.ts +2 -0
  3. package/dist/builtin/helpAction.d.ts.map +1 -0
  4. package/dist/builtin/helpAction.js +14 -0
  5. package/dist/dtos/chatHistoryMessage.d.ts +35 -0
  6. package/dist/dtos/chatHistoryMessage.d.ts.map +1 -0
  7. package/dist/dtos/chatHistoryMessage.js +32 -0
  8. package/dist/dtos/chatInfo.d.ts +17 -0
  9. package/dist/dtos/chatInfo.d.ts.map +1 -0
  10. package/dist/dtos/chatInfo.js +16 -0
  11. package/dist/dtos/commandTriggerCheckResult.d.ts +24 -0
  12. package/dist/dtos/commandTriggerCheckResult.d.ts.map +1 -0
  13. package/dist/dtos/commandTriggerCheckResult.js +34 -0
  14. package/dist/dtos/cooldownInfo.d.ts +13 -0
  15. package/dist/dtos/cooldownInfo.d.ts.map +1 -0
  16. package/dist/dtos/cooldownInfo.js +12 -0
  17. package/dist/dtos/incomingMessage.d.ts +19 -0
  18. package/dist/dtos/incomingMessage.d.ts.map +1 -0
  19. package/dist/dtos/incomingMessage.js +63 -0
  20. package/dist/dtos/incomingQuery.d.ts +10 -0
  21. package/dist/dtos/incomingQuery.d.ts.map +1 -0
  22. package/dist/dtos/incomingQuery.js +14 -0
  23. package/dist/dtos/messageInfo.d.ts +22 -0
  24. package/dist/dtos/messageInfo.d.ts.map +1 -0
  25. package/dist/dtos/messageInfo.js +20 -0
  26. package/dist/dtos/propertyProviderSets.d.ts +16 -0
  27. package/dist/dtos/propertyProviderSets.d.ts.map +1 -0
  28. package/dist/dtos/propertyProviderSets.js +1 -0
  29. package/dist/dtos/replyInfo.d.ts +6 -0
  30. package/dist/dtos/replyInfo.d.ts.map +1 -0
  31. package/dist/dtos/replyInfo.js +8 -0
  32. package/dist/dtos/responses/delay.d.ts +16 -0
  33. package/dist/dtos/responses/delay.d.ts.map +1 -0
  34. package/dist/dtos/responses/delay.js +15 -0
  35. package/dist/dtos/responses/imageMessage.d.ts +22 -0
  36. package/dist/dtos/responses/imageMessage.d.ts.map +1 -0
  37. package/dist/dtos/responses/imageMessage.js +21 -0
  38. package/dist/dtos/responses/inlineQueryResponse.d.ts +13 -0
  39. package/dist/dtos/responses/inlineQueryResponse.d.ts.map +1 -0
  40. package/dist/dtos/responses/inlineQueryResponse.js +15 -0
  41. package/dist/dtos/responses/reaction.d.ts +16 -0
  42. package/dist/dtos/responses/reaction.d.ts.map +1 -0
  43. package/dist/dtos/responses/reaction.js +17 -0
  44. package/dist/dtos/responses/textMessage.d.ts +23 -0
  45. package/dist/dtos/responses/textMessage.d.ts.map +1 -0
  46. package/dist/dtos/responses/textMessage.js +24 -0
  47. package/dist/dtos/responses/unpin.d.ts +15 -0
  48. package/dist/dtos/responses/unpin.d.ts.map +1 -0
  49. package/dist/dtos/responses/unpin.js +15 -0
  50. package/dist/dtos/responses/videoMessage.d.ts +22 -0
  51. package/dist/dtos/responses/videoMessage.d.ts.map +1 -0
  52. package/dist/dtos/responses/videoMessage.js +21 -0
  53. package/dist/dtos/userInfo.d.ts +12 -0
  54. package/dist/dtos/userInfo.d.ts.map +1 -0
  55. package/dist/dtos/userInfo.js +12 -0
  56. package/dist/entities/actions/commandAction.d.ts +31 -0
  57. package/dist/entities/actions/commandAction.d.ts.map +1 -0
  58. package/dist/entities/actions/commandAction.js +149 -0
  59. package/dist/entities/actions/inlineQueryAction.d.ts +14 -0
  60. package/dist/entities/actions/inlineQueryAction.d.ts.map +1 -0
  61. package/dist/entities/actions/inlineQueryAction.js +51 -0
  62. package/dist/entities/actions/replyCaptureAction.d.ts +15 -0
  63. package/dist/entities/actions/replyCaptureAction.d.ts.map +1 -0
  64. package/dist/entities/actions/replyCaptureAction.js +66 -0
  65. package/dist/entities/actions/scheduledAction.d.ts +24 -0
  66. package/dist/entities/actions/scheduledAction.d.ts.map +1 -0
  67. package/dist/entities/actions/scheduledAction.js +92 -0
  68. package/dist/entities/botInstance.d.ts +36 -0
  69. package/dist/entities/botInstance.d.ts.map +1 -0
  70. package/dist/entities/botInstance.js +39 -0
  71. package/dist/entities/cachedStateFactory.d.ts +7 -0
  72. package/dist/entities/cachedStateFactory.d.ts.map +1 -0
  73. package/dist/entities/cachedStateFactory.js +8 -0
  74. package/dist/entities/context/baseContext.d.ts +39 -0
  75. package/dist/entities/context/baseContext.d.ts.map +1 -0
  76. package/dist/entities/context/baseContext.js +56 -0
  77. package/dist/entities/context/chatContext.d.ts +50 -0
  78. package/dist/entities/context/chatContext.d.ts.map +1 -0
  79. package/dist/entities/context/chatContext.js +65 -0
  80. package/dist/entities/context/inlineQueryContext.d.ts +27 -0
  81. package/dist/entities/context/inlineQueryContext.d.ts.map +1 -0
  82. package/dist/entities/context/inlineQueryContext.js +29 -0
  83. package/dist/entities/context/messageContext.d.ts +92 -0
  84. package/dist/entities/context/messageContext.d.ts.map +1 -0
  85. package/dist/entities/context/messageContext.js +116 -0
  86. package/dist/entities/context/replyContext.d.ts +89 -0
  87. package/dist/entities/context/replyContext.d.ts.map +1 -0
  88. package/dist/entities/context/replyContext.js +124 -0
  89. package/dist/entities/states/actionStateBase.d.ts +6 -0
  90. package/dist/entities/states/actionStateBase.d.ts.map +1 -0
  91. package/dist/entities/states/actionStateBase.js +4 -0
  92. package/dist/entities/taskRecord.d.ts +8 -0
  93. package/dist/entities/taskRecord.d.ts.map +1 -0
  94. package/dist/entities/taskRecord.js +10 -0
  95. package/dist/eslint.config.d.ts +3 -0
  96. package/dist/eslint.config.d.ts.map +1 -0
  97. package/dist/eslint.config.js +51 -0
  98. package/dist/helpers/builders/commandActionBuilder.d.ts +100 -0
  99. package/dist/helpers/builders/commandActionBuilder.d.ts.map +1 -0
  100. package/dist/helpers/builders/commandActionBuilder.js +146 -0
  101. package/dist/helpers/builders/inlineQueryActionBuilder.d.ts +37 -0
  102. package/dist/helpers/builders/inlineQueryActionBuilder.d.ts.map +1 -0
  103. package/dist/helpers/builders/inlineQueryActionBuilder.js +50 -0
  104. package/dist/helpers/builders/scheduledActionBuilder.d.ts +68 -0
  105. package/dist/helpers/builders/scheduledActionBuilder.d.ts.map +1 -0
  106. package/dist/helpers/builders/scheduledActionBuilder.js +95 -0
  107. package/dist/helpers/mapUtils.d.ts +10 -0
  108. package/dist/helpers/mapUtils.d.ts.map +1 -0
  109. package/dist/helpers/mapUtils.js +13 -0
  110. package/dist/helpers/noop.d.ts +9 -0
  111. package/dist/helpers/noop.d.ts.map +1 -0
  112. package/dist/helpers/noop.js +17 -0
  113. package/dist/helpers/objectFromEntries.d.ts +2 -0
  114. package/dist/helpers/objectFromEntries.d.ts.map +1 -0
  115. package/dist/helpers/objectFromEntries.js +3 -0
  116. package/dist/helpers/timeConvertions.d.ts +5 -0
  117. package/dist/helpers/timeConvertions.d.ts.map +1 -0
  118. package/dist/helpers/timeConvertions.js +9 -0
  119. package/dist/helpers/toArray.d.ts +2 -0
  120. package/dist/helpers/toArray.d.ts.map +1 -0
  121. package/dist/helpers/toArray.js +3 -0
  122. package/dist/helpers/traceFactory.d.ts +3 -0
  123. package/dist/helpers/traceFactory.d.ts.map +1 -0
  124. package/dist/helpers/traceFactory.js +3 -0
  125. package/dist/index.d.ts +27 -0
  126. package/dist/index.d.ts.map +1 -0
  127. package/dist/index.js +20 -0
  128. package/dist/main.d.ts +49 -0
  129. package/dist/main.d.ts.map +1 -0
  130. package/dist/main.js +33 -0
  131. package/dist/services/actionProcessingService.d.ts +25 -0
  132. package/dist/services/actionProcessingService.d.ts.map +1 -0
  133. package/dist/services/actionProcessingService.js +50 -0
  134. package/dist/services/actionProcessors/baseProcessor.d.ts +18 -0
  135. package/dist/services/actionProcessors/baseProcessor.d.ts.map +1 -0
  136. package/dist/services/actionProcessors/baseProcessor.js +33 -0
  137. package/dist/services/actionProcessors/commandActionProcessor.d.ts +19 -0
  138. package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -0
  139. package/dist/services/actionProcessors/commandActionProcessor.js +130 -0
  140. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts +11 -0
  141. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -0
  142. package/dist/services/actionProcessors/inlineQueryActionProcessor.js +69 -0
  143. package/dist/services/actionProcessors/scheduledActionProcessor.d.ts +17 -0
  144. package/dist/services/actionProcessors/scheduledActionProcessor.d.ts.map +1 -0
  145. package/dist/services/actionProcessors/scheduledActionProcessor.js +55 -0
  146. package/dist/services/jsonFileStorage.d.ts +25 -0
  147. package/dist/services/jsonFileStorage.d.ts.map +1 -0
  148. package/dist/services/jsonFileStorage.js +133 -0
  149. package/dist/services/nodeTimeoutScheduler.d.ts +13 -0
  150. package/dist/services/nodeTimeoutScheduler.d.ts.map +1 -0
  151. package/dist/services/nodeTimeoutScheduler.js +50 -0
  152. package/dist/services/responseProcessingQueue.d.ts +12 -0
  153. package/dist/services/responseProcessingQueue.d.ts.map +1 -0
  154. package/dist/services/responseProcessingQueue.js +37 -0
  155. package/dist/services/telegramApi.d.ts +23 -0
  156. package/dist/services/telegramApi.d.ts.map +1 -0
  157. package/dist/services/telegramApi.js +163 -0
  158. package/dist/types/action.d.ts +14 -0
  159. package/dist/types/action.d.ts.map +1 -0
  160. package/dist/types/action.js +1 -0
  161. package/dist/types/actionState.d.ts +5 -0
  162. package/dist/types/actionState.d.ts.map +1 -0
  163. package/dist/types/actionState.js +1 -0
  164. package/dist/types/cachedValueAccessor.d.ts +2 -0
  165. package/dist/types/cachedValueAccessor.d.ts.map +1 -0
  166. package/dist/types/cachedValueAccessor.js +1 -0
  167. package/dist/types/capture.d.ts +24 -0
  168. package/dist/types/capture.d.ts.map +1 -0
  169. package/dist/types/capture.js +1 -0
  170. package/dist/types/commandCondition.d.ts +8 -0
  171. package/dist/types/commandCondition.d.ts.map +1 -0
  172. package/dist/types/commandCondition.js +1 -0
  173. package/dist/types/commandTrigger.d.ts +2 -0
  174. package/dist/types/commandTrigger.d.ts.map +1 -0
  175. package/dist/types/commandTrigger.js +1 -0
  176. package/dist/types/events.d.ts +193 -0
  177. package/dist/types/events.d.ts.map +1 -0
  178. package/dist/types/events.js +69 -0
  179. package/dist/types/externalAliases.d.ts +11 -0
  180. package/dist/types/externalAliases.d.ts.map +1 -0
  181. package/dist/types/externalAliases.js +1 -0
  182. package/dist/types/handlers.d.ts +21 -0
  183. package/dist/types/handlers.d.ts.map +1 -0
  184. package/dist/types/handlers.js +1 -0
  185. package/dist/types/inputFile.d.ts +5 -0
  186. package/dist/types/inputFile.d.ts.map +1 -0
  187. package/dist/types/inputFile.js +1 -0
  188. package/dist/types/logger.d.ts +1 -0
  189. package/dist/types/logger.d.ts.map +1 -0
  190. package/dist/types/logger.js +1 -0
  191. package/dist/types/messageSendingOptions.d.ts +9 -0
  192. package/dist/types/messageSendingOptions.d.ts.map +1 -0
  193. package/dist/types/messageSendingOptions.js +1 -0
  194. package/dist/types/messageTypes.d.ts +20 -0
  195. package/dist/types/messageTypes.d.ts.map +1 -0
  196. package/dist/types/messageTypes.js +18 -0
  197. package/dist/types/propertyProvider.d.ts +8 -0
  198. package/dist/types/propertyProvider.d.ts.map +1 -0
  199. package/dist/types/propertyProvider.js +1 -0
  200. package/dist/types/response.d.ts +39 -0
  201. package/dist/types/response.d.ts.map +1 -0
  202. package/dist/types/response.js +9 -0
  203. package/dist/types/scheduler.d.ts +7 -0
  204. package/dist/types/scheduler.d.ts.map +1 -0
  205. package/dist/types/scheduler.js +1 -0
  206. package/dist/types/storage.d.ts +11 -0
  207. package/dist/types/storage.d.ts.map +1 -0
  208. package/dist/types/storage.js +1 -0
  209. package/dist/types/timeValues.d.ts +15 -0
  210. package/dist/types/timeValues.d.ts.map +1 -0
  211. package/dist/types/timeValues.js +1 -0
  212. package/dist/types/trace.d.ts +6 -0
  213. package/dist/types/trace.d.ts.map +1 -0
  214. package/dist/types/trace.js +1 -0
  215. package/entities/actions/commandAction.ts +11 -3
  216. package/entities/actions/inlineQueryAction.ts +9 -1
  217. package/entities/actions/replyCaptureAction.ts +9 -3
  218. package/entities/actions/scheduledAction.ts +31 -10
  219. package/entities/botInstance.ts +18 -25
  220. package/entities/context/baseContext.ts +9 -4
  221. package/index.ts +1 -1
  222. package/main.ts +1 -10
  223. package/package.json +38 -38
  224. package/services/actionProcessingService.ts +11 -15
  225. package/services/actionProcessors/baseProcessor.ts +9 -9
  226. package/services/actionProcessors/commandActionProcessor.ts +35 -46
  227. package/services/actionProcessors/inlineQueryActionProcessor.ts +24 -20
  228. package/services/actionProcessors/scheduledActionProcessor.ts +5 -10
  229. package/services/jsonFileStorage.ts +27 -1
  230. package/services/nodeTimeoutScheduler.ts +22 -22
  231. package/services/telegramApi.ts +53 -23
  232. package/types/events.ts +285 -0
  233. package/services/jsonLogger.ts +0 -112
  234. package/types/logger.ts +0 -39
@@ -6,7 +6,6 @@ import { ReplyContextInternal } from '../../entities/context/replyContext';
6
6
  import { IActionState } from '../../types/actionState';
7
7
  import { TelegramApiService } from '../telegramApi';
8
8
  import { IReplyCapture } from '../../types/capture';
9
- import { TraceId } from '../../types/trace';
10
9
  import { ChatInfo } from '../../dtos/chatInfo';
11
10
  import {
12
11
  INTERNAL_MESSAGE_TYPE_PREFIX,
@@ -19,6 +18,7 @@ import { MessageInfo } from '../../dtos/messageInfo';
19
18
  import { UserInfo } from '../../dtos/userInfo';
20
19
  import { ChatHistoryMessage } from '../../dtos/chatHistoryMessage';
21
20
  import { BotInfo, TelegramBot } from '../../types/externalAliases';
21
+ import { BotEventType } from '../../types/events';
22
22
 
23
23
  const MESSAGE_HISTORY_LENGTH_LIMIT = 100;
24
24
 
@@ -38,7 +38,6 @@ export class CommandActionProcessor extends BaseActionProcessor {
38
38
  api: TelegramApiService,
39
39
  telegram: TelegramBot,
40
40
  commands: CommandAction<IActionState>[],
41
- verboseLoggingForIncomingMessage: boolean,
42
41
  botInfo: BotInfo
43
42
  ) {
44
43
  this.botInfo = botInfo;
@@ -69,30 +68,24 @@ export class CommandActionProcessor extends BaseActionProcessor {
69
68
  }
70
69
 
71
70
  if (commands.length > 0) {
72
- telegram.on('message', ({ message }) => {
71
+ telegram.on('message', async ({ message }) => {
73
72
  const internalMessage = new IncomingMessage(
74
73
  message,
75
74
  this.botName,
76
75
  getOrSetIfNotExists(this.chatHistory, message.chat.id, [])
77
76
  );
78
77
 
79
- const logger = this.logger.createScope(
80
- this.botName,
81
- internalMessage.traceId,
82
- internalMessage.chatInfo.name
83
- );
78
+ this.eventEmitter.emit(BotEventType.messageRecieved, {
79
+ botInfo: this.botInfo,
80
+ message: internalMessage
81
+ });
84
82
 
85
- if (verboseLoggingForIncomingMessage) {
86
- logger.logObjectWithTraceId(message);
87
- } else {
88
- logger.logWithTraceId(
89
- `${internalMessage.from?.first_name ?? 'Unknown'} (${
90
- internalMessage.from?.id ?? 'Unknown'
91
- }): ${internalMessage.text || internalMessage.type}`
92
- );
93
- }
83
+ await this.processMessage(internalMessage);
94
84
 
95
- void this.processMessage(internalMessage);
85
+ this.eventEmitter.emit(BotEventType.messageProcessingFinished, {
86
+ botInfo: this.botInfo,
87
+ message: internalMessage
88
+ });
96
89
  });
97
90
  }
98
91
  }
@@ -100,8 +93,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
100
93
  captureRegistrationCallback(
101
94
  capture: IReplyCapture,
102
95
  parentMessageId: number,
103
- chatInfo: ChatInfo,
104
- traceId: TraceId
96
+ chatInfo: ChatInfo
105
97
  ) {
106
98
  const replyAction = new ReplyCaptureAction(
107
99
  parentMessageId,
@@ -111,15 +103,10 @@ export class CommandActionProcessor extends BaseActionProcessor {
111
103
  capture.abortController
112
104
  );
113
105
 
114
- const logger = this.logger.createScope(
115
- this.botName,
116
- traceId,
117
- chatInfo.name
118
- );
119
-
120
- logger.logWithTraceId(
121
- `Starting capturing replies to message ${parentMessageId} with action ${replyAction.key}`
122
- );
106
+ this.eventEmitter.emit(BotEventType.commandActionCaptureStarted, {
107
+ parentMessageId,
108
+ chatInfo
109
+ });
123
110
 
124
111
  this.replyCaptures.push(replyAction);
125
112
 
@@ -127,13 +114,19 @@ export class CommandActionProcessor extends BaseActionProcessor {
127
114
  const index = this.replyCaptures.indexOf(replyAction);
128
115
  this.replyCaptures.splice(index, 1);
129
116
 
130
- logger.logWithTraceId(
131
- `Stopping capturing replies to message ${parentMessageId} with action ${replyAction.key}`
132
- );
117
+ this.eventEmitter.emit(BotEventType.commandActionCaptureAborted, {
118
+ parentMessageId,
119
+ chatInfo
120
+ });
133
121
  });
134
122
  }
135
123
 
136
124
  private async processMessage(msg: IncomingMessage) {
125
+ this.eventEmitter.emit(BotEventType.messageProcessingStarted, {
126
+ botInfo: this.botInfo,
127
+ message: msg
128
+ });
129
+
137
130
  const chatHistoryArray = getOrSetIfNotExists(
138
131
  this.chatHistory,
139
132
  msg.chatInfo.id,
@@ -142,6 +135,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
142
135
 
143
136
  while (chatHistoryArray.length > MESSAGE_HISTORY_LENGTH_LIMIT)
144
137
  chatHistoryArray.shift();
138
+
145
139
  chatHistoryArray.push(
146
140
  new ChatHistoryMessage(
147
141
  msg.messageId,
@@ -156,7 +150,8 @@ export class CommandActionProcessor extends BaseActionProcessor {
156
150
 
157
151
  const ctx = new MessageContextInternal<IActionState>(
158
152
  this.storage,
159
- this.scheduler
153
+ this.scheduler,
154
+ this.eventEmitter
160
155
  );
161
156
 
162
157
  const commandsToCheck = new Set(this.commands[msg.type]);
@@ -166,6 +161,11 @@ export class CommandActionProcessor extends BaseActionProcessor {
166
161
  }
167
162
  }
168
163
 
164
+ this.eventEmitter.emit(BotEventType.beforeActionsExecuting, {
165
+ botInfo: this.botInfo,
166
+ message: msg,
167
+ commands: commandsToCheck
168
+ });
169
169
  for (const commandAction of commandsToCheck) {
170
170
  this.initializeMessageContext(ctx, commandAction, msg);
171
171
  await this.executeAction(commandAction, ctx);
@@ -174,7 +174,8 @@ export class CommandActionProcessor extends BaseActionProcessor {
174
174
  if (this.replyCaptures.length != 0) {
175
175
  const replyCtx = new ReplyContextInternal<IActionState>(
176
176
  this.storage,
177
- this.scheduler
177
+ this.scheduler,
178
+ this.eventEmitter
178
179
  );
179
180
 
180
181
  for (const replyAction of this.replyCaptures) {
@@ -211,12 +212,6 @@ export class CommandActionProcessor extends BaseActionProcessor {
211
212
 
212
213
  ctx.isInitialized = true;
213
214
  ctx.matchResults = [];
214
-
215
- ctx.logger = this.logger.createScope(
216
- this.botName,
217
- message.traceId,
218
- message.chatInfo.name
219
- );
220
215
  }
221
216
 
222
217
  private initializeMessageContext(
@@ -247,11 +242,5 @@ export class CommandActionProcessor extends BaseActionProcessor {
247
242
  ctx.traceId = message.traceId;
248
243
  ctx.botInfo = this.botInfo;
249
244
  ctx.customCooldown = undefined;
250
-
251
- ctx.logger = this.logger.createScope(
252
- this.botName,
253
- message.traceId,
254
- message.chatInfo.name
255
- );
256
245
  }
257
246
  }
@@ -2,6 +2,7 @@ import { IncomingInlineQuery } from '../../dtos/incomingQuery';
2
2
  import { InlineQueryAction } from '../../entities/actions/inlineQueryAction';
3
3
  import { InlineQueryContextInternal } from '../../entities/context/inlineQueryContext';
4
4
  import { createTrace } from '../../helpers/traceFactory';
5
+ import { BotEventType } from '../../types/events';
5
6
  import { TelegramBot } from '../../types/externalAliases';
6
7
  import { Milliseconds } from '../../types/timeValues';
7
8
  import { TraceId } from '../../types/trace';
@@ -33,24 +34,20 @@ export class InlineQueryActionProcessor extends BaseActionProcessor {
33
34
  createTrace('InlineQuery', this.botName, inlineQuery.id)
34
35
  );
35
36
 
36
- const logger = this.logger.createScope(
37
- this.botName,
38
- query.traceId,
39
- 'Query'
40
- );
41
-
42
- logger.logWithTraceId(
43
- `${inlineQuery.from.username ?? 'Unknown'} (${
44
- inlineQuery.from.id
45
- }): Query for ${inlineQuery.query}`
46
- );
37
+ this.eventEmitter.emit(BotEventType.inlineProcessingStarted, {
38
+ query
39
+ });
47
40
 
48
41
  const queryBeingProcessed = queriesInProcessing.get(
49
42
  query.userId
50
43
  );
51
44
  if (queryBeingProcessed) {
52
- logger.logWithTraceId(
53
- `Aborting query ${queryBeingProcessed.queryId} (${queryBeingProcessed.query}): new query recieved from ${query.userId}`
45
+ this.eventEmitter.emit(
46
+ BotEventType.inlineProcessingAborting,
47
+ {
48
+ newQuery: query,
49
+ abortedQuery: queryBeingProcessed
50
+ }
54
51
  );
55
52
 
56
53
  queryBeingProcessed.abortController.abort();
@@ -69,7 +66,8 @@ export class InlineQueryActionProcessor extends BaseActionProcessor {
69
66
  async () => {
70
67
  const ctx = new InlineQueryContextInternal(
71
68
  this.storage,
72
- this.scheduler
69
+ this.scheduler,
70
+ this.eventEmitter
73
71
  );
74
72
 
75
73
  const queriesToProcess = [...pendingInlineQueries];
@@ -94,13 +92,21 @@ export class InlineQueryActionProcessor extends BaseActionProcessor {
94
92
  await this.executeAction(
95
93
  inlineQueryAction,
96
94
  ctx,
97
- (error, ctx) => {
95
+ (error, _) => {
98
96
  if (error.name == 'AbortError') {
99
- ctx.logger.logWithTraceId(
100
- `Aborting query ${inlineQuery.queryId} (${inlineQuery.query}) successful.`
97
+ this.eventEmitter.emit(
98
+ BotEventType.inlineProcessingAborted,
99
+ {
100
+ abortedQuery: inlineQuery
101
+ }
101
102
  );
102
103
  } else {
103
- ctx.logger.errorWithTraceId(error, ctx);
104
+ this.eventEmitter.emit(
105
+ BotEventType.error,
106
+ {
107
+ error
108
+ }
109
+ );
104
110
  }
105
111
  }
106
112
  );
@@ -136,7 +142,5 @@ export class InlineQueryActionProcessor extends BaseActionProcessor {
136
142
  ctx.isInitialized = true;
137
143
  ctx.queryResults = [];
138
144
  ctx.matchResults = [];
139
-
140
- ctx.logger = this.logger.createScope(this.botName, traceId, 'Unknown');
141
145
  }
142
146
  }
@@ -5,13 +5,13 @@ import { ChatContextInternal } from '../../entities/context/chatContext';
5
5
  import { secondsToMilliseconds } from '../../helpers/timeConvertions';
6
6
  import { createTrace } from '../../helpers/traceFactory';
7
7
  import { IActionState } from '../../types/actionState';
8
- import { ILogger } from '../../types/logger';
9
8
  import { IScheduler } from '../../types/scheduler';
10
9
  import { IStorageClient } from '../../types/storage';
11
10
  import { Seconds, Milliseconds } from '../../types/timeValues';
12
11
  import { TraceId } from '../../types/trace';
13
12
  import { TelegramApiService } from '../telegramApi';
14
13
  import { BaseActionProcessor } from './baseProcessor';
14
+ import { TypedEventEmitter } from '../../types/events';
15
15
 
16
16
  export class ScheduledActionProcessor extends BaseActionProcessor {
17
17
  private readonly chats: Record<string, number>;
@@ -23,9 +23,9 @@ export class ScheduledActionProcessor extends BaseActionProcessor {
23
23
  chats: Record<string, number>,
24
24
  storage: IStorageClient,
25
25
  scheduler: IScheduler,
26
- logger: ILogger
26
+ eventEmitter: TypedEventEmitter
27
27
  ) {
28
- super(botName, storage, scheduler, logger);
28
+ super(botName, storage, scheduler, eventEmitter);
29
29
  this.chats = chats;
30
30
  }
31
31
 
@@ -83,7 +83,8 @@ export class ScheduledActionProcessor extends BaseActionProcessor {
83
83
  private async runScheduled() {
84
84
  const ctx = new ChatContextInternal<IActionState>(
85
85
  this.storage,
86
- this.scheduler
86
+ this.scheduler,
87
+ this.eventEmitter
87
88
  );
88
89
 
89
90
  for (const [chatName, chatId] of Object.entries(this.chats)) {
@@ -118,11 +119,5 @@ export class ScheduledActionProcessor extends BaseActionProcessor {
118
119
  ctx.action = action;
119
120
  ctx.chatInfo = chatInfo;
120
121
  ctx.traceId = traceId;
121
-
122
- ctx.logger = this.logger.createScope(
123
- this.botName,
124
- traceId,
125
- chatInfo.name
126
- );
127
122
  }
128
123
  }
@@ -5,12 +5,14 @@ import { IStorageClient } from '../types/storage';
5
5
  import { IActionState } from '../types/actionState';
6
6
  import { IActionWithState, ActionKey } from '../types/action';
7
7
  import { getOrSetIfNotExists } from '../helpers/mapUtils';
8
+ import { BotEventType, TypedEventEmitter } from '../types/events';
8
9
 
9
10
  function buildPath(storagePath: string, botName: string, actionKey: string) {
10
11
  return `${storagePath}/${botName}/${actionKey.replaceAll(':', '/')}.json`;
11
12
  }
12
13
 
13
14
  export class JsonFileStorage implements IStorageClient {
15
+ private readonly eventEmitter: TypedEventEmitter;
14
16
  private readonly filePaths = new Map<ActionKey, string>();
15
17
  private readonly locks = new Map<ActionKey, Semaphore>();
16
18
  private readonly cache: Map<string, Record<number, IActionState>>;
@@ -20,8 +22,10 @@ export class JsonFileStorage implements IStorageClient {
20
22
  constructor(
21
23
  botName: string,
22
24
  actions: IActionWithState<IActionState>[],
25
+ eventEmitter: TypedEventEmitter,
23
26
  path?: string
24
27
  ) {
28
+ this.eventEmitter = eventEmitter;
25
29
  this.cache = new Map<string, Record<number, IActionState>>();
26
30
  this.botName = botName;
27
31
  this.storagePath = path ?? 'storage';
@@ -57,12 +61,15 @@ export class JsonFileStorage implements IStorageClient {
57
61
  private async lock<TType>(key: ActionKey, action: () => Promise<TType>) {
58
62
  const lock = getOrSetIfNotExists(this.locks, key, new Semaphore(1));
59
63
 
64
+ this.eventEmitter.emit(BotEventType.storageLockAcquiring, key);
60
65
  await lock.acquire();
66
+ this.eventEmitter.emit(BotEventType.storageLockAcquired, key);
61
67
 
62
68
  try {
63
69
  return await action();
64
70
  } finally {
65
71
  lock.release();
72
+ this.eventEmitter.emit(BotEventType.storageLockReleased, key);
66
73
  }
67
74
  }
68
75
 
@@ -103,6 +110,10 @@ export class JsonFileStorage implements IStorageClient {
103
110
  data: Record<number, TActionState>,
104
111
  key: ActionKey
105
112
  ) {
113
+ this.eventEmitter.emit(BotEventType.storageStateSaving, {
114
+ data,
115
+ key
116
+ });
106
117
  this.cache.set(key, data);
107
118
 
108
119
  const targetPath = getOrSetIfNotExists(
@@ -112,6 +123,10 @@ export class JsonFileStorage implements IStorageClient {
112
123
  );
113
124
 
114
125
  await writeFile(targetPath, JSON.stringify(data), { flag: 'w+' });
126
+ this.eventEmitter.emit(BotEventType.storageStateSaved, {
127
+ data,
128
+ key
129
+ });
115
130
  }
116
131
 
117
132
  async load<TActionState extends IActionState>(key: ActionKey) {
@@ -135,13 +150,24 @@ export class JsonFileStorage implements IStorageClient {
135
150
  action: IActionWithState<TActionState>,
136
151
  chatId: number
137
152
  ) {
153
+ this.eventEmitter.emit(BotEventType.storageStateLoading, {
154
+ action,
155
+ chatId
156
+ });
138
157
  const value =
139
158
  this.tryGetFromCache<TActionState>(action.key) ??
140
159
  (await this.lock(action.key, async () => {
141
160
  return await this.loadFromFile<TActionState>(action.key);
142
161
  }));
143
162
 
144
- return Object.assign(action.stateConstructor(), value[chatId]);
163
+ const result = Object.assign(action.stateConstructor(), value[chatId]);
164
+
165
+ this.eventEmitter.emit(BotEventType.storageStateLoaded, {
166
+ action,
167
+ chatId,
168
+ state: result
169
+ });
170
+ return result;
145
171
  }
146
172
 
147
173
  async saveActionExecutionResult<TActionState extends IActionState>(
@@ -1,16 +1,12 @@
1
1
  import { TaskRecord } from '../entities/taskRecord';
2
- import { createTrace } from '../helpers/traceFactory';
3
- import { ILogger } from '../types/logger';
2
+ import { BotEventType, TypedEventEmitter } from '../types/events';
4
3
  import { IScheduler } from '../types/scheduler';
5
4
  import { Milliseconds } from '../types/timeValues';
6
5
 
7
6
  export class NodeTimeoutScheduler implements IScheduler {
8
- private readonly logger!: ILogger;
9
7
  readonly activeTasks: TaskRecord[] = [];
10
8
 
11
- constructor(logger: ILogger) {
12
- this.logger = logger;
13
- }
9
+ constructor(readonly eventEmitter: TypedEventEmitter) {}
14
10
 
15
11
  stopAll() {
16
12
  for (const task of this.activeTasks) {
@@ -25,19 +21,25 @@ export class NodeTimeoutScheduler implements IScheduler {
25
21
  executeRightAway: boolean,
26
22
  ownerName: string
27
23
  ) {
28
- const taskId = setInterval(action, interval);
24
+ const taskId = setInterval(() => {
25
+ action();
26
+ this.eventEmitter.emit(BotEventType.taskRun, {
27
+ name,
28
+ ownerName,
29
+ interval
30
+ });
31
+ }, interval);
29
32
  const task = new TaskRecord(name, taskId, interval);
30
33
 
31
34
  if (executeRightAway) {
32
35
  setImmediate(action);
33
36
  }
34
37
 
35
- this.logger.logWithTraceId(
38
+ this.eventEmitter.emit(BotEventType.taskCreated, {
39
+ name,
36
40
  ownerName,
37
- createTrace(this, ownerName, name),
38
- 'System',
39
- `Created task ${name}, that will run every ${interval}ms.`
40
- );
41
+ interval
42
+ });
41
43
 
42
44
  this.activeTasks.push(task);
43
45
  }
@@ -49,21 +51,19 @@ export class NodeTimeoutScheduler implements IScheduler {
49
51
  ownerName: string
50
52
  ) {
51
53
  const actionWrapper = () => {
52
- this.logger.logWithTraceId(
54
+ this.eventEmitter.emit(BotEventType.taskRun, {
55
+ name,
53
56
  ownerName,
54
- createTrace(this, ownerName, name),
55
- 'System',
56
- `Executing delayed oneshot ${name}`
57
- );
57
+ delay
58
+ });
58
59
  action();
59
60
  };
60
61
  setTimeout(actionWrapper, delay);
61
62
 
62
- this.logger.logWithTraceId(
63
+ this.eventEmitter.emit(BotEventType.taskCreated, {
64
+ name,
63
65
  ownerName,
64
- createTrace(this, ownerName, name),
65
- 'System',
66
- `Created oneshot task ${name}, that will run in ${delay}ms.`
67
- );
66
+ delay
67
+ });
68
68
  }
69
69
  }
@@ -1,6 +1,9 @@
1
1
  import { IStorageClient } from '../types/storage';
2
- import { BotResponse, IReplyResponse } from '../types/response';
3
- import { ILogger } from '../types/logger';
2
+ import {
3
+ BotResponse,
4
+ BotResponseTypes,
5
+ IReplyResponse
6
+ } from '../types/response';
4
7
  import { QueueItem, ResponseProcessingQueue } from './responseProcessingQueue';
5
8
  import { IReplyCapture } from '../types/capture';
6
9
  import { IActionWithState } from '../types/action';
@@ -8,6 +11,7 @@ import { IActionState } from '../types/actionState';
8
11
  import { TraceId } from '../types/trace';
9
12
  import { ChatInfo } from '../dtos/chatInfo';
10
13
  import { TelegramApiClient, TelegramMessage } from '../types/externalAliases';
14
+ import { BotEventType, TypedEventEmitter } from '../types/events';
11
15
 
12
16
  export const TELEGRAM_ERROR_QUOTE_INVALID = 'QUOTE_TEXT_INVALID';
13
17
 
@@ -15,7 +19,7 @@ export class TelegramApiService {
15
19
  private readonly queue = new ResponseProcessingQueue();
16
20
  private readonly telegram: TelegramApiClient;
17
21
  private readonly storage: IStorageClient;
18
- private readonly logger: ILogger;
22
+ private readonly eventEmitter: TypedEventEmitter;
19
23
  private readonly captureRegistrationCallback: (
20
24
  capture: IReplyCapture,
21
25
  parentMessageId: number,
@@ -25,22 +29,35 @@ export class TelegramApiService {
25
29
 
26
30
  private readonly botName: string;
27
31
 
32
+ private readonly methodMap: Record<
33
+ 'pin' | keyof typeof BotResponseTypes,
34
+ string | null
35
+ > = {
36
+ inlineQuery: 'answerInlineQuery',
37
+ text: 'sendMessage',
38
+ react: 'setMessageReaction',
39
+ unpin: 'unpinChatMessage',
40
+ pin: 'pinChatMessage',
41
+ image: 'sendPhoto',
42
+ video: 'sendVideo',
43
+ delay: null
44
+ };
45
+
28
46
  constructor(
29
47
  botName: string,
30
48
  telegram: TelegramApiClient,
31
49
  storage: IStorageClient,
32
- logger: ILogger,
50
+ eventEmitter: TypedEventEmitter,
33
51
  captureRegistrationCallback: (
34
52
  capture: IReplyCapture,
35
53
  parentMessageId: number,
36
- chatInfo: ChatInfo,
37
- traceId: TraceId
54
+ chatInfo: ChatInfo
38
55
  ) => void
39
56
  ) {
40
57
  this.telegram = telegram;
41
58
  this.botName = botName;
42
59
  this.storage = storage;
43
- this.logger = logger;
60
+ this.eventEmitter = eventEmitter;
44
61
  this.captureRegistrationCallback = captureRegistrationCallback;
45
62
  }
46
63
 
@@ -54,14 +71,6 @@ export class TelegramApiService {
54
71
 
55
72
  const queueItem: QueueItem = {
56
73
  callback: async () => {
57
- const scopedLogger = this.logger.createScope(
58
- this.botName,
59
- response.traceId,
60
- 'chatInfo' in response
61
- ? response.chatInfo.name
62
- : 'Unknown'
63
- );
64
-
65
74
  try {
66
75
  await this.processResponse(response);
67
76
  } catch (error) {
@@ -75,23 +84,27 @@ export class TelegramApiService {
75
84
  TELEGRAM_ERROR_QUOTE_INVALID
76
85
  )
77
86
  ) {
78
- scopedLogger.logWithTraceId(
79
- 'Quote error recieved, retrying without quote'
80
- );
87
+ this.eventEmitter.emit(BotEventType.error, {
88
+ error: new Error(
89
+ 'Quote error recieved, retrying without quote'
90
+ )
91
+ });
92
+
81
93
  try {
82
94
  await this.processResponse(response, true);
83
95
  } catch (error) {
84
- scopedLogger.errorWithTraceId(
85
- error,
86
- response
87
- );
96
+ this.eventEmitter.emit(BotEventType.error, {
97
+ error: error as Error
98
+ });
88
99
  }
89
100
 
90
101
  return;
91
102
  }
92
103
  }
93
104
 
94
- scopedLogger.errorWithTraceId(error, response);
105
+ this.eventEmitter.emit(BotEventType.error, {
106
+ error: error as Error
107
+ });
95
108
  }
96
109
  },
97
110
  priority: response.createdAt + offset
@@ -109,11 +122,19 @@ export class TelegramApiService {
109
122
  message: TelegramMessage
110
123
  ) {
111
124
  if (response.shouldPin) {
125
+ this.eventEmitter.emit(BotEventType.apiRequestSending, {
126
+ response: null,
127
+ telegramMethod: this.methodMap['pin']
128
+ });
112
129
  await this.telegram.pinChatMessage(
113
130
  response.chatInfo.id,
114
131
  message.message_id,
115
132
  { disable_notification: true }
116
133
  );
134
+ this.eventEmitter.emit(BotEventType.apiRequestSent, {
135
+ response: null,
136
+ telegramMethod: this.methodMap['pin']
137
+ });
117
138
 
118
139
  await this.storage.updateStateFor(
119
140
  response.action as IActionWithState<IActionState>,
@@ -127,6 +148,10 @@ export class TelegramApiService {
127
148
 
128
149
  private async processResponse(response: BotResponse, ignoreQuote = false) {
129
150
  const sentMessage = await this.sendApiRequest(response, ignoreQuote);
151
+ this.eventEmitter.emit(BotEventType.apiRequestSent, {
152
+ response,
153
+ telegramMethod: this.methodMap[response.kind]
154
+ });
130
155
 
131
156
  if (sentMessage && 'content' in response) {
132
157
  await this.pinIfShould(response, sentMessage);
@@ -146,6 +171,11 @@ export class TelegramApiService {
146
171
  response: BotResponse,
147
172
  ignoreQuote: boolean
148
173
  ): Promise<TelegramMessage | null> {
174
+ this.eventEmitter.emit(BotEventType.apiRequestSending, {
175
+ response,
176
+ telegramMethod: this.methodMap[response.kind]
177
+ });
178
+
149
179
  switch (response.kind) {
150
180
  case 'text':
151
181
  return await this.telegram.sendMessage(