chz-telegram-bot 0.5.4 → 0.5.5

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 (214) hide show
  1. package/dist/builtin/helpAction.d.ts +2 -0
  2. package/dist/builtin/helpAction.d.ts.map +1 -0
  3. package/dist/builtin/helpAction.js +14 -0
  4. package/dist/dtos/chatHistoryMessage.d.ts +35 -0
  5. package/dist/dtos/chatHistoryMessage.d.ts.map +1 -0
  6. package/dist/dtos/chatHistoryMessage.js +32 -0
  7. package/dist/dtos/chatInfo.d.ts +17 -0
  8. package/dist/dtos/chatInfo.d.ts.map +1 -0
  9. package/dist/dtos/chatInfo.js +16 -0
  10. package/dist/dtos/commandTriggerCheckResult.d.ts +24 -0
  11. package/dist/dtos/commandTriggerCheckResult.d.ts.map +1 -0
  12. package/dist/dtos/commandTriggerCheckResult.js +34 -0
  13. package/dist/dtos/cooldownInfo.d.ts +13 -0
  14. package/dist/dtos/cooldownInfo.d.ts.map +1 -0
  15. package/dist/dtos/cooldownInfo.js +12 -0
  16. package/dist/dtos/incomingMessage.d.ts +19 -0
  17. package/dist/dtos/incomingMessage.d.ts.map +1 -0
  18. package/dist/dtos/incomingMessage.js +63 -0
  19. package/dist/dtos/incomingQuery.d.ts +10 -0
  20. package/dist/dtos/incomingQuery.d.ts.map +1 -0
  21. package/dist/dtos/incomingQuery.js +14 -0
  22. package/dist/dtos/messageInfo.d.ts +22 -0
  23. package/dist/dtos/messageInfo.d.ts.map +1 -0
  24. package/dist/dtos/messageInfo.js +20 -0
  25. package/dist/dtos/propertyProviderSets.d.ts +16 -0
  26. package/dist/dtos/propertyProviderSets.d.ts.map +1 -0
  27. package/dist/dtos/propertyProviderSets.js +1 -0
  28. package/dist/dtos/replyInfo.d.ts +6 -0
  29. package/dist/dtos/replyInfo.d.ts.map +1 -0
  30. package/dist/dtos/replyInfo.js +8 -0
  31. package/dist/dtos/responses/delay.d.ts +16 -0
  32. package/dist/dtos/responses/delay.d.ts.map +1 -0
  33. package/dist/dtos/responses/delay.js +15 -0
  34. package/dist/dtos/responses/imageMessage.d.ts +22 -0
  35. package/dist/dtos/responses/imageMessage.d.ts.map +1 -0
  36. package/dist/dtos/responses/imageMessage.js +21 -0
  37. package/dist/dtos/responses/inlineQueryResponse.d.ts +13 -0
  38. package/dist/dtos/responses/inlineQueryResponse.d.ts.map +1 -0
  39. package/dist/dtos/responses/inlineQueryResponse.js +15 -0
  40. package/dist/dtos/responses/reaction.d.ts +16 -0
  41. package/dist/dtos/responses/reaction.d.ts.map +1 -0
  42. package/dist/dtos/responses/reaction.js +17 -0
  43. package/dist/dtos/responses/textMessage.d.ts +23 -0
  44. package/dist/dtos/responses/textMessage.d.ts.map +1 -0
  45. package/dist/dtos/responses/textMessage.js +24 -0
  46. package/dist/dtos/responses/unpin.d.ts +15 -0
  47. package/dist/dtos/responses/unpin.d.ts.map +1 -0
  48. package/dist/dtos/responses/unpin.js +15 -0
  49. package/dist/dtos/responses/videoMessage.d.ts +22 -0
  50. package/dist/dtos/responses/videoMessage.d.ts.map +1 -0
  51. package/dist/dtos/responses/videoMessage.js +21 -0
  52. package/dist/dtos/userInfo.d.ts +12 -0
  53. package/dist/dtos/userInfo.d.ts.map +1 -0
  54. package/dist/dtos/userInfo.js +12 -0
  55. package/dist/entities/actions/commandAction.d.ts +31 -0
  56. package/dist/entities/actions/commandAction.d.ts.map +1 -0
  57. package/dist/entities/actions/commandAction.js +139 -0
  58. package/dist/entities/actions/inlineQueryAction.d.ts +14 -0
  59. package/dist/entities/actions/inlineQueryAction.d.ts.map +1 -0
  60. package/dist/entities/actions/inlineQueryAction.js +43 -0
  61. package/dist/entities/actions/replyCaptureAction.d.ts +15 -0
  62. package/dist/entities/actions/replyCaptureAction.d.ts.map +1 -0
  63. package/dist/entities/actions/replyCaptureAction.js +58 -0
  64. package/dist/entities/actions/scheduledAction.d.ts +24 -0
  65. package/dist/entities/actions/scheduledAction.d.ts.map +1 -0
  66. package/dist/entities/actions/scheduledAction.js +72 -0
  67. package/dist/entities/botInstance.d.ts +37 -0
  68. package/dist/entities/botInstance.d.ts.map +1 -0
  69. package/dist/entities/botInstance.js +37 -0
  70. package/dist/entities/cachedStateFactory.d.ts +7 -0
  71. package/dist/entities/cachedStateFactory.d.ts.map +1 -0
  72. package/dist/entities/cachedStateFactory.js +8 -0
  73. package/dist/entities/context/baseContext.d.ts +39 -0
  74. package/dist/entities/context/baseContext.d.ts.map +1 -0
  75. package/dist/entities/context/baseContext.js +55 -0
  76. package/dist/entities/context/chatContext.d.ts +50 -0
  77. package/dist/entities/context/chatContext.d.ts.map +1 -0
  78. package/dist/entities/context/chatContext.js +65 -0
  79. package/dist/entities/context/inlineQueryContext.d.ts +27 -0
  80. package/dist/entities/context/inlineQueryContext.d.ts.map +1 -0
  81. package/dist/entities/context/inlineQueryContext.js +29 -0
  82. package/dist/entities/context/messageContext.d.ts +92 -0
  83. package/dist/entities/context/messageContext.d.ts.map +1 -0
  84. package/dist/entities/context/messageContext.js +116 -0
  85. package/dist/entities/context/replyContext.d.ts +89 -0
  86. package/dist/entities/context/replyContext.d.ts.map +1 -0
  87. package/dist/entities/context/replyContext.js +124 -0
  88. package/dist/entities/states/actionStateBase.d.ts +6 -0
  89. package/dist/entities/states/actionStateBase.d.ts.map +1 -0
  90. package/dist/entities/states/actionStateBase.js +4 -0
  91. package/dist/entities/taskRecord.d.ts +8 -0
  92. package/dist/entities/taskRecord.d.ts.map +1 -0
  93. package/dist/entities/taskRecord.js +10 -0
  94. package/dist/eslint.config.d.ts +3 -0
  95. package/dist/eslint.config.d.ts.map +1 -0
  96. package/dist/eslint.config.js +51 -0
  97. package/dist/helpers/builders/commandActionBuilder.d.ts +100 -0
  98. package/dist/helpers/builders/commandActionBuilder.d.ts.map +1 -0
  99. package/dist/helpers/builders/commandActionBuilder.js +146 -0
  100. package/dist/helpers/builders/inlineQueryActionBuilder.d.ts +37 -0
  101. package/dist/helpers/builders/inlineQueryActionBuilder.d.ts.map +1 -0
  102. package/dist/helpers/builders/inlineQueryActionBuilder.js +50 -0
  103. package/dist/helpers/builders/scheduledActionBuilder.d.ts +68 -0
  104. package/dist/helpers/builders/scheduledActionBuilder.d.ts.map +1 -0
  105. package/dist/helpers/builders/scheduledActionBuilder.js +95 -0
  106. package/dist/helpers/mapUtils.d.ts +10 -0
  107. package/dist/helpers/mapUtils.d.ts.map +1 -0
  108. package/dist/helpers/mapUtils.js +13 -0
  109. package/dist/helpers/noop.d.ts +9 -0
  110. package/dist/helpers/noop.d.ts.map +1 -0
  111. package/dist/helpers/noop.js +17 -0
  112. package/dist/helpers/objectFromEntries.d.ts +2 -0
  113. package/dist/helpers/objectFromEntries.d.ts.map +1 -0
  114. package/dist/helpers/objectFromEntries.js +3 -0
  115. package/dist/helpers/timeConvertions.d.ts +5 -0
  116. package/dist/helpers/timeConvertions.d.ts.map +1 -0
  117. package/dist/helpers/timeConvertions.js +9 -0
  118. package/dist/helpers/toArray.d.ts +2 -0
  119. package/dist/helpers/toArray.d.ts.map +1 -0
  120. package/dist/helpers/toArray.js +3 -0
  121. package/dist/helpers/traceFactory.d.ts +3 -0
  122. package/dist/helpers/traceFactory.d.ts.map +1 -0
  123. package/dist/helpers/traceFactory.js +3 -0
  124. package/dist/index.d.ts +27 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +20 -0
  127. package/dist/main.d.ts +52 -0
  128. package/dist/main.d.ts.map +1 -0
  129. package/dist/main.js +34 -0
  130. package/dist/services/actionProcessingService.d.ts +25 -0
  131. package/dist/services/actionProcessingService.d.ts.map +1 -0
  132. package/dist/services/actionProcessingService.js +50 -0
  133. package/dist/services/actionProcessors/baseProcessor.d.ts +18 -0
  134. package/dist/services/actionProcessors/baseProcessor.d.ts.map +1 -0
  135. package/dist/services/actionProcessors/baseProcessor.js +29 -0
  136. package/dist/services/actionProcessors/commandActionProcessor.d.ts +20 -0
  137. package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -0
  138. package/dist/services/actionProcessors/commandActionProcessor.js +116 -0
  139. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts +11 -0
  140. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -0
  141. package/dist/services/actionProcessors/inlineQueryActionProcessor.js +61 -0
  142. package/dist/services/actionProcessors/scheduledActionProcessor.d.ts +17 -0
  143. package/dist/services/actionProcessors/scheduledActionProcessor.d.ts.map +1 -0
  144. package/dist/services/actionProcessors/scheduledActionProcessor.js +56 -0
  145. package/dist/services/jsonFileStorage.d.ts +23 -0
  146. package/dist/services/jsonFileStorage.d.ts.map +1 -0
  147. package/dist/services/jsonFileStorage.js +109 -0
  148. package/dist/services/jsonLogger.d.ts +11 -0
  149. package/dist/services/jsonLogger.d.ts.map +1 -0
  150. package/dist/services/jsonLogger.js +66 -0
  151. package/dist/services/nodeTimeoutScheduler.d.ts +13 -0
  152. package/dist/services/nodeTimeoutScheduler.d.ts.map +1 -0
  153. package/dist/services/nodeTimeoutScheduler.js +31 -0
  154. package/dist/services/responseProcessingQueue.d.ts +12 -0
  155. package/dist/services/responseProcessingQueue.d.ts.map +1 -0
  156. package/dist/services/responseProcessingQueue.js +37 -0
  157. package/dist/services/telegramApi.d.ts +23 -0
  158. package/dist/services/telegramApi.d.ts.map +1 -0
  159. package/dist/services/telegramApi.js +133 -0
  160. package/dist/types/action.d.ts +14 -0
  161. package/dist/types/action.d.ts.map +1 -0
  162. package/dist/types/action.js +1 -0
  163. package/dist/types/actionState.d.ts +5 -0
  164. package/dist/types/actionState.d.ts.map +1 -0
  165. package/dist/types/actionState.js +1 -0
  166. package/dist/types/cachedValueAccessor.d.ts +2 -0
  167. package/dist/types/cachedValueAccessor.d.ts.map +1 -0
  168. package/dist/types/cachedValueAccessor.js +1 -0
  169. package/dist/types/capture.d.ts +24 -0
  170. package/dist/types/capture.d.ts.map +1 -0
  171. package/dist/types/capture.js +1 -0
  172. package/dist/types/commandCondition.d.ts +8 -0
  173. package/dist/types/commandCondition.d.ts.map +1 -0
  174. package/dist/types/commandCondition.js +1 -0
  175. package/dist/types/commandTrigger.d.ts +2 -0
  176. package/dist/types/commandTrigger.d.ts.map +1 -0
  177. package/dist/types/commandTrigger.js +1 -0
  178. package/dist/types/externalAliases.d.ts +11 -0
  179. package/dist/types/externalAliases.d.ts.map +1 -0
  180. package/dist/types/externalAliases.js +1 -0
  181. package/dist/types/handlers.d.ts +21 -0
  182. package/dist/types/handlers.d.ts.map +1 -0
  183. package/dist/types/handlers.js +1 -0
  184. package/dist/types/inputFile.d.ts +5 -0
  185. package/dist/types/inputFile.d.ts.map +1 -0
  186. package/dist/types/inputFile.js +1 -0
  187. package/dist/types/logger.d.ts +13 -0
  188. package/dist/types/logger.d.ts.map +1 -0
  189. package/dist/types/logger.js +1 -0
  190. package/dist/types/messageSendingOptions.d.ts +9 -0
  191. package/dist/types/messageSendingOptions.d.ts.map +1 -0
  192. package/dist/types/messageSendingOptions.js +1 -0
  193. package/dist/types/messageTypes.d.ts +20 -0
  194. package/dist/types/messageTypes.d.ts.map +1 -0
  195. package/dist/types/messageTypes.js +18 -0
  196. package/dist/types/propertyProvider.d.ts +8 -0
  197. package/dist/types/propertyProvider.d.ts.map +1 -0
  198. package/dist/types/propertyProvider.js +1 -0
  199. package/dist/types/response.d.ts +39 -0
  200. package/dist/types/response.d.ts.map +1 -0
  201. package/dist/types/response.js +9 -0
  202. package/dist/types/scheduler.d.ts +7 -0
  203. package/dist/types/scheduler.d.ts.map +1 -0
  204. package/dist/types/scheduler.js +1 -0
  205. package/dist/types/storage.d.ts +11 -0
  206. package/dist/types/storage.d.ts.map +1 -0
  207. package/dist/types/storage.js +1 -0
  208. package/dist/types/timeValues.d.ts +15 -0
  209. package/dist/types/timeValues.d.ts.map +1 -0
  210. package/dist/types/timeValues.js +1 -0
  211. package/dist/types/trace.d.ts +6 -0
  212. package/dist/types/trace.d.ts.map +1 -0
  213. package/dist/types/trace.js +1 -0
  214. package/package.json +38 -38
@@ -0,0 +1,116 @@
1
+ import { IncomingMessage } from '../../dtos/incomingMessage';
2
+ import { ReplyCaptureAction } from '../../entities/actions/replyCaptureAction';
3
+ import { MessageContextInternal } from '../../entities/context/messageContext';
4
+ import { ReplyContextInternal } from '../../entities/context/replyContext';
5
+ import { INTERNAL_MESSAGE_TYPE_PREFIX, MessageType } from '../../types/messageTypes';
6
+ import { typeSafeObjectFromEntries } from '../../helpers/objectFromEntries';
7
+ import { BaseActionProcessor } from './baseProcessor';
8
+ import { getOrSetIfNotExists } from '../../helpers/mapUtils';
9
+ import { MessageInfo } from '../../dtos/messageInfo';
10
+ import { UserInfo } from '../../dtos/userInfo';
11
+ import { ChatHistoryMessage } from '../../dtos/chatHistoryMessage';
12
+ const MESSAGE_HISTORY_LENGTH_LIMIT = 100;
13
+ export class CommandActionProcessor extends BaseActionProcessor {
14
+ replyCaptures = [];
15
+ chatHistory = new Map();
16
+ botInfo;
17
+ commands = typeSafeObjectFromEntries(Object.values(MessageType).map((x) => [
18
+ x,
19
+ []
20
+ ]));
21
+ initialize(api, telegram, commands, verboseLoggingForIncomingMessage, botInfo) {
22
+ this.botInfo = botInfo;
23
+ this.initializeDependencies(api);
24
+ for (const msgType of Object.values(MessageType)) {
25
+ if (msgType == MessageType.Text) {
26
+ this.commands[msgType] = commands.filter((cmd) => cmd.triggers.some((x) => typeof x != 'string') ||
27
+ cmd.triggers.some((x) => typeof x == 'string' &&
28
+ !x.startsWith(INTERNAL_MESSAGE_TYPE_PREFIX)) ||
29
+ cmd.triggers.includes(MessageType.Text) ||
30
+ cmd.triggers.includes(MessageType.Any));
31
+ continue;
32
+ }
33
+ this.commands[msgType] = commands.filter((cmd) => cmd.triggers.includes(msgType) ||
34
+ cmd.triggers.includes(MessageType.Any));
35
+ }
36
+ if (commands.length > 0) {
37
+ telegram.on('message', ({ message }) => {
38
+ const internalMessage = new IncomingMessage(message, this.botName, getOrSetIfNotExists(this.chatHistory, message.chat.id, []));
39
+ const logger = this.logger.createScope(this.botName, internalMessage.traceId, internalMessage.chatInfo.name);
40
+ if (verboseLoggingForIncomingMessage) {
41
+ logger.logObjectWithTraceId(message);
42
+ }
43
+ else {
44
+ logger.logWithTraceId(`${internalMessage.from?.first_name ?? 'Unknown'} (${internalMessage.from?.id ?? 'Unknown'}): ${internalMessage.text || internalMessage.type}`);
45
+ }
46
+ void this.processMessage(internalMessage);
47
+ });
48
+ }
49
+ }
50
+ captureRegistrationCallback(capture, parentMessageId, chatInfo, traceId) {
51
+ const replyAction = new ReplyCaptureAction(parentMessageId, capture.action, capture.handler, capture.trigger, capture.abortController);
52
+ const logger = this.logger.createScope(this.botName, traceId, chatInfo.name);
53
+ logger.logWithTraceId(`Starting capturing replies to message ${parentMessageId} with action ${replyAction.key}`);
54
+ this.replyCaptures.push(replyAction);
55
+ capture.abortController.signal.addEventListener('abort', () => {
56
+ const index = this.replyCaptures.indexOf(replyAction);
57
+ this.replyCaptures.splice(index, 1);
58
+ logger.logWithTraceId(`Stopping capturing replies to message ${parentMessageId} with action ${replyAction.key}`);
59
+ });
60
+ }
61
+ async processMessage(msg) {
62
+ const chatHistoryArray = getOrSetIfNotExists(this.chatHistory, msg.chatInfo.id, []);
63
+ while (chatHistoryArray.length > MESSAGE_HISTORY_LENGTH_LIMIT)
64
+ chatHistoryArray.shift();
65
+ chatHistoryArray.push(new ChatHistoryMessage(msg.messageId, msg.from, msg.text, msg.type, msg.traceId, msg.replyToMessageId, msg.updateObject.date));
66
+ const ctx = new MessageContextInternal(this.storage, this.scheduler);
67
+ const commandsToCheck = new Set(this.commands[msg.type]);
68
+ if (msg.type != MessageType.Text && msg.text != '') {
69
+ for (const command of this.commands[MessageType.Text]) {
70
+ commandsToCheck.add(command);
71
+ }
72
+ }
73
+ for (const commandAction of commandsToCheck) {
74
+ this.initializeMessageContext(ctx, commandAction, msg);
75
+ await this.executeAction(commandAction, ctx);
76
+ }
77
+ if (this.replyCaptures.length != 0) {
78
+ const replyCtx = new ReplyContextInternal(this.storage, this.scheduler);
79
+ for (const replyAction of this.replyCaptures) {
80
+ this.initializeReplyCaptureContext(replyCtx, replyAction, msg);
81
+ await this.executeAction(replyAction, replyCtx);
82
+ }
83
+ }
84
+ this.api.flushResponses();
85
+ }
86
+ initializeReplyCaptureContext(ctx, action, message) {
87
+ ctx.replyMessageId = message.replyToMessageId;
88
+ ctx.messageInfo = new MessageInfo(message.messageId, message.text, message.type, message.updateObject);
89
+ ctx.userInfo = new UserInfo(message.from?.id ?? -1, (message.from?.first_name ?? 'Unknown user') +
90
+ (message.from?.last_name ? ` ${message.from.last_name}` : ''));
91
+ ctx.botName = this.botName;
92
+ ctx.action = action;
93
+ ctx.chatInfo = message.chatInfo;
94
+ ctx.traceId = message.traceId;
95
+ ctx.botInfo = this.botInfo;
96
+ ctx.isInitialized = true;
97
+ ctx.matchResults = [];
98
+ ctx.logger = this.logger.createScope(this.botName, message.traceId, message.chatInfo.name);
99
+ }
100
+ initializeMessageContext(ctx, action, message) {
101
+ ctx.messageInfo = new MessageInfo(message.messageId, message.text, message.type, message.updateObject);
102
+ ctx.userInfo = new UserInfo(message.from?.id ?? -1, (message.from?.first_name ?? 'Unknown user') +
103
+ (message.from?.last_name ? ` ${message.from.last_name}` : ''));
104
+ ctx.matchResults = [];
105
+ ctx.startCooldown = true;
106
+ ctx.responses = [];
107
+ ctx.isInitialized = true;
108
+ ctx.botName = this.botName;
109
+ ctx.action = action;
110
+ ctx.chatInfo = message.chatInfo;
111
+ ctx.traceId = message.traceId;
112
+ ctx.botInfo = this.botInfo;
113
+ ctx.customCooldown = undefined;
114
+ ctx.logger = this.logger.createScope(this.botName, message.traceId, message.chatInfo.name);
115
+ }
116
+ }
@@ -0,0 +1,11 @@
1
+ import { InlineQueryAction } from '../../entities/actions/inlineQueryAction';
2
+ import { TelegramBot } from '../../types/externalAliases';
3
+ import { Milliseconds } from '../../types/timeValues';
4
+ import { TelegramApiService } from '../telegramApi';
5
+ import { BaseActionProcessor } from './baseProcessor';
6
+ export declare class InlineQueryActionProcessor extends BaseActionProcessor {
7
+ private inlineQueries;
8
+ initialize(api: TelegramApiService, telegram: TelegramBot, inlineQueries: InlineQueryAction[], period: Milliseconds): void;
9
+ private initializeInlineQueryContext;
10
+ }
11
+ //# sourceMappingURL=inlineQueryActionProcessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inlineQueryActionProcessor.d.ts","sourceRoot":"","sources":["../../../services/actionProcessors/inlineQueryActionProcessor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAG7E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,qBAAa,0BAA2B,SAAQ,mBAAmB;IAC/D,OAAO,CAAC,aAAa,CAAuB;IAE5C,UAAU,CACN,GAAG,EAAE,kBAAkB,EACvB,QAAQ,EAAE,WAAW,EACrB,aAAa,EAAE,iBAAiB,EAAE,EAClC,MAAM,EAAE,YAAY;IAuGxB,OAAO,CAAC,4BAA4B;CAqBvC"}
@@ -0,0 +1,61 @@
1
+ import { IncomingInlineQuery } from '../../dtos/incomingQuery';
2
+ import { InlineQueryContextInternal } from '../../entities/context/inlineQueryContext';
3
+ import { createTrace } from '../../helpers/traceFactory';
4
+ import { BaseActionProcessor } from './baseProcessor';
5
+ export class InlineQueryActionProcessor extends BaseActionProcessor {
6
+ inlineQueries;
7
+ initialize(api, telegram, inlineQueries, period) {
8
+ this.initializeDependencies(api);
9
+ this.inlineQueries = inlineQueries;
10
+ let pendingInlineQueries = [];
11
+ const queriesInProcessing = new Map();
12
+ if (this.inlineQueries.length > 0) {
13
+ telegram.on('inline_query', ({ inlineQuery }) => {
14
+ const query = new IncomingInlineQuery(inlineQuery.id, inlineQuery.query, inlineQuery.from.id, createTrace('InlineQuery', this.botName, inlineQuery.id));
15
+ const logger = this.logger.createScope(this.botName, query.traceId, 'Query');
16
+ logger.logWithTraceId(`${inlineQuery.from.username ?? 'Unknown'} (${inlineQuery.from.id}): Query for ${inlineQuery.query}`);
17
+ const queryBeingProcessed = queriesInProcessing.get(query.userId);
18
+ if (queryBeingProcessed) {
19
+ logger.logWithTraceId(`Aborting query ${queryBeingProcessed.queryId} (${queryBeingProcessed.query}): new query recieved from ${query.userId}`);
20
+ queryBeingProcessed.abortController.abort();
21
+ queriesInProcessing.delete(query.userId);
22
+ }
23
+ pendingInlineQueries = pendingInlineQueries.filter((q) => q.userId != query.userId);
24
+ pendingInlineQueries.push(query);
25
+ });
26
+ this.scheduler.createTask('InlineQueryProcessing', async () => {
27
+ const ctx = new InlineQueryContextInternal(this.storage, this.scheduler);
28
+ const queriesToProcess = [...pendingInlineQueries];
29
+ pendingInlineQueries = [];
30
+ for (const inlineQuery of queriesToProcess) {
31
+ queriesInProcessing.set(inlineQuery.userId, inlineQuery);
32
+ for (const inlineQueryAction of this.inlineQueries) {
33
+ this.initializeInlineQueryContext(ctx, inlineQuery.query, inlineQuery.queryId, inlineQueryAction, inlineQuery.abortController.signal, inlineQuery.traceId);
34
+ await this.executeAction(inlineQueryAction, ctx, (error, ctx) => {
35
+ if (error.name == 'AbortError') {
36
+ ctx.logger.logWithTraceId(`Aborting query ${inlineQuery.queryId} (${inlineQuery.query}) successful.`);
37
+ }
38
+ else {
39
+ ctx.logger.errorWithTraceId(error, ctx);
40
+ }
41
+ });
42
+ }
43
+ queriesInProcessing.delete(inlineQuery.userId);
44
+ }
45
+ this.api.flushResponses();
46
+ }, period, false, this.botName);
47
+ }
48
+ }
49
+ initializeInlineQueryContext(ctx, queryText, queryId, action, abortSignal, traceId) {
50
+ ctx.queryText = queryText;
51
+ ctx.queryId = queryId;
52
+ ctx.botName = this.botName;
53
+ ctx.action = action;
54
+ ctx.traceId = traceId;
55
+ ctx.abortSignal = abortSignal;
56
+ ctx.isInitialized = true;
57
+ ctx.queryResults = [];
58
+ ctx.matchResults = [];
59
+ ctx.logger = this.logger.createScope(this.botName, traceId, 'Unknown');
60
+ }
61
+ }
@@ -0,0 +1,17 @@
1
+ import { ScheduledAction } from '../../entities/actions/scheduledAction';
2
+ import { IActionState } from '../../types/actionState';
3
+ import { ILogger } from '../../types/logger';
4
+ import { IScheduler } from '../../types/scheduler';
5
+ import { IStorageClient } from '../../types/storage';
6
+ import { Seconds } from '../../types/timeValues';
7
+ import { TelegramApiService } from '../telegramApi';
8
+ import { BaseActionProcessor } from './baseProcessor';
9
+ export declare class ScheduledActionProcessor extends BaseActionProcessor {
10
+ private readonly chats;
11
+ private scheduled;
12
+ constructor(botName: string, chats: Record<string, number>, storage: IStorageClient, scheduler: IScheduler, logger: ILogger);
13
+ initialize(api: TelegramApiService, scheduled: ScheduledAction<IActionState>[], period: Seconds): void;
14
+ private runScheduled;
15
+ private initializeChatContext;
16
+ }
17
+ //# sourceMappingURL=scheduledActionProcessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduledActionProcessor.d.ts","sourceRoot":"","sources":["../../../services/actionProcessors/scheduledActionProcessor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAIzE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAgB,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,qBAAa,wBAAyB,SAAQ,mBAAmB;IAC7D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAE/C,OAAO,CAAC,SAAS,CAAmC;gBAGhD,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,UAAU,EACrB,MAAM,EAAE,OAAO;IAMnB,UAAU,CACN,GAAG,EAAE,kBAAkB,EACvB,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,EAC1C,MAAM,EAAE,OAAO;YAgDL,YAAY;IA0B1B,OAAO,CAAC,qBAAqB;CAmBhC"}
@@ -0,0 +1,56 @@
1
+ import moment from 'moment';
2
+ import { ChatInfo } from '../../dtos/chatInfo';
3
+ import { ChatContextInternal } from '../../entities/context/chatContext';
4
+ import { secondsToMilliseconds } from '../../helpers/timeConvertions';
5
+ import { createTrace } from '../../helpers/traceFactory';
6
+ import { BaseActionProcessor } from './baseProcessor';
7
+ export class ScheduledActionProcessor extends BaseActionProcessor {
8
+ chats;
9
+ scheduled;
10
+ constructor(botName, chats, storage, scheduler, logger) {
11
+ super(botName, storage, scheduler, logger);
12
+ this.chats = chats;
13
+ }
14
+ initialize(api, scheduled, period) {
15
+ this.initializeDependencies(api);
16
+ this.scheduled = scheduled;
17
+ if (this.scheduled.length > 0) {
18
+ const now = moment();
19
+ if (now.minute() == 0 && now.second() == 0) {
20
+ this.scheduler.createTask('ScheduledProcessing', async () => {
21
+ await this.runScheduled();
22
+ }, secondsToMilliseconds(period), true, this.botName);
23
+ return;
24
+ }
25
+ let nextExecutionTime = now.clone().startOf('hour');
26
+ if (now.minute() > 0 || now.second() > 0) {
27
+ nextExecutionTime = nextExecutionTime.add(1, 'hour');
28
+ }
29
+ const delay = nextExecutionTime.diff(now);
30
+ this.scheduler.createOnetimeTask('ScheduledProcessing_OneTime', () => {
31
+ this.scheduler.createTask('ScheduledProcessing', () => {
32
+ void this.runScheduled();
33
+ }, secondsToMilliseconds(period), true, this.botName);
34
+ }, delay, this.botName);
35
+ }
36
+ }
37
+ async runScheduled() {
38
+ const ctx = new ChatContextInternal(this.storage, this.scheduler);
39
+ for (const [chatName, chatId] of Object.entries(this.chats)) {
40
+ for (const scheduledAction of this.scheduled) {
41
+ this.initializeChatContext(ctx, scheduledAction, new ChatInfo(chatId, chatName, []), createTrace(scheduledAction, this.botName, `${scheduledAction.key}-${chatId}`));
42
+ await this.executeAction(scheduledAction, ctx);
43
+ }
44
+ }
45
+ this.api.flushResponses();
46
+ }
47
+ initializeChatContext(ctx, action, chatInfo, traceId) {
48
+ ctx.responses = [];
49
+ ctx.isInitialized = true;
50
+ ctx.botName = this.botName;
51
+ ctx.action = action;
52
+ ctx.chatInfo = chatInfo;
53
+ ctx.traceId = traceId;
54
+ ctx.logger = this.logger.createScope(this.botName, traceId, chatInfo.name);
55
+ }
56
+ }
@@ -0,0 +1,23 @@
1
+ import { IStorageClient } from '../types/storage';
2
+ import { IActionState } from '../types/actionState';
3
+ import { IActionWithState, ActionKey } from '../types/action';
4
+ export declare class JsonFileStorage implements IStorageClient {
5
+ private readonly filePaths;
6
+ private readonly locks;
7
+ private readonly cache;
8
+ private readonly storagePath;
9
+ private readonly botName;
10
+ constructor(botName: string, actions: IActionWithState<IActionState>[], path?: string);
11
+ private backfillEmptyActionStates;
12
+ private lock;
13
+ private tryGetFromCache;
14
+ private loadFromFile;
15
+ private updateCacheAndSaveToFile;
16
+ load<TActionState extends IActionState>(key: ActionKey): Promise<Record<number, TActionState | undefined>>;
17
+ saveMetadata(actions: IActionWithState<IActionState>[]): Promise<void>;
18
+ getActionState<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number): Promise<TActionState | (TActionState & undefined)>;
19
+ saveActionExecutionResult<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, state: TActionState): Promise<void>;
20
+ close(): Promise<void>;
21
+ updateStateFor<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, update: (state: TActionState) => Promise<void> | void): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=jsonFileStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonFileStorage.d.ts","sourceRoot":"","sources":["../../services/jsonFileStorage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO9D,qBAAa,eAAgB,YAAW,cAAc;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAG7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,EACzC,IAAI,CAAC,EAAE,MAAM;IAqBjB,OAAO,CAAC,yBAAyB;YAanB,IAAI;IAYlB,OAAO,CAAC,eAAe;YAIT,YAAY;YA6BZ,wBAAwB;IAehC,IAAI,CAAC,YAAY,SAAS,YAAY,EAAE,GAAG,EAAE,SAAS;IAStD,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE;IAQtD,cAAc,CAAC,YAAY,SAAS,YAAY,EAClD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM;IAWZ,yBAAyB,CAAC,YAAY,SAAS,YAAY,EAC7D,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY;IAcjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,cAAc,CAAC,YAAY,SAAS,YAAY,EAClD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;CAkB5D"}
@@ -0,0 +1,109 @@
1
+ import { existsSync, mkdirSync } from 'fs';
2
+ import { readFile, writeFile } from 'fs/promises';
3
+ import { Sema as Semaphore } from 'async-sema';
4
+ import { getOrSetIfNotExists } from '../helpers/mapUtils';
5
+ function buildPath(storagePath, botName, actionKey) {
6
+ return `${storagePath}/${botName}/${actionKey.replaceAll(':', '/')}.json`;
7
+ }
8
+ export class JsonFileStorage {
9
+ filePaths = new Map();
10
+ locks = new Map();
11
+ cache;
12
+ storagePath;
13
+ botName;
14
+ constructor(botName, actions, path) {
15
+ this.cache = new Map();
16
+ this.botName = botName;
17
+ this.storagePath = path ?? 'storage';
18
+ if (!existsSync(`${this.storagePath}/${this.botName}/`)) {
19
+ mkdirSync(`${this.storagePath}/${this.botName}/`, {
20
+ recursive: true
21
+ });
22
+ }
23
+ for (const action of actions) {
24
+ this.locks.set(action.key, new Semaphore(1));
25
+ this.filePaths.set(action.key, buildPath(this.storagePath, this.botName, action.key));
26
+ }
27
+ }
28
+ backfillEmptyActionStates(action, data) {
29
+ for (const [stringKey, value] of Object.entries(data)) {
30
+ if (value)
31
+ continue;
32
+ data[Number.parseInt(stringKey)] = action.stateConstructor();
33
+ }
34
+ return true;
35
+ }
36
+ async lock(key, action) {
37
+ const lock = getOrSetIfNotExists(this.locks, key, new Semaphore(1));
38
+ await lock.acquire();
39
+ try {
40
+ return await action();
41
+ }
42
+ finally {
43
+ lock.release();
44
+ }
45
+ }
46
+ tryGetFromCache(key) {
47
+ return this.cache.get(key);
48
+ }
49
+ async loadFromFile(key) {
50
+ const targetPath = getOrSetIfNotExists(this.filePaths, key, buildPath(this.storagePath, this.botName, key));
51
+ const fileContent = await readFile(targetPath, {
52
+ encoding: 'utf-8',
53
+ flag: 'a+'
54
+ });
55
+ if (fileContent) {
56
+ const data = JSON.parse(fileContent);
57
+ this.cache.set(key, data);
58
+ }
59
+ return (this.cache.get(key) ?? {});
60
+ }
61
+ async updateCacheAndSaveToFile(data, key) {
62
+ this.cache.set(key, data);
63
+ const targetPath = getOrSetIfNotExists(this.filePaths, key, buildPath(this.storagePath, this.botName, key));
64
+ await writeFile(targetPath, JSON.stringify(data), { flag: 'w+' });
65
+ }
66
+ async load(key) {
67
+ return (this.tryGetFromCache(key) ??
68
+ (await this.lock(key, async () => {
69
+ return await this.loadFromFile(key);
70
+ })));
71
+ }
72
+ async saveMetadata(actions) {
73
+ const targetPath = `${this.storagePath}/${this.botName}/Metadata-${this.botName}.json`;
74
+ await writeFile(targetPath, JSON.stringify(actions), {
75
+ flag: 'w+'
76
+ });
77
+ }
78
+ async getActionState(action, chatId) {
79
+ const value = this.tryGetFromCache(action.key) ??
80
+ (await this.lock(action.key, async () => {
81
+ return await this.loadFromFile(action.key);
82
+ }));
83
+ return Object.assign(action.stateConstructor(), value[chatId]);
84
+ }
85
+ async saveActionExecutionResult(action, chatId, state) {
86
+ await this.lock(action.key, async () => {
87
+ const data = this.tryGetFromCache(action.key) ??
88
+ (await this.loadFromFile(action.key));
89
+ data[chatId] = state;
90
+ if (this.backfillEmptyActionStates(action, data))
91
+ await this.updateCacheAndSaveToFile(data, action.key);
92
+ });
93
+ }
94
+ async close() {
95
+ for (const lock of this.locks.values()) {
96
+ await lock.acquire();
97
+ }
98
+ }
99
+ async updateStateFor(action, chatId, update) {
100
+ await this.lock(action.key, async () => {
101
+ const data = this.tryGetFromCache(action.key) ??
102
+ (await this.loadFromFile(action.key));
103
+ const state = Object.assign(action.stateConstructor(), data[chatId]);
104
+ await update(state);
105
+ if (this.backfillEmptyActionStates(action, data))
106
+ await this.updateCacheAndSaveToFile(data, action.key);
107
+ });
108
+ }
109
+ }
@@ -0,0 +1,11 @@
1
+ import { ILogger, IScopedLogger } from '../types/logger';
2
+ import { TraceId } from '../types/trace';
3
+ export declare class JsonLogger implements ILogger {
4
+ private serializeError;
5
+ private getCircularReplacer;
6
+ createScope(botName: string, traceId: TraceId, chatName: string): IScopedLogger;
7
+ logObjectWithTraceId(botName: string, traceId: TraceId, chatName: string, data: unknown): void;
8
+ logWithTraceId(botName: string, traceId: TraceId, chatName: string, text: string): void;
9
+ errorWithTraceId(botName: string, traceId: TraceId, chatName: string, errorObj: unknown, extraData?: unknown): void;
10
+ }
11
+ //# sourceMappingURL=jsonLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonLogger.d.ts","sourceRoot":"","sources":["../../services/jsonLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,qBAAa,UAAW,YAAW,OAAO;IACtC,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,mBAAmB;IAc3B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAiBtD,aAAa;IAGtB,oBAAoB,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO;IAoBjB,cAAc,CACV,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM;IAOhB,gBAAgB,CACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,OAAO;CAe1B"}
@@ -0,0 +1,66 @@
1
+ export class JsonLogger {
2
+ serializeError(error) {
3
+ if (error instanceof Error) {
4
+ const plainObject = {
5
+ name: error.name,
6
+ message: error.message,
7
+ stack: error.stack
8
+ };
9
+ for (const [key, value] of Object.entries(error)) {
10
+ plainObject[key] = value;
11
+ }
12
+ return JSON.stringify(plainObject);
13
+ }
14
+ return JSON.stringify({ error });
15
+ }
16
+ getCircularReplacer() {
17
+ const cache = new Set();
18
+ return (_, value) => {
19
+ if (typeof value === 'object' && value !== null) {
20
+ if (cache.has(value)) {
21
+ return;
22
+ }
23
+ cache.add(value);
24
+ }
25
+ return value;
26
+ };
27
+ }
28
+ createScope(botName, traceId, chatName) {
29
+ return {
30
+ logObjectWithTraceId: (data) => {
31
+ this.logObjectWithTraceId(botName, traceId, chatName, data);
32
+ },
33
+ logWithTraceId: (text) => {
34
+ this.logWithTraceId(botName, traceId, chatName, text);
35
+ },
36
+ errorWithTraceId: (errorObj, extraData) => {
37
+ this.errorWithTraceId(botName, traceId, chatName, errorObj, extraData);
38
+ }
39
+ };
40
+ }
41
+ logObjectWithTraceId(botName, traceId, chatName, data) {
42
+ const enrichedData = typeof data == 'object'
43
+ ? {
44
+ ...data,
45
+ botName,
46
+ traceId,
47
+ chatName
48
+ }
49
+ : {
50
+ botName,
51
+ traceId,
52
+ chatName,
53
+ data
54
+ };
55
+ console.log(enrichedData);
56
+ }
57
+ logWithTraceId(botName, traceId, chatName, text) {
58
+ console.log(`{"botName":"${botName}","traceId":"${traceId}","chatName":"${chatName}","text":"${text}"}`);
59
+ }
60
+ errorWithTraceId(botName, traceId, chatName, errorObj, extraData) {
61
+ const dataString = extraData
62
+ ? `,"extraData":${JSON.stringify(extraData, this.getCircularReplacer())}`
63
+ : '';
64
+ console.error(`{"botName":"${botName}","traceId":"${traceId}","chatName":"${chatName}","error":${this.serializeError(errorObj)}${dataString}}`);
65
+ }
66
+ }
@@ -0,0 +1,13 @@
1
+ import { TaskRecord } from '../entities/taskRecord';
2
+ import { ILogger } from '../types/logger';
3
+ import { IScheduler } from '../types/scheduler';
4
+ import { Milliseconds } from '../types/timeValues';
5
+ export declare class NodeTimeoutScheduler implements IScheduler {
6
+ private readonly logger;
7
+ readonly activeTasks: TaskRecord[];
8
+ constructor(logger: ILogger);
9
+ stopAll(): void;
10
+ createTask(name: string, action: () => unknown, interval: Milliseconds, executeRightAway: boolean, ownerName: string): void;
11
+ createOnetimeTask(name: string, action: () => unknown, delay: Milliseconds, ownerName: string): void;
12
+ }
13
+ //# sourceMappingURL=nodeTimeoutScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeTimeoutScheduler.d.ts","sourceRoot":"","sources":["../../services/nodeTimeoutScheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,qBAAa,oBAAqB,YAAW,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,QAAQ,CAAC,WAAW,EAAE,UAAU,EAAE,CAAM;gBAE5B,MAAM,EAAE,OAAO;IAI3B,OAAO;IAMP,UAAU,CACN,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,OAAO,EACrB,QAAQ,EAAE,YAAY,EACtB,gBAAgB,EAAE,OAAO,EACzB,SAAS,EAAE,MAAM;IAmBrB,iBAAiB,CACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,OAAO,EACrB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM;CAoBxB"}
@@ -0,0 +1,31 @@
1
+ import { TaskRecord } from '../entities/taskRecord';
2
+ import { createTrace } from '../helpers/traceFactory';
3
+ export class NodeTimeoutScheduler {
4
+ logger;
5
+ activeTasks = [];
6
+ constructor(logger) {
7
+ this.logger = logger;
8
+ }
9
+ stopAll() {
10
+ for (const task of this.activeTasks) {
11
+ clearInterval(task.taskId);
12
+ }
13
+ }
14
+ createTask(name, action, interval, executeRightAway, ownerName) {
15
+ const taskId = setInterval(action, interval);
16
+ const task = new TaskRecord(name, taskId, interval);
17
+ if (executeRightAway) {
18
+ setImmediate(action);
19
+ }
20
+ this.logger.logWithTraceId(ownerName, createTrace(this, ownerName, name), 'System', `Created task ${name}, that will run every ${interval}ms.`);
21
+ this.activeTasks.push(task);
22
+ }
23
+ createOnetimeTask(name, action, delay, ownerName) {
24
+ const actionWrapper = () => {
25
+ this.logger.logWithTraceId(ownerName, createTrace(this, ownerName, name), 'System', `Executing delayed oneshot ${name}`);
26
+ action();
27
+ };
28
+ setTimeout(actionWrapper, delay);
29
+ this.logger.logWithTraceId(ownerName, createTrace(this, ownerName, name), 'System', `Created oneshot task ${name}, that will run in ${delay}ms.`);
30
+ }
31
+ }
@@ -0,0 +1,12 @@
1
+ export type QueueItem = {
2
+ priority: number;
3
+ callback: () => Promise<void>;
4
+ };
5
+ export declare class ResponseProcessingQueue {
6
+ rateLimiter: () => Promise<void>;
7
+ items: QueueItem[];
8
+ isFlushing: boolean;
9
+ enqueue(item: QueueItem): void;
10
+ flushReadyItems(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=responseProcessingQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseProcessingQueue.d.ts","sourceRoot":"","sources":["../../services/responseProcessingQueue.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAAC;AAQF,qBAAa,uBAAuB;IAChC,WAAW,sBAAwD;IACnE,KAAK,EAAE,SAAS,EAAE,CAAM;IACxB,UAAU,UAAS;IAEnB,OAAO,CAAC,IAAI,EAAE,SAAS;IAmBjB,eAAe;CAkBxB"}
@@ -0,0 +1,37 @@
1
+ import { RateLimit } from 'async-sema';
2
+ function notEmpty(arr) {
3
+ return arr.length > 0;
4
+ }
5
+ const TELEGRAM_RATELIMIT_DELAY = 35;
6
+ export class ResponseProcessingQueue {
7
+ rateLimiter = RateLimit(1, { timeUnit: TELEGRAM_RATELIMIT_DELAY });
8
+ items = [];
9
+ isFlushing = false;
10
+ enqueue(item) {
11
+ if (this.items.length === 0 ||
12
+ item.priority >= this.items[this.items.length - 1].priority) {
13
+ this.items.push(item);
14
+ return;
15
+ }
16
+ let insertIndex = this.items.length;
17
+ while (insertIndex > 0 &&
18
+ this.items[insertIndex - 1].priority > item.priority) {
19
+ insertIndex--;
20
+ }
21
+ this.items.splice(insertIndex, 0, item);
22
+ }
23
+ async flushReadyItems() {
24
+ if (this.isFlushing)
25
+ return;
26
+ this.isFlushing = true;
27
+ while (notEmpty(this.items)) {
28
+ if (Date.now() >= this.items[0].priority) {
29
+ await this.rateLimiter();
30
+ const [item] = this.items;
31
+ this.items.shift();
32
+ await item.callback();
33
+ }
34
+ }
35
+ this.isFlushing = false;
36
+ }
37
+ }
@@ -0,0 +1,23 @@
1
+ import { IStorageClient } from '../types/storage';
2
+ import { BotResponse } from '../types/response';
3
+ import { ILogger } from '../types/logger';
4
+ import { IReplyCapture } from '../types/capture';
5
+ import { TraceId } from '../types/trace';
6
+ import { ChatInfo } from '../dtos/chatInfo';
7
+ import { TelegramApiClient } from '../types/externalAliases';
8
+ export declare const TELEGRAM_ERROR_QUOTE_INVALID = "QUOTE_TEXT_INVALID";
9
+ export declare class TelegramApiService {
10
+ private readonly queue;
11
+ private readonly telegram;
12
+ private readonly storage;
13
+ private readonly logger;
14
+ private readonly captureRegistrationCallback;
15
+ private readonly botName;
16
+ constructor(botName: string, telegram: TelegramApiClient, storage: IStorageClient, logger: ILogger, captureRegistrationCallback: (capture: IReplyCapture, parentMessageId: number, chatInfo: ChatInfo, traceId: TraceId) => void);
17
+ enqueueBatchedResponses(responses: BotResponse[]): void;
18
+ flushResponses(): void;
19
+ private pinIfShould;
20
+ private processResponse;
21
+ private sendApiRequest;
22
+ }
23
+ //# sourceMappingURL=telegramApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegramApi.d.ts","sourceRoot":"","sources":["../../services/telegramApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAmB,MAAM,0BAA0B,CAAC;AAE9E,eAAO,MAAM,4BAA4B,uBAAuB,CAAC;AAEjE,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAKlC;IAEV,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAG7B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,OAAO,EACf,2BAA2B,EAAE,CACzB,OAAO,EAAE,aAAa,EACtB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,KACf,IAAI;IASb,uBAAuB,CAAC,SAAS,EAAE,WAAW,EAAE;IAwDhD,cAAc;YAIA,WAAW;YAqBX,eAAe;YAiBf,cAAc;CA6F/B"}