chz-telegram-bot 0.3.9 → 0.3.11

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 (124) hide show
  1. package/builtin/helpAction.ts +1 -1
  2. package/dist/builtin/helpAction.js +1 -1
  3. package/dist/dtos/chatInfo.js +4 -0
  4. package/dist/dtos/commandTriggerCheckResult.js +3 -0
  5. package/dist/dtos/incomingMessage.js +9 -1
  6. package/dist/dtos/incomingQuery.js +5 -0
  7. package/dist/dtos/replyInfo.js +2 -0
  8. package/dist/dtos/responses/delay.js +6 -2
  9. package/dist/dtos/responses/imageMessage.js +10 -4
  10. package/dist/dtos/responses/inlineQueryResponse.js +6 -2
  11. package/dist/dtos/responses/reaction.js +7 -2
  12. package/dist/dtos/responses/textMessage.js +10 -3
  13. package/dist/dtos/responses/unpin.js +6 -2
  14. package/dist/dtos/responses/videoMessage.js +10 -4
  15. package/dist/entities/actions/commandAction.d.ts.map +1 -1
  16. package/dist/entities/actions/commandAction.js +14 -1
  17. package/dist/entities/actions/inlineQueryAction.d.ts.map +1 -1
  18. package/dist/entities/actions/inlineQueryAction.js +8 -1
  19. package/dist/entities/actions/replyCaptureAction.d.ts.map +1 -1
  20. package/dist/entities/actions/replyCaptureAction.js +8 -1
  21. package/dist/entities/actions/scheduledAction.d.ts.map +1 -1
  22. package/dist/entities/actions/scheduledAction.js +13 -14
  23. package/dist/entities/botInstance.js +6 -1
  24. package/dist/entities/cachedStateFactory.js +2 -0
  25. package/dist/entities/context/baseContext.js +14 -2
  26. package/dist/entities/context/chatContext.d.ts +0 -3
  27. package/dist/entities/context/chatContext.d.ts.map +1 -1
  28. package/dist/entities/context/chatContext.js +38 -41
  29. package/dist/entities/context/inlineQueryContext.d.ts +0 -3
  30. package/dist/entities/context/inlineQueryContext.d.ts.map +1 -1
  31. package/dist/entities/context/inlineQueryContext.js +12 -6
  32. package/dist/entities/context/messageContext.d.ts +0 -3
  33. package/dist/entities/context/messageContext.d.ts.map +1 -1
  34. package/dist/entities/context/messageContext.js +77 -68
  35. package/dist/entities/context/replyContext.d.ts +0 -3
  36. package/dist/entities/context/replyContext.d.ts.map +1 -1
  37. package/dist/entities/context/replyContext.js +90 -65
  38. package/dist/entities/states/actionStateBase.js +2 -4
  39. package/dist/entities/taskRecord.js +3 -0
  40. package/dist/helpers/builders/commandActionBuilder.js +10 -8
  41. package/dist/helpers/builders/inlineQueryActionBuilder.js +7 -6
  42. package/dist/helpers/builders/scheduledActionBuilder.js +7 -5
  43. package/dist/helpers/mapUtils.d.ts +3 -0
  44. package/dist/helpers/mapUtils.d.ts.map +1 -0
  45. package/dist/helpers/mapUtils.js +17 -0
  46. package/dist/helpers/noop.d.ts +3 -4
  47. package/dist/helpers/noop.d.ts.map +1 -1
  48. package/dist/helpers/noop.js +2 -1
  49. package/dist/helpers/traceFactory.d.ts +1 -1
  50. package/dist/helpers/traceFactory.d.ts.map +1 -1
  51. package/dist/main.js +1 -3
  52. package/dist/services/actionProcessingService.d.ts.map +1 -1
  53. package/dist/services/actionProcessingService.js +15 -3
  54. package/dist/services/actionProcessors/baseProcessor.d.ts +1 -3
  55. package/dist/services/actionProcessors/baseProcessor.d.ts.map +1 -1
  56. package/dist/services/actionProcessors/baseProcessor.js +6 -2
  57. package/dist/services/actionProcessors/commandActionProcessor.d.ts +0 -4
  58. package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -1
  59. package/dist/services/actionProcessors/commandActionProcessor.js +11 -14
  60. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts +0 -4
  61. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -1
  62. package/dist/services/actionProcessors/inlineQueryActionProcessor.js +5 -7
  63. package/dist/services/actionProcessors/scheduledActionProcessor.js +7 -5
  64. package/dist/services/jsonFileStorage.d.ts +4 -3
  65. package/dist/services/jsonFileStorage.d.ts.map +1 -1
  66. package/dist/services/jsonFileStorage.js +22 -14
  67. package/dist/services/jsonLogger.d.ts +1 -1
  68. package/dist/services/jsonLogger.d.ts.map +1 -1
  69. package/dist/services/jsonLogger.js +9 -3
  70. package/dist/services/nodeTimeoutScheduler.d.ts +2 -2
  71. package/dist/services/nodeTimeoutScheduler.d.ts.map +1 -1
  72. package/dist/services/nodeTimeoutScheduler.js +6 -5
  73. package/dist/services/responseProcessingQueue.d.ts +1 -0
  74. package/dist/services/responseProcessingQueue.d.ts.map +1 -1
  75. package/dist/services/responseProcessingQueue.js +11 -10
  76. package/dist/services/telegramApi.d.ts.map +1 -1
  77. package/dist/services/telegramApi.js +17 -8
  78. package/dist/types/commandTrigger.d.ts +1 -2
  79. package/dist/types/commandTrigger.d.ts.map +1 -1
  80. package/dist/types/handlers.d.ts +1 -1
  81. package/dist/types/handlers.d.ts.map +1 -1
  82. package/dist/types/logger.d.ts +2 -2
  83. package/dist/types/logger.d.ts.map +1 -1
  84. package/dist/types/scheduler.d.ts +2 -2
  85. package/dist/types/scheduler.d.ts.map +1 -1
  86. package/dist/types/storage.d.ts +2 -2
  87. package/dist/types/storage.d.ts.map +1 -1
  88. package/dist/types/timeValues.d.ts +3 -3
  89. package/dist/types/timeValues.d.ts.map +1 -1
  90. package/dist/types/trace.d.ts +1 -1
  91. package/dist/types/trace.d.ts.map +1 -1
  92. package/dtos/incomingMessage.ts +1 -1
  93. package/entities/actions/commandAction.ts +5 -1
  94. package/entities/actions/inlineQueryAction.ts +5 -1
  95. package/entities/actions/replyCaptureAction.ts +5 -1
  96. package/entities/actions/scheduledAction.ts +11 -13
  97. package/entities/botInstance.ts +7 -7
  98. package/entities/context/chatContext.ts +0 -6
  99. package/entities/context/inlineQueryContext.ts +0 -6
  100. package/entities/context/messageContext.ts +0 -6
  101. package/entities/context/replyContext.ts +18 -15
  102. package/eslint.config.js +26 -1
  103. package/helpers/mapUtils.ts +15 -0
  104. package/helpers/noop.ts +4 -4
  105. package/helpers/traceFactory.ts +2 -2
  106. package/package.json +1 -1
  107. package/services/actionProcessingService.ts +8 -4
  108. package/services/actionProcessors/baseProcessor.ts +5 -8
  109. package/services/actionProcessors/commandActionProcessor.ts +6 -18
  110. package/services/actionProcessors/inlineQueryActionProcessor.ts +6 -16
  111. package/services/actionProcessors/scheduledActionProcessor.ts +5 -5
  112. package/services/jsonFileStorage.ts +39 -21
  113. package/services/jsonLogger.ts +12 -8
  114. package/services/nodeTimeoutScheduler.ts +6 -6
  115. package/services/responseProcessingQueue.ts +13 -7
  116. package/services/telegramApi.ts +7 -5
  117. package/tsconfig.json +1 -1
  118. package/types/commandTrigger.ts +1 -3
  119. package/types/handlers.ts +1 -1
  120. package/types/logger.ts +3 -6
  121. package/types/scheduler.ts +2 -2
  122. package/types/storage.ts +2 -2
  123. package/types/timeValues.ts +3 -3
  124. package/types/trace.ts +3 -1
@@ -1,7 +1,7 @@
1
1
  import { Milliseconds } from './timeValues';
2
2
  export interface IScheduler {
3
3
  stopAll(): void;
4
- createTask(name: string, action: () => void, interval: Milliseconds, executeRightAway: boolean, ownerName: string): void;
5
- createOnetimeTask(name: string, action: () => void, delay: Milliseconds, ownerName: string): void;
4
+ createTask(name: string, action: () => unknown, interval: Milliseconds, executeRightAway: boolean, ownerName: string): void;
5
+ createOnetimeTask(name: string, action: () => unknown, delay: Milliseconds, ownerName: string): void;
6
6
  }
7
7
  //# sourceMappingURL=scheduler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../types/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,WAAW,UAAU;IACvB,OAAO,IAAI,IAAI,CAAC;IAEhB,UAAU,CACN,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,IAAI,EAClB,QAAQ,EAAE,YAAY,EACtB,gBAAgB,EAAE,OAAO,EACzB,SAAS,EAAE,MAAM,GAClB,IAAI,CAAC;IAER,iBAAiB,CACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,IAAI,EAClB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAClB,IAAI,CAAC;CACX"}
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../types/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,WAAW,UAAU;IACvB,OAAO,IAAI,IAAI,CAAC;IAEhB,UAAU,CACN,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,OAAO,EACrB,QAAQ,EAAE,YAAY,EACtB,gBAAgB,EAAE,OAAO,EACzB,SAAS,EAAE,MAAM,GAClB,IAAI,CAAC;IAER,iBAAiB,CACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,OAAO,EACrB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAClB,IAAI,CAAC;CACX"}
@@ -1,9 +1,9 @@
1
1
  import { IActionState } from './actionState';
2
2
  import { ActionKey, IActionWithState } from './action';
3
3
  export interface IStorageClient {
4
- updateStateFor<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, update: (state: TActionState) => Promise<void>): Promise<void>;
4
+ updateStateFor<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, update: (state: TActionState) => Promise<void> | void): Promise<void>;
5
5
  close(): Promise<void>;
6
- load<TActionState extends IActionState>(key: ActionKey): Promise<Record<number, TActionState>>;
6
+ load<TActionState extends IActionState>(key: ActionKey): Promise<Record<number, TActionState | undefined>>;
7
7
  saveMetadata<TActionState extends IActionState>(actions: IActionWithState<TActionState>[]): Promise<void>;
8
8
  getActionState<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number): Promise<TActionState>;
9
9
  saveActionExecutionResult<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, state: TActionState): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,YAAY,SAAS,YAAY,EAClC,GAAG,EAAE,SAAS,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACzC,YAAY,CAAC,YAAY,SAAS,YAAY,EAC1C,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,yBAAyB,CAAC,YAAY,SAAS,YAAY,EACvD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACtD,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,YAAY,SAAS,YAAY,EAClC,GAAG,EAAE,SAAS,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC;IACrD,YAAY,CAAC,YAAY,SAAS,YAAY,EAC1C,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,yBAAyB,CAAC,YAAY,SAAS,YAAY,EACvD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
@@ -2,13 +2,13 @@ declare const millisecondsSymbol: unique symbol;
2
2
  declare const secondsSymbol: unique symbol;
3
3
  declare const hoursSymbol: unique symbol;
4
4
  export type Milliseconds = number & {
5
- [millisecondsSymbol]: void;
5
+ [millisecondsSymbol]: never;
6
6
  };
7
7
  export type Seconds = number & {
8
- [secondsSymbol]: void;
8
+ [secondsSymbol]: never;
9
9
  };
10
10
  export type Hours = number & {
11
- [hoursSymbol]: void;
11
+ [hoursSymbol]: never;
12
12
  };
13
13
  export type HoursOfDay = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23;
14
14
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"timeValues.d.ts","sourceRoot":"","sources":["../../types/timeValues.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,kBAAkB,EAAE,OAAO,MAAM,CAAC;AAChD,OAAO,CAAC,MAAM,aAAa,EAAE,OAAO,MAAM,CAAC;AAC3C,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AACnE,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG;IAAE,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,CAAC,WAAW,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAErD,MAAM,MAAM,UAAU,GAChB,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,CAAC"}
1
+ {"version":3,"file":"timeValues.d.ts","sourceRoot":"","sources":["../../types/timeValues.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,kBAAkB,EAAE,OAAO,MAAM,CAAC;AAChD,OAAO,CAAC,MAAM,aAAa,EAAE,OAAO,MAAM,CAAC;AAC3C,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AACpE,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG;IAAE,CAAC,aAAa,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAC1D,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,CAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,UAAU,GAChB,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  declare const traceSymbol: unique symbol;
2
2
  export type TraceId = `${string}:${string}-${string}` & {
3
- [traceSymbol]: void;
3
+ [traceSymbol]: never;
4
4
  };
5
5
  export {};
6
6
  //# sourceMappingURL=trace.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../types/trace.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAEzC,MAAM,MAAM,OAAO,GAAG,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,GAAG;IAAE,CAAC,WAAW,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../types/trace.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAEzC,MAAM,MAAM,OAAO,GAAG,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,GAAG;IACpD,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;CACxB,CAAC"}
@@ -61,7 +61,7 @@ export class IncomingMessage {
61
61
  this.chatInfo = new ChatInfo(
62
62
  ctxMessage.chat.id,
63
63
  'title' in ctxMessage.chat
64
- ? ctxMessage.chat.title + ' ' + ctxMessage.chat.id
64
+ ? `${ctxMessage.chat.title} ${ctxMessage.chat.id}`
65
65
  : 'DM'
66
66
  );
67
67
  this.type = this.detectMessageType(ctxMessage);
@@ -149,13 +149,17 @@ export class CommandAction<TActionState extends IActionState>
149
149
 
150
150
  const execResult = trigger.exec(ctx.messageText);
151
151
  if (execResult != null) {
152
+ let regexMatchLimit = 100;
152
153
  matchResults.push(execResult);
153
154
 
154
155
  if (trigger.global) {
155
- while (true) {
156
+ while (regexMatchLimit > 0) {
156
157
  const nextResult = trigger.exec(ctx.messageText);
158
+
157
159
  if (nextResult == null) break;
160
+
158
161
  matchResults.push(nextResult);
162
+ regexMatchLimit -= 1;
159
163
  }
160
164
  }
161
165
  }
@@ -38,13 +38,17 @@ export class InlineQueryAction implements IAction {
38
38
 
39
39
  const execResult = this.pattern.exec(ctx.queryText);
40
40
  if (execResult != null) {
41
+ let regexMatchLimit = 100;
41
42
  matchResults.push(execResult);
42
43
 
43
44
  if (this.pattern.global) {
44
- while (true) {
45
+ while (regexMatchLimit > 0) {
45
46
  const nextResult = this.pattern.exec(ctx.queryText);
47
+
46
48
  if (nextResult == null) break;
49
+
47
50
  matchResults.push(nextResult);
51
+ regexMatchLimit -= 1;
48
52
  }
49
53
  }
50
54
  }
@@ -81,13 +81,17 @@ export class ReplyCaptureAction<TParentActionState extends IActionState>
81
81
 
82
82
  const execResult = trigger.exec(ctx.messageText);
83
83
  if (execResult != null) {
84
+ let regexMatchLimit = 100;
84
85
  matchResults.push(execResult);
85
86
 
86
87
  if (trigger.global) {
87
- while (true) {
88
+ while (regexMatchLimit > 0) {
88
89
  const nextResult = trigger.exec(ctx.messageText);
90
+
89
91
  if (nextResult == null) break;
92
+
90
93
  matchResults.push(nextResult);
94
+ regexMatchLimit -= 1;
91
95
  }
92
96
  }
93
97
  }
@@ -9,6 +9,7 @@ import { CachedStateFactory } from '../cachedStateFactory';
9
9
  import { ChatContext } from '../context/chatContext';
10
10
  import { Noop } from '../../helpers/noop';
11
11
  import { IScheduler } from '../../types/scheduler';
12
+ import { getOrSetIfNotExists, getOrThrow } from '../../helpers/mapUtils';
12
13
 
13
14
  export class ScheduledAction<TActionState extends IActionState>
14
15
  implements IActionWithState<TActionState>
@@ -89,20 +90,18 @@ export class ScheduledAction<TActionState extends IActionState>
89
90
  botName: string,
90
91
  scheduler: IScheduler
91
92
  ): Promise<TResult> {
92
- if (!this.cachedStateFactories.has(key)) {
93
- throw new Error(
94
- `No shared cache was set up for the key [${key}] in action '${this.name}'`
95
- );
96
- }
93
+ const cachedItemFactory = getOrThrow(
94
+ this.cachedStateFactories,
95
+ key,
96
+ `No shared cache was set up for the key [${key}] in action '${this.name}'`
97
+ );
97
98
 
98
99
  const semaphoreKey = `${this.key}_cached:${key}`;
99
- let semaphore: Semaphore;
100
- if (ScheduledAction.locks.has(semaphoreKey)) {
101
- semaphore = ScheduledAction.locks.get(semaphoreKey)!;
102
- } else {
103
- semaphore = new Semaphore(1);
104
- ScheduledAction.locks.set(semaphoreKey, semaphore);
105
- }
100
+ const semaphore = getOrSetIfNotExists(
101
+ ScheduledAction.locks,
102
+ semaphoreKey,
103
+ new Semaphore(1)
104
+ );
106
105
 
107
106
  await semaphore.acquire();
108
107
 
@@ -111,7 +110,6 @@ export class ScheduledAction<TActionState extends IActionState>
111
110
  return this.cachedState.get(key) as TResult;
112
111
  }
113
112
 
114
- const cachedItemFactory = this.cachedStateFactories.get(key)!;
115
113
  const value = await cachedItemFactory.getValue();
116
114
 
117
115
  this.cachedState.set(key, value);
@@ -68,19 +68,19 @@ export class BotInstance {
68
68
  scheduledPeriod?: Seconds,
69
69
  verboseLoggingForIncomingMessage?: boolean
70
70
  ) {
71
- this.actionProcessingService.initialize(
72
- token,
73
- actions,
74
- scheduledPeriod,
75
- verboseLoggingForIncomingMessage
76
- );
77
-
78
71
  this.logger.logWithTraceId(
79
72
  this.name,
80
73
  createTrace(this, this.name, 'Start'),
81
74
  'System',
82
75
  'Starting bot...'
83
76
  );
77
+
78
+ await this.actionProcessingService.initialize(
79
+ token,
80
+ actions,
81
+ scheduledPeriod,
82
+ verboseLoggingForIncomingMessage
83
+ );
84
84
  }
85
85
 
86
86
  async stop(code: string) {
@@ -1,5 +1,4 @@
1
1
  import { resolve } from 'path';
2
- import { IStorageClient } from '../../types/storage';
3
2
  import { ImageMessage } from '../../dtos/responses/imageMessage';
4
3
  import { TextMessage } from '../../dtos/responses/textMessage';
5
4
  import { VideoMessage } from '../../dtos/responses/videoMessage';
@@ -13,7 +12,6 @@ import { IActionState } from '../../types/actionState';
13
12
  import { IReplyResponse } from '../../types/response';
14
13
  import { Milliseconds } from '../../types/timeValues';
15
14
  import { DelayResponse } from '../../dtos/responses/delay';
16
- import { IScheduler } from '../../types/scheduler';
17
15
  import { ICaptureController } from '../../types/capture';
18
16
  import { CommandTrigger } from '../../types/commandTrigger';
19
17
  import { ReplyContext } from './replyContext';
@@ -27,10 +25,6 @@ export class ChatContext<
27
25
  TActionState extends IActionState,
28
26
  TAction extends IActionWithState<TActionState> = ScheduledAction<TActionState>
29
27
  > extends BaseContext<TAction> {
30
- constructor(storage: IStorageClient, scheduler: IScheduler) {
31
- super(storage, scheduler);
32
- }
33
-
34
28
  protected createCaptureController(
35
29
  response: IReplyResponse
36
30
  ): ICaptureController {
@@ -1,7 +1,5 @@
1
1
  import { InlineQueryResult } from 'telegraf/types';
2
2
  import { BotResponse } from '../../types/response';
3
- import { IScheduler } from '../../types/scheduler';
4
- import { IStorageClient } from '../../types/storage';
5
3
  import { InlineQueryAction } from '../actions/inlineQueryAction';
6
4
  import { InlineQueryResponse } from '../../dtos/responses/inlineQueryResponse';
7
5
  import { BaseContext } from './baseContext';
@@ -32,10 +30,6 @@ export class InlineQueryContext extends BaseContext<InlineQueryAction> {
32
30
  /** Collection of Regexp match results on a message that triggered this action. Will be empty if trigger is not a Regexp. */
33
31
  matchResults: RegExpMatchArray[] = [];
34
32
 
35
- constructor(storage: IStorageClient, scheduler: IScheduler) {
36
- super(storage, scheduler);
37
- }
38
-
39
33
  /**
40
34
  * This result will be shown to user as a response to inline query.
41
35
  * @param queryResult Inline query result to be shown to user.
@@ -1,6 +1,5 @@
1
1
  import { resolve } from 'path';
2
2
  import { TelegramEmoji } from 'telegraf/types';
3
- import { IStorageClient } from '../../types/storage';
4
3
  import { IActionState } from '../../types/actionState';
5
4
  import { ImageMessage } from '../../dtos/responses/imageMessage';
6
5
  import { Reaction } from '../../dtos/responses/reaction';
@@ -15,7 +14,6 @@ import {
15
14
  MessageTypeValue,
16
15
  TelegrafContextMessage
17
16
  } from '../../types/messageTypes';
18
- import { IScheduler } from '../../types/scheduler';
19
17
  import { ReplyInfo } from '../../dtos/replyInfo';
20
18
  import { CommandAction } from '../actions/commandAction';
21
19
 
@@ -42,10 +40,6 @@ export class MessageContext<
42
40
  /** Message object recieved from Telegram */
43
41
  messageUpdateObject!: TelegrafContextMessage;
44
42
 
45
- constructor(storage: IStorageClient, scheduler: IScheduler) {
46
- super(storage, scheduler);
47
- }
48
-
49
43
  private getQuotePart(quote: boolean | string) {
50
44
  return typeof quote == 'boolean'
51
45
  ? this.matchResults.length != 0
@@ -13,8 +13,6 @@ import {
13
13
  MessageTypeValue,
14
14
  TelegrafContextMessage
15
15
  } from '../../types/messageTypes';
16
- import { IScheduler } from '../../types/scheduler';
17
- import { IStorageClient } from '../../types/storage';
18
16
  import { ReplyCaptureAction } from '../actions/replyCaptureAction';
19
17
  import { resolve } from 'path';
20
18
  import { BaseContext } from './baseContext';
@@ -41,10 +39,6 @@ export class ReplyContext<
41
39
 
42
40
  isInitialized = false;
43
41
 
44
- constructor(storage: IStorageClient, scheduler: IScheduler) {
45
- super(storage, scheduler);
46
- }
47
-
48
42
  private getQuotePart(quote: boolean | string) {
49
43
  return typeof quote == 'boolean'
50
44
  ? this.matchResults.length != 0
@@ -136,7 +130,9 @@ export class ReplyContext<
136
130
  text: string,
137
131
  quote?: string,
138
132
  options?: TextMessageSendingOptions
139
- ) => this.replyWithText(text, quote ?? true, options),
133
+ ) => {
134
+ this.replyWithText(text, quote ?? true, options);
135
+ },
140
136
  /**
141
137
  * Reply with image message to message that triggered this action after action execution is finished.
142
138
  * If multiple responses are sent, they will be sent in the order they were added, with delay of at least 35ms as per Telegram rate-limit.
@@ -147,7 +143,9 @@ export class ReplyContext<
147
143
  name: string,
148
144
  quote?: string,
149
145
  options?: MessageSendingOptions
150
- ) => this.replyWithImage(name, quote ?? true, options),
146
+ ) => {
147
+ this.replyWithImage(name, quote ?? true, options);
148
+ },
151
149
 
152
150
  /**
153
151
  * Reply with video/gif message to message that triggered this action after action execution is finished.
@@ -159,7 +157,9 @@ export class ReplyContext<
159
157
  name: string,
160
158
  quote?: string,
161
159
  options?: MessageSendingOptions
162
- ) => this.replyWithVideo(name, quote ?? true, options)
160
+ ) => {
161
+ this.replyWithVideo(name, quote ?? true, options);
162
+ }
163
163
  },
164
164
 
165
165
  /**
@@ -168,16 +168,18 @@ export class ReplyContext<
168
168
  * @param text Message contents.
169
169
  * @param options Message sending option.
170
170
  */
171
- withText: (text: string, options?: TextMessageSendingOptions) =>
172
- this.replyWithText(text, false, options),
171
+ withText: (text: string, options?: TextMessageSendingOptions) => {
172
+ this.replyWithText(text, false, options);
173
+ },
173
174
  /**
174
175
  * Reply with image message to message that triggered this action after action execution is finished.
175
176
  * If multiple responses are sent, they will be sent in the order they were added, with delay of at least 35ms as per Telegram rate-limit.
176
177
  * @param text Message contents.
177
178
  * @param options Message sending option.
178
179
  */
179
- withImage: (name: string, options?: MessageSendingOptions) =>
180
- this.replyWithImage(name, false, options),
180
+ withImage: (name: string, options?: MessageSendingOptions) => {
181
+ this.replyWithImage(name, false, options);
182
+ },
181
183
 
182
184
  /**
183
185
  * Reply with video/gif message to message that triggered this action after action execution is finished.
@@ -185,8 +187,9 @@ export class ReplyContext<
185
187
  * @param text Message contents.
186
188
  * @param options Message sending option.
187
189
  */
188
- withVideo: (name: string, options?: MessageSendingOptions) =>
189
- this.replyWithVideo(name, false, options),
190
+ withVideo: (name: string, options?: MessageSendingOptions) => {
191
+ this.replyWithVideo(name, false, options);
192
+ },
190
193
 
191
194
  /**
192
195
  * React to the message that triggered this action after action execution is finished.
package/eslint.config.js CHANGED
@@ -3,8 +3,14 @@ import tseslint from 'typescript-eslint';
3
3
 
4
4
  export default tseslint.config(
5
5
  eslint.configs.recommended,
6
- ...tseslint.configs.recommended,
6
+ ...tseslint.configs.strictTypeChecked,
7
7
  {
8
+ languageOptions: {
9
+ parserOptions: {
10
+ project: './tsconfig.json',
11
+ sourceType: 'module'
12
+ }
13
+ },
8
14
  rules: {
9
15
  '@typescript-eslint/no-unused-vars': [
10
16
  'error',
@@ -17,6 +23,25 @@ export default tseslint.config(
17
23
  varsIgnorePattern: '^_',
18
24
  ignoreRestSiblings: true
19
25
  }
26
+ ],
27
+ '@typescript-eslint/no-misused-promises': [
28
+ 'error',
29
+ {
30
+ checksVoidReturn: true,
31
+ checksConditionals: true
32
+ }
33
+ ],
34
+ '@typescript-eslint/restrict-template-expressions': [
35
+ 'error',
36
+ {
37
+ allowNumber: true
38
+ }
39
+ ],
40
+ '@typescript-eslint/unbound-method': [
41
+ 'error',
42
+ {
43
+ ignoreStatic: true
44
+ }
20
45
  ]
21
46
  },
22
47
  ignores: ['dist/*']
@@ -0,0 +1,15 @@
1
+ export function getOrSetIfNotExists<K, V>(map: Map<K, V>, key: K, fallback: V) {
2
+ const existingValue = map.get(key);
3
+ if (existingValue) return existingValue;
4
+
5
+ map.set(key, fallback);
6
+
7
+ return fallback;
8
+ }
9
+
10
+ export function getOrThrow<K, V>(map: Map<K, V>, key: K, error: string) {
11
+ const existingValue = map.get(key);
12
+ if (existingValue) return existingValue;
13
+
14
+ throw new Error(error);
15
+ }
package/helpers/noop.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { BotResponse } from '../types/response';
2
2
 
3
3
  /* eslint-disable @typescript-eslint/no-unused-vars */
4
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
4
5
  export class Noop {
5
6
  static NoResponse: BotResponse[] = [];
6
- static true<T1>(arg1: T1) {
7
+ static true(arg1: unknown) {
7
8
  return true;
8
9
  }
9
- static false<T1>(arg1: T1) {
10
+ static false(arg1: unknown) {
10
11
  return false;
11
12
  }
12
13
 
13
- static async call<T1>(arg1: T1): Promise<void>;
14
- static async call<T1, T2>(arg1: T1, arg2: T2): Promise<void>;
14
+ static async call(arg1: unknown): Promise<void>;
15
15
  static async call(arg1: unknown, arg2?: unknown) {}
16
16
  }
@@ -1,7 +1,7 @@
1
1
  import { TraceId } from '../types/trace';
2
2
 
3
- export function createTrace<T extends object>(
4
- traceOwner: T | string,
3
+ export function createTrace(
4
+ traceOwner: object | string,
5
5
  botName: string,
6
6
  traceName: string
7
7
  ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chz-telegram-bot",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "async-sema": "^3.1.1",
@@ -75,13 +75,14 @@ export class ActionProcessingService {
75
75
  this.telegraf.telegram,
76
76
  this.storage,
77
77
  this.logger,
78
- (capture, id, chatInfo, traceId) =>
78
+ (capture, id, chatInfo, traceId) => {
79
79
  this.commandProcessor.captureRegistrationCallback(
80
80
  capture,
81
81
  id,
82
82
  chatInfo,
83
83
  traceId
84
- )
84
+ );
85
+ }
85
86
  );
86
87
 
87
88
  const botInfo = await this.telegraf.telegram.getMe();
@@ -116,9 +117,12 @@ export class ActionProcessingService {
116
117
  scheduledPeriod ?? hoursToSeconds(1 as Hours)
117
118
  );
118
119
 
119
- this.storage.saveMetadata([...actions.scheduled, ...commandActions]);
120
+ void this.storage.saveMetadata([
121
+ ...actions.scheduled,
122
+ ...commandActions
123
+ ]);
120
124
 
121
- this.telegraf.launch();
125
+ void this.telegraf.launch();
122
126
  }
123
127
 
124
128
  stop(code: string) {
@@ -1,4 +1,3 @@
1
- import { Telegraf } from 'telegraf';
2
1
  import { ILogger } from '../../types/logger';
3
2
  import { IScheduler } from '../../types/scheduler';
4
3
  import { IStorageClient } from '../../types/storage';
@@ -14,7 +13,6 @@ export abstract class BaseActionProcessor {
14
13
  protected readonly botName: string;
15
14
 
16
15
  protected api!: TelegramApiService;
17
- protected telegraf!: Telegraf;
18
16
 
19
17
  constructor(
20
18
  botName: string,
@@ -29,16 +27,15 @@ export abstract class BaseActionProcessor {
29
27
  this.botName = botName;
30
28
  }
31
29
 
32
- private defaultErrorHandler<
33
- TAction extends IAction,
34
- TActionContext extends BaseContext<TAction>
35
- >(error: Error, ctx: TActionContext) {
30
+ private defaultErrorHandler<TAction extends IAction>(
31
+ error: Error,
32
+ ctx: BaseContext<TAction>
33
+ ) {
36
34
  ctx.logger.errorWithTraceId(error, ctx);
37
35
  }
38
36
 
39
- initializeDependencies(api: TelegramApiService, telegraf: Telegraf) {
37
+ initializeDependencies(api: TelegramApiService) {
40
38
  this.api = api;
41
- this.telegraf = telegraf;
42
39
  }
43
40
 
44
41
  async executeAction<
@@ -5,9 +5,6 @@ import { ReplyCaptureAction } from '../../entities/actions/replyCaptureAction';
5
5
  import { MessageContext } from '../../entities/context/messageContext';
6
6
  import { ReplyContext } from '../../entities/context/replyContext';
7
7
  import { IActionState } from '../../types/actionState';
8
- import { ILogger } from '../../types/logger';
9
- import { IScheduler } from '../../types/scheduler';
10
- import { IStorageClient } from '../../types/storage';
11
8
  import { TelegramApiService } from '../telegramApi';
12
9
  import { IReplyCapture } from '../../types/capture';
13
10
  import { TraceId } from '../../types/trace';
@@ -29,22 +26,13 @@ export class CommandActionProcessor extends BaseActionProcessor {
29
26
  ])
30
27
  );
31
28
 
32
- constructor(
33
- botName: string,
34
- storage: IStorageClient,
35
- scheduler: IScheduler,
36
- logger: ILogger
37
- ) {
38
- super(botName, storage, scheduler, logger);
39
- }
40
-
41
29
  initialize(
42
30
  api: TelegramApiService,
43
31
  telegraf: Telegraf,
44
32
  commands: CommandAction<IActionState>[],
45
33
  verboseLoggingForIncomingMessage: boolean
46
34
  ) {
47
- this.initializeDependencies(api, telegraf);
35
+ this.initializeDependencies(api);
48
36
 
49
37
  for (const msgType of Object.values(MessageType)) {
50
38
  if (msgType == MessageType.Text) {
@@ -72,7 +60,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
72
60
  }
73
61
 
74
62
  if (commands.length > 0) {
75
- this.telegraf.on('message', async (ctx) => {
63
+ telegraf.on('message', async (ctx) => {
76
64
  const msg = new IncomingMessage(
77
65
  ctx.update.message,
78
66
  this.botName
@@ -149,7 +137,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
149
137
 
150
138
  for (const commandAction of commandsToCheck) {
151
139
  this.initializeMessageContext(ctx, commandAction, msg);
152
- this.executeAction(commandAction, ctx);
140
+ await this.executeAction(commandAction, ctx);
153
141
  }
154
142
 
155
143
  if (this.replyCaptures.length != 0) {
@@ -160,7 +148,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
160
148
 
161
149
  for (const replyAction of this.replyCaptures) {
162
150
  this.initializeReplyCaptureContext(replyCtx, replyAction, msg);
163
- this.executeAction(replyAction, replyCtx);
151
+ await this.executeAction(replyAction, replyCtx);
164
152
  }
165
153
  }
166
154
 
@@ -174,7 +162,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
174
162
  ) {
175
163
  ctx.replyMessageId = message.replyToMessageId;
176
164
  ctx.messageId = message.messageId;
177
- ctx.messageText = message.text ?? '';
165
+ ctx.messageText = message.text;
178
166
  ctx.messageType = message.type;
179
167
  ctx.fromUserId = message.from?.id;
180
168
  ctx.fromUserName =
@@ -202,7 +190,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
202
190
  message: IncomingMessage
203
191
  ) {
204
192
  ctx.messageId = message.messageId;
205
- ctx.messageText = message.text ?? '';
193
+ ctx.messageText = message.text;
206
194
  ctx.messageType = message.type;
207
195
  ctx.fromUserId = message.from?.id;
208
196
  ctx.fromUserName =