chz-telegram-bot 0.0.47 → 0.0.48

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 (32) hide show
  1. package/dist/entities/actions/commandAction.d.ts +1 -1
  2. package/dist/entities/actions/commandAction.d.ts.map +1 -1
  3. package/dist/entities/actions/commandAction.js +6 -4
  4. package/dist/entities/actions/scheduledAction.d.ts +1 -1
  5. package/dist/entities/actions/scheduledAction.d.ts.map +1 -1
  6. package/dist/entities/actions/scheduledAction.js +4 -2
  7. package/dist/entities/botInstance.d.ts.map +1 -1
  8. package/dist/entities/botInstance.js +4 -2
  9. package/dist/entities/context/chatContext.d.ts +18 -7
  10. package/dist/entities/context/chatContext.d.ts.map +1 -1
  11. package/dist/entities/context/chatContext.js +24 -10
  12. package/dist/entities/context/messageContext.d.ts +9 -6
  13. package/dist/entities/context/messageContext.d.ts.map +1 -1
  14. package/dist/entities/context/messageContext.js +14 -10
  15. package/dist/entities/responses/delay.d.ts +13 -0
  16. package/dist/entities/responses/delay.d.ts.map +1 -0
  17. package/dist/entities/responses/delay.js +14 -0
  18. package/dist/services/telegramApi.d.ts +1 -12
  19. package/dist/services/telegramApi.d.ts.map +1 -1
  20. package/dist/services/telegramApi.js +7 -10
  21. package/dist/types/response.d.ts +3 -1
  22. package/dist/types/response.d.ts.map +1 -1
  23. package/dist/types/response.js +2 -1
  24. package/entities/actions/commandAction.ts +5 -3
  25. package/entities/actions/scheduledAction.ts +4 -1
  26. package/entities/botInstance.ts +4 -2
  27. package/entities/context/chatContext.ts +28 -12
  28. package/entities/context/messageContext.ts +12 -12
  29. package/entities/responses/delay.ts +25 -0
  30. package/package.json +1 -1
  31. package/services/telegramApi.ts +5 -23
  32. package/types/response.ts +4 -1
@@ -17,7 +17,7 @@ export declare class CommandAction<TActionState extends IActionState> implements
17
17
  stateConstructor: () => TActionState;
18
18
  key: ActionKey;
19
19
  constructor(trigger: CommandTrigger | CommandTrigger[], handler: CommandHandler<TActionState>, name: string, active: boolean, cooldown: Seconds, chatsBlacklist: number[], allowedUsers: number[], condition: CommandCondition<TActionState>, stateConstructor: () => TActionState);
20
- exec(ctx: MessageContext<TActionState>): Promise<void>;
20
+ exec(ctx: MessageContext<TActionState>): Promise<import("../../types/response").BotResponse[]>;
21
21
  private checkTrigger;
22
22
  }
23
23
  //# sourceMappingURL=commandAction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commandAction.d.ts","sourceRoot":"","sources":["../../../entities/actions/commandAction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE1E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,qBAAa,aAAa,CAAC,YAAY,SAAS,YAAY,CACxD,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAEzC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC1C,gBAAgB,EAAE,MAAM,YAAY,CAAC;IACrC,GAAG,EAAE,SAAS,CAAC;gBAGX,OAAO,EAAE,cAAc,GAAG,cAAc,EAAE,EAC1C,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,EACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,OAAO,EACjB,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACzC,gBAAgB,EAAE,MAAM,YAAY;IAelC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,YAAY,CAAC;IAkD5C,OAAO,CAAC,YAAY;CAwDvB"}
1
+ {"version":3,"file":"commandAction.d.ts","sourceRoot":"","sources":["../../../entities/actions/commandAction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE1E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,qBAAa,aAAa,CAAC,YAAY,SAAS,YAAY,CACxD,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAEzC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC1C,gBAAgB,EAAE,MAAM,YAAY,CAAC;IACrC,GAAG,EAAE,SAAS,CAAC;gBAGX,OAAO,EAAE,cAAc,GAAG,cAAc,EAAE,EAC1C,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,EACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,OAAO,EACjB,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACzC,gBAAgB,EAAE,MAAM,YAAY;IAelC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,YAAY,CAAC;IAyD5C,OAAO,CAAC,YAAY;CAwDvB"}
@@ -25,18 +25,18 @@ class CommandAction {
25
25
  }
26
26
  async exec(ctx) {
27
27
  if (!ctx.isInitialized)
28
- throw new Error('Context is not initialized');
28
+ throw new Error(`Context for ${this.key} is not initialized or already consumed`);
29
29
  if (!this.active || this.chatsBlacklist.includes(ctx.chatId))
30
- return;
30
+ return [];
31
31
  const isConditionMet = await this.condition(ctx);
32
32
  if (!isConditionMet)
33
- return;
33
+ return [];
34
34
  const state = await ctx.storage.getActionState(this, ctx.chatId);
35
35
  const { shouldTrigger, matchResults, skipCooldown } = this.triggers
36
36
  .map((x) => this.checkTrigger(ctx, x, state))
37
37
  .reduce((acc, curr) => acc.mergeWith(curr), commandTriggerCheckResult_1.CommandTriggerCheckResult.DoNotTrigger);
38
38
  if (!shouldTrigger)
39
- return;
39
+ return [];
40
40
  logger_1.Logger.logWithTraceId(ctx.botName, ctx.traceId, ctx.chatName, ` - Executing [${this.name}] in ${ctx.chatId}`);
41
41
  ctx.matchResults = matchResults;
42
42
  await this.handler(ctx, state);
@@ -48,6 +48,8 @@ class CommandAction {
48
48
  }
49
49
  ctx.updateActions.forEach((action) => action(state));
50
50
  await ctx.storage.saveActionExecutionResult(this, ctx.chatId, new actionExecutionResult_1.ActionExecutionResult(state, ctx.startCooldown && shouldTrigger));
51
+ ctx.isInitialized = false;
52
+ return ctx.responses;
51
53
  }
52
54
  checkTrigger(ctx, trigger, state) {
53
55
  let shouldTrigger = false;
@@ -17,7 +17,7 @@ export declare class ScheduledAction<TActionState extends IActionState> implemen
17
17
  cachedStateFactories: Map<string, CachedStateFactory>;
18
18
  handler: ScheduledHandler<TActionState>;
19
19
  constructor(name: string, handler: ScheduledHandler<TActionState>, timeinHours: HoursOfDay, active: boolean, whitelist: number[], cachedStateFactories: Map<string, CachedStateFactory>, stateConstructor: () => TActionState);
20
- exec(ctx: ChatContext<TActionState>): Promise<void>;
20
+ exec(ctx: ChatContext<TActionState>): Promise<import("../../types/response").BotResponse[]>;
21
21
  private getCachedValue;
22
22
  private shouldTrigger;
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scheduledAction.d.ts","sourceRoot":"","sources":["../../../entities/actions/scheduledAction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAKrD,qBAAa,eAAe,CAAC,YAAY,SAAS,YAAY,CAC1D,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAEzC,MAAM,CAAC,KAAK,yBAAgC;IAE5C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,GAAG,EAAE,SAAS,CAAC;IAEf,WAAW,uBAA8B;IACzC,gBAAgB,EAAE,MAAM,YAAY,CAAC;IACrC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACtD,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBAGpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACvC,WAAW,EAAE,UAAU,EACvB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACrD,gBAAgB,EAAE,MAAM,YAAY;IAYlC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,YAAY,CAAC;YAqC3B,cAAc;IA8C5B,OAAO,CAAC,aAAa;CAaxB"}
1
+ {"version":3,"file":"scheduledAction.d.ts","sourceRoot":"","sources":["../../../entities/actions/scheduledAction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAKrD,qBAAa,eAAe,CAAC,YAAY,SAAS,YAAY,CAC1D,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAEzC,MAAM,CAAC,KAAK,yBAAgC;IAE5C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,GAAG,EAAE,SAAS,CAAC;IAEf,WAAW,uBAA8B;IACzC,gBAAgB,EAAE,MAAM,YAAY,CAAC;IACrC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACtD,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBAGpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACvC,WAAW,EAAE,UAAU,EACvB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACrD,gBAAgB,EAAE,MAAM,YAAY;IAYlC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,YAAY,CAAC;YA6C3B,cAAc;IA8C5B,OAAO,CAAC,aAAa;CAaxB"}
@@ -24,9 +24,9 @@ class ScheduledAction {
24
24
  }
25
25
  async exec(ctx) {
26
26
  if (!ctx.isInitialized)
27
- throw new Error('Context is not initialized');
27
+ throw new Error(`Context for ${this.key} is not initialized or already consumed`);
28
28
  if (!this.active || !this.chatsWhitelist.includes(ctx.chatId))
29
- return;
29
+ return [];
30
30
  const state = await ctx.storage.getActionState(this, ctx.chatId);
31
31
  const isAllowedToTrigger = this.shouldTrigger(state);
32
32
  if (isAllowedToTrigger) {
@@ -36,6 +36,8 @@ class ScheduledAction {
36
36
  ctx.updateActions.forEach((action) => action(state));
37
37
  await ctx.storage.saveActionExecutionResult(this, ctx.chatId, new actionExecutionResult_1.ActionExecutionResult(state, isAllowedToTrigger));
38
38
  }
39
+ ctx.isInitialized = false;
40
+ return ctx.responses;
39
41
  }
40
42
  async getCachedValue(key, botName) {
41
43
  if (!this.cachedStateFactories.has(key)) {
@@ -1 +1 @@
1
- {"version":3,"file":"botInstance.d.ts","sourceRoot":"","sources":["../../entities/botInstance.ts"],"names":[],"mappings":"AAKA,OAAO,EAAuB,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAQ5D,qBAAa,WAAW;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,EAAE,cAAc,CAAC;gBAEZ,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,aAAa,CAAC,EAAE,cAAc,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,gCAAgC,CAAC,EAAE,OAAO,CAAC;KAC9C;IAqCD,OAAO,CAAC,6BAA6B;IA2CrC,OAAO,CAAC,2BAA2B;IAiC7B,IAAI,CAAC,IAAI,EAAE,MAAM;YAYT,YAAY;YAwBZ,cAAc;CAqB/B"}
1
+ {"version":3,"file":"botInstance.d.ts","sourceRoot":"","sources":["../../entities/botInstance.ts"],"names":[],"mappings":"AAKA,OAAO,EAAuB,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAQ5D,qBAAa,WAAW;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,EAAE,cAAc,CAAC;gBAEZ,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,aAAa,CAAC,EAAE,cAAc,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,gCAAgC,CAAC,EAAE,OAAO,CAAC;KAC9C;IAqCD,OAAO,CAAC,6BAA6B;IA2CrC,OAAO,CAAC,2BAA2B;IAiC7B,IAAI,CAAC,IAAI,EAAE,MAAM;YAYT,YAAY;YAyBZ,cAAc;CAsB/B"}
@@ -81,7 +81,8 @@ class BotInstance {
81
81
  for (const scheduledAction of this.scheduled) {
82
82
  this.api.initializeContextForChat(ctx, chatId, scheduledAction);
83
83
  try {
84
- await scheduledAction.exec(ctx);
84
+ const responses = await scheduledAction.exec(ctx);
85
+ this.api.enqueueBatchedResponses(responses);
85
86
  }
86
87
  catch (error) {
87
88
  logger_1.Logger.errorWithTraceId(ctx.botName, ctx.traceId, chatName, error, ctx);
@@ -95,7 +96,8 @@ class BotInstance {
95
96
  for (const commandAction of this.commands) {
96
97
  this.api.initializeContextForMessage(ctx, msg, commandAction);
97
98
  try {
98
- await commandAction.exec(ctx);
99
+ const responses = await commandAction.exec(ctx);
100
+ this.api.enqueueBatchedResponses(responses);
99
101
  }
100
102
  catch (error) {
101
103
  logger_1.Logger.errorWithTraceId(ctx.botName, ctx.traceId, ctx.chatName, error, ctx);
@@ -1,14 +1,14 @@
1
- import { IBotApiInteractions } from '../../services/telegramApi';
2
1
  import { IStorageClient } from '../../types/storage';
3
2
  import { MessageSendingOptions, TextMessageSendingOptions } from '../../types/messageSendingOptions';
4
3
  import { IActionWithState } from '../../types/actionWithState';
5
4
  import { IActionState } from '../../types/actionState';
5
+ import { BotResponse } from '../../types/response';
6
+ import { Milliseconds } from '../../types/timeValues';
6
7
  /**
7
8
  * Context of action executed in chat.
8
9
  */
9
10
  export declare class ChatContext<TActionState extends IActionState> {
10
11
  protected action: IActionWithState<TActionState>;
11
- protected interactions: IBotApiInteractions;
12
12
  updateActions: Array<(state: TActionState) => void>;
13
13
  /** Trace id of a action execution. */
14
14
  traceId: number | string;
@@ -20,36 +20,47 @@ export declare class ChatContext<TActionState extends IActionState> {
20
20
  chatName: string;
21
21
  /** Storage client instance for this bot. */
22
22
  storage: IStorageClient;
23
+ /** Ordered collection of responses to be processed */
24
+ responses: BotResponse[];
23
25
  isInitialized: boolean;
24
26
  constructor();
25
- initializeChatContext(botName: string, action: IActionWithState<TActionState>, interactions: IBotApiInteractions, chatId: number, chatName: string, traceId: number | string, storage: IStorageClient): this;
27
+ initializeChatContext(botName: string, action: IActionWithState<TActionState>, chatId: number, chatName: string, traceId: number | string, storage: IStorageClient): this;
26
28
  /**
27
29
  * Manually update the state of an action.
28
30
  * @param stateUpdateAction Function that will modify state.
29
31
  */
30
32
  updateState(stateUpdateAction: (state: TActionState) => void): void;
31
33
  /**
32
- * Sends text message to chat.
34
+ * Sends text message to chat after action execution is finished.
35
+ * 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.
33
36
  * @param text Message contents.
34
37
  * @param options Message sending option.
35
38
  */
36
39
  sendTextToChat(text: string, options?: TextMessageSendingOptions): void;
37
40
  /**
38
- * Sends image message to chat.
41
+ * Sends image message to chat after action execution is finished.
42
+ * 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.
39
43
  * @param name Message contents.
40
44
  * @param options Message sending option.
41
45
  */
42
46
  sendImageToChat(name: string, options?: MessageSendingOptions): void;
43
47
  /**
44
- * Sends video/gif message to chat.
48
+ * Sends video/gif message to chat after action execution is finished.
49
+ * 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.
45
50
  * @param name Message contents.
46
51
  * @param options Message sending option.
47
52
  */
48
53
  sendVideoToChat(name: string, options?: MessageSendingOptions): void;
49
54
  /**
50
- * Unpins message.
55
+ * Unpins message after action execution is finished.
56
+ * 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.
51
57
  * @param messageId Message id.
52
58
  */
53
59
  unpinMessage(messageId: number): void;
60
+ /**
61
+ * Delays next response by specified amount of time.
62
+ * @param delay Delay in milliseconds.
63
+ */
64
+ delayNextResponse(delay: Milliseconds): void;
54
65
  }
55
66
  //# sourceMappingURL=chatContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chatContext.d.ts","sourceRoot":"","sources":["../../../entities/context/chatContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;GAEG;AACH,qBAAa,WAAW,CAAC,YAAY,SAAS,YAAY;IACtD,SAAS,CAAC,MAAM,EAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAClD,SAAS,CAAC,YAAY,EAAG,mBAAmB,CAAC;IAC7C,aAAa,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,CAAM;IACzD,sCAAsC;IACtC,OAAO,EAAG,MAAM,GAAG,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,OAAO,EAAG,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,EAAG,MAAM,CAAC;IAChB,iDAAiD;IACjD,QAAQ,EAAG,MAAM,CAAC;IAClB,4CAA4C;IAC5C,OAAO,EAAG,cAAc,CAAC;IAEzB,aAAa,UAAS;;IAItB,qBAAqB,CACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,YAAY,EAAE,mBAAmB,EACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,EAAE,cAAc;IAgB3B;;;OAGG;IACH,WAAW,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI;IAI5D;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAahE;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc7D;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc7D;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM;CAKjC"}
1
+ {"version":3,"file":"chatContext.d.ts","sourceRoot":"","sources":["../../../entities/context/chatContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD;;GAEG;AACH,qBAAa,WAAW,CAAC,YAAY,SAAS,YAAY;IACtD,SAAS,CAAC,MAAM,EAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAClD,aAAa,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,CAAM;IACzD,sCAAsC;IACtC,OAAO,EAAG,MAAM,GAAG,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,OAAO,EAAG,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,EAAG,MAAM,CAAC;IAChB,iDAAiD;IACjD,QAAQ,EAAG,MAAM,CAAC;IAClB,4CAA4C;IAC5C,OAAO,EAAG,cAAc,CAAC;IACzB,uDAAuD;IACvD,SAAS,EAAE,WAAW,EAAE,CAAM;IAE9B,aAAa,UAAS;;IAItB,qBAAqB,CACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,EAAE,cAAc;IAgB3B;;;OAGG;IACH,WAAW,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI;IAI5D;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAahE;;;;;OAKG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc7D;;;;;OAKG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc7D;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM;IAM9B;;;OAGG;IACH,iBAAiB,CAAC,KAAK,EAAE,YAAY;CAKxC"}
@@ -6,24 +6,27 @@ const imageMessage_1 = require("../responses/imageMessage");
6
6
  const textMessage_1 = require("../responses/textMessage");
7
7
  const videoMessage_1 = require("../responses/videoMessage");
8
8
  const unpin_1 = require("../responses/unpin");
9
+ const delay_1 = require("../responses/delay");
9
10
  /**
10
11
  * Context of action executed in chat.
11
12
  */
12
13
  class ChatContext {
13
14
  constructor() {
14
15
  this.updateActions = [];
16
+ /** Ordered collection of responses to be processed */
17
+ this.responses = [];
15
18
  this.isInitialized = false;
16
19
  }
17
- initializeChatContext(botName, action, interactions, chatId, chatName, traceId, storage) {
20
+ initializeChatContext(botName, action, chatId, chatName, traceId, storage) {
18
21
  this.botName = botName;
19
22
  this.action = action;
20
- this.interactions = interactions;
21
23
  this.chatId = chatId;
22
24
  this.chatName = chatName;
23
25
  this.traceId = traceId;
24
26
  this.storage = storage;
25
27
  this.updateActions = [];
26
28
  this.isInitialized = true;
29
+ this.responses = [];
27
30
  return this;
28
31
  }
29
32
  /**
@@ -34,37 +37,48 @@ class ChatContext {
34
37
  this.updateActions.push(stateUpdateAction);
35
38
  }
36
39
  /**
37
- * Sends text message to chat.
40
+ * Sends text message to chat after action execution is finished.
41
+ * 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.
38
42
  * @param text Message contents.
39
43
  * @param options Message sending option.
40
44
  */
41
45
  sendTextToChat(text, options) {
42
- this.interactions.respond(new textMessage_1.TextMessage(text, this.chatId, undefined, this.traceId, this.action, options));
46
+ this.responses.push(new textMessage_1.TextMessage(text, this.chatId, undefined, this.traceId, this.action, options));
43
47
  }
44
48
  /**
45
- * Sends image message to chat.
49
+ * Sends image message to chat after action execution is finished.
50
+ * 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.
46
51
  * @param name Message contents.
47
52
  * @param options Message sending option.
48
53
  */
49
54
  sendImageToChat(name, options) {
50
55
  const filePath = `./content/${name}.png`;
51
- this.interactions.respond(new imageMessage_1.ImageMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, undefined, this.traceId, this.action, options));
56
+ this.responses.push(new imageMessage_1.ImageMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, undefined, this.traceId, this.action, options));
52
57
  }
53
58
  /**
54
- * Sends video/gif message to chat.
59
+ * Sends video/gif message to chat after action execution is finished.
60
+ * 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.
55
61
  * @param name Message contents.
56
62
  * @param options Message sending option.
57
63
  */
58
64
  sendVideoToChat(name, options) {
59
65
  const filePath = `./content/${name}.mp4`;
60
- this.interactions.respond(new videoMessage_1.VideoMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, undefined, this.traceId, this.action, options));
66
+ this.responses.push(new videoMessage_1.VideoMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, undefined, this.traceId, this.action, options));
61
67
  }
62
68
  /**
63
- * Unpins message.
69
+ * Unpins message after action execution is finished.
70
+ * 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.
64
71
  * @param messageId Message id.
65
72
  */
66
73
  unpinMessage(messageId) {
67
- this.interactions.unpin(new unpin_1.UnpinResponse(messageId, this.chatId, this.traceId, this.action));
74
+ this.responses.push(new unpin_1.UnpinResponse(messageId, this.chatId, this.traceId, this.action));
75
+ }
76
+ /**
77
+ * Delays next response by specified amount of time.
78
+ * @param delay Delay in milliseconds.
79
+ */
80
+ delayNextResponse(delay) {
81
+ this.responses.push(new delay_1.DelayResponse(delay, this.chatId, this.traceId, this.action));
68
82
  }
69
83
  }
70
84
  exports.ChatContext = ChatContext;
@@ -1,4 +1,3 @@
1
- import { IBotApiInteractions } from '../../services/telegramApi';
2
1
  import { TelegramEmoji } from 'telegraf/types';
3
2
  import { IStorageClient } from '../../types/storage';
4
3
  import { IActionState } from '../../types/actionState';
@@ -26,7 +25,7 @@ export declare class MessageContext<TActionState extends IActionState> extends C
26
25
  /** Type of message being received */
27
26
  messageType: MessageTypeValue;
28
27
  constructor();
29
- initializeMessageContext(botName: string, action: IActionWithState<TActionState>, interactions: IBotApiInteractions, message: IncomingMessage, storage: IStorageClient): this;
28
+ initializeMessageContext(botName: string, action: IActionWithState<TActionState>, message: IncomingMessage, storage: IStorageClient): this;
30
29
  /**
31
30
  * Loads state of another action. Changes to the loaded state will no affect actual state of other action.
32
31
  * @param commandName Name of an action to load state of.
@@ -34,25 +33,29 @@ export declare class MessageContext<TActionState extends IActionState> extends C
34
33
  */
35
34
  loadStateOf<TAnotherActionState extends IActionState>(commandName: string): Promise<TAnotherActionState>;
36
35
  /**
37
- * Reply with text message to message that triggered this action.
36
+ * Reply with text message to message that triggered this action after action execution is finished.
37
+ * 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.
38
38
  * @param text Message contents.
39
39
  * @param options Message sending option.
40
40
  */
41
41
  replyWithText(text: string, options?: TextMessageSendingOptions): void;
42
42
  /**
43
- * Reply with image message to message that triggered this action.
43
+ * Reply with image message to message that triggered this action after action execution is finished.
44
+ * 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.
44
45
  * @param text Message contents.
45
46
  * @param options Message sending option.
46
47
  */
47
48
  replyWithImage(name: string, options?: MessageSendingOptions): void;
48
49
  /**
49
- * Reply with video/gif message to message that triggered this action.
50
+ * Reply with video/gif message to message that triggered this action after action execution is finished.
51
+ * 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.
50
52
  * @param text Message contents.
51
53
  * @param options Message sending option.
52
54
  */
53
55
  replyWithVideo(name: string, options?: MessageSendingOptions): void;
54
56
  /**
55
- * React to the message that triggered this action.
57
+ * React to the message that triggered this action after action execution is finished.
58
+ * 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.
56
59
  * @param emoji Telegram emoji to react with.
57
60
  */
58
61
  react(emoji: TelegramEmoji): void;
@@ -1 +1 @@
1
- {"version":3,"file":"messageContext.d.ts","sourceRoot":"","sources":["../../../entities/context/messageContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAMvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAa,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;GAEG;AACH,qBAAa,cAAc,CACvB,YAAY,SAAS,YAAY,CACnC,SAAQ,WAAW,CAAC,YAAY,CAAC;IAC/B,kDAAkD;IAClD,SAAS,EAAG,MAAM,CAAC;IACnB,oDAAoD;IACpD,WAAW,EAAG,MAAM,CAAC;IACrB,4HAA4H;IAC5H,YAAY,EAAE,gBAAgB,EAAE,CAAM;IACtC,mEAAmE;IACnE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kGAAkG;IAClG,aAAa,EAAE,OAAO,CAAQ;IAC9B,qEAAqE;IACrE,YAAY,EAAG,MAAM,CAAC;IACtB,qCAAqC;IACrC,WAAW,EAAG,gBAAgB,CAAC;;IAM/B,wBAAwB,CACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,YAAY,EAAE,mBAAmB,EACjC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,cAAc;IAwB3B;;;;OAIG;IACG,WAAW,CAAC,mBAAmB,SAAS,YAAY,EACtD,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC;IAe/B;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAa/D;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc5D;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc5D;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,aAAa;CAW7B"}
1
+ {"version":3,"file":"messageContext.d.ts","sourceRoot":"","sources":["../../../entities/context/messageContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAMvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAa,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D;;GAEG;AACH,qBAAa,cAAc,CACvB,YAAY,SAAS,YAAY,CACnC,SAAQ,WAAW,CAAC,YAAY,CAAC;IAC/B,kDAAkD;IAClD,SAAS,EAAG,MAAM,CAAC;IACnB,oDAAoD;IACpD,WAAW,EAAG,MAAM,CAAC;IACrB,4HAA4H;IAC5H,YAAY,EAAE,gBAAgB,EAAE,CAAM;IACtC,mEAAmE;IACnE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kGAAkG;IAClG,aAAa,EAAE,OAAO,CAAQ;IAC9B,qEAAqE;IACrE,YAAY,EAAG,MAAM,CAAC;IACtB,qCAAqC;IACrC,WAAW,EAAG,gBAAgB,CAAC;;IAM/B,wBAAwB,CACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,cAAc;IAuB3B;;;;OAIG;IACG,WAAW,CAAC,mBAAmB,SAAS,YAAY,EACtD,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC;IAe/B;;;;;OAKG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAa/D;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc5D;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAc5D;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,aAAa;CAW7B"}
@@ -19,7 +19,7 @@ class MessageContext extends chatContext_1.ChatContext {
19
19
  /** Indicates if cooldown should be started after action is executed. Set to `true` by default. */
20
20
  this.startCooldown = true;
21
21
  }
22
- initializeMessageContext(botName, action, interactions, message, storage) {
22
+ initializeMessageContext(botName, action, message, storage) {
23
23
  this.messageId = message.message_id;
24
24
  this.messageText = message.text ?? '';
25
25
  this.messageType = message.type;
@@ -29,7 +29,7 @@ class MessageContext extends chatContext_1.ChatContext {
29
29
  (message.from?.last_name ? ` ${message.from.last_name}` : '');
30
30
  this.matchResults = [];
31
31
  this.startCooldown = true;
32
- return this.initializeChatContext(botName, action, interactions, message.chat.id, message.chatName, message.traceId, storage);
32
+ return this.initializeChatContext(botName, action, message.chat.id, message.chatName, message.traceId, storage);
33
33
  }
34
34
  /**
35
35
  * Loads state of another action. Changes to the loaded state will no affect actual state of other action.
@@ -46,37 +46,41 @@ class MessageContext extends chatContext_1.ChatContext {
46
46
  return stateForChat;
47
47
  }
48
48
  /**
49
- * Reply with text message to message that triggered this action.
49
+ * Reply with text message to message that triggered this action after action execution is finished.
50
+ * 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.
50
51
  * @param text Message contents.
51
52
  * @param options Message sending option.
52
53
  */
53
54
  replyWithText(text, options) {
54
- this.interactions.respond(new textMessage_1.TextMessage(text, this.chatId, this.messageId, this.traceId, this.action, options));
55
+ this.responses.push(new textMessage_1.TextMessage(text, this.chatId, this.messageId, this.traceId, this.action, options));
55
56
  }
56
57
  /**
57
- * Reply with image message to message that triggered this action.
58
+ * Reply with image message to message that triggered this action after action execution is finished.
59
+ * 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.
58
60
  * @param text Message contents.
59
61
  * @param options Message sending option.
60
62
  */
61
63
  replyWithImage(name, options) {
62
64
  const filePath = `./content/${name}.png`;
63
- this.interactions.respond(new imageMessage_1.ImageMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, this.messageId, this.traceId, this.action, options));
65
+ this.responses.push(new imageMessage_1.ImageMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, this.messageId, this.traceId, this.action, options));
64
66
  }
65
67
  /**
66
- * Reply with video/gif message to message that triggered this action.
68
+ * Reply with video/gif message to message that triggered this action after action execution is finished.
69
+ * 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.
67
70
  * @param text Message contents.
68
71
  * @param options Message sending option.
69
72
  */
70
73
  replyWithVideo(name, options) {
71
74
  const filePath = `./content/${name}.mp4`;
72
- this.interactions.respond(new videoMessage_1.VideoMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, this.messageId, this.traceId, this.action, options));
75
+ this.responses.push(new videoMessage_1.VideoMessage({ source: (0, path_1.resolve)(filePath) }, this.chatId, this.messageId, this.traceId, this.action, options));
73
76
  }
74
77
  /**
75
- * React to the message that triggered this action.
78
+ * React to the message that triggered this action after action execution is finished.
79
+ * 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.
76
80
  * @param emoji Telegram emoji to react with.
77
81
  */
78
82
  react(emoji) {
79
- this.interactions.react(new reaction_1.Reaction(this.traceId, this.chatId, this.messageId, emoji, this.action));
83
+ this.responses.push(new reaction_1.Reaction(this.traceId, this.chatId, this.messageId, emoji, this.action));
80
84
  }
81
85
  }
82
86
  exports.MessageContext = MessageContext;
@@ -0,0 +1,13 @@
1
+ import { IActionState } from '../../types/actionState';
2
+ import { IActionWithState } from '../../types/actionWithState';
3
+ import { IChatResponse } from '../../types/response';
4
+ import { Milliseconds } from '../../types/timeValues';
5
+ export declare class DelayResponse implements IChatResponse {
6
+ kind: "delay";
7
+ chatId: number;
8
+ traceId: number | string;
9
+ delay: Milliseconds;
10
+ action: IActionWithState<IActionState>;
11
+ constructor(delay: Milliseconds, chatId: number, traceId: number | string, action: IActionWithState<IActionState>);
12
+ }
13
+ //# sourceMappingURL=delay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delay.d.ts","sourceRoot":"","sources":["../../../entities/responses/delay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAoB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,qBAAa,aAAc,YAAW,aAAa;IAC/C,IAAI,UAA0B;IAE9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBAGnC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC;CAO7C"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DelayResponse = void 0;
4
+ const response_1 = require("../../types/response");
5
+ class DelayResponse {
6
+ constructor(delay, chatId, traceId, action) {
7
+ this.kind = response_1.BotResponseTypes.delay;
8
+ this.chatId = chatId;
9
+ this.delay = delay;
10
+ this.traceId = traceId;
11
+ this.action = action;
12
+ }
13
+ }
14
+ exports.DelayResponse = DelayResponse;
@@ -1,13 +1,8 @@
1
1
  import { ChatContext } from '../entities/context/chatContext';
2
2
  import { MessageContext } from '../entities/context/messageContext';
3
3
  import { IStorageClient } from '../types/storage';
4
- import { Reaction } from '../entities/responses/reaction';
5
4
  import { IncomingMessage } from '../entities/incomingMessage';
6
5
  import { BotResponse } from '../types/response';
7
- import { UnpinResponse } from '../entities/responses/unpin';
8
- import { TextMessage } from '../entities/responses/textMessage';
9
- import { VideoMessage } from '../entities/responses/videoMessage';
10
- import { ImageMessage } from '../entities/responses/imageMessage';
11
6
  import { Telegram } from 'telegraf/typings/telegram';
12
7
  import { ScheduledAction } from '../entities/actions/scheduledAction';
13
8
  import { IActionState } from '../types/actionState';
@@ -19,18 +14,12 @@ export declare class TelegramApiService {
19
14
  telegram: Telegram;
20
15
  chats: Record<number, string>;
21
16
  storage: IStorageClient;
22
- interactions: IBotApiInteractions;
23
17
  constructor(botName: string, telegram: Telegram, storage: IStorageClient, chats: Record<string, number>);
18
+ enqueueBatchedResponses(responses: BotResponse[]): void;
24
19
  flushResponses(): Promise<void>;
25
20
  private pinIfShould;
26
21
  private processResponse;
27
- private enqueue;
28
22
  initializeContextForMessage<TActionState extends IActionState>(ctx: MessageContext<TActionState>, incomingMessage: IncomingMessage, command: CommandAction<TActionState>): MessageContext<TActionState>;
29
23
  initializeContextForChat<TActionState extends IActionState>(ctx: ChatContext<TActionState>, chatId: number, scheduledAction: ScheduledAction<TActionState>): ChatContext<TActionState>;
30
24
  }
31
- export interface IBotApiInteractions {
32
- respond: (response: TextMessage | VideoMessage | ImageMessage) => void;
33
- react: (reaction: Reaction) => void;
34
- unpin: (unpinMessage: UnpinResponse) => void;
35
- }
36
25
  //# sourceMappingURL=telegramApi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telegramApi.d.ts","sourceRoot":"","sources":["../../services/telegramApi.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAiB,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAIlE,qBAAa,kBAAkB;IAC3B,UAAU,UAAS;IACnB,YAAY,EAAE,WAAW,EAAE,CAAM;IAEjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,EAAE,mBAAmB,CAAC;gBAG9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAc3B,cAAc;YA2BN,WAAW;YAqBX,eAAe;IA2E7B,OAAO,CAAC,OAAO;IAIf,2BAA2B,CAAC,YAAY,SAAS,YAAY,EACzD,GAAG,EAAE,cAAc,CAAC,YAAY,CAAC,EACjC,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC;IAWxC,wBAAwB,CAAC,YAAY,SAAS,YAAY,EACtD,GAAG,EAAE,WAAW,CAAC,YAAY,CAAC,EAC9B,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,CAAC,YAAY,CAAC;CAYrD;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,CAAC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,YAAY,KAAK,IAAI,CAAC;IACvE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,KAAK,EAAE,CAAC,YAAY,EAAE,aAAa,KAAK,IAAI,CAAC;CAChD"}
1
+ {"version":3,"file":"telegramApi.d.ts","sourceRoot":"","sources":["../../services/telegramApi.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAiB,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAIlE,qBAAa,kBAAkB;IAC3B,UAAU,UAAS;IACnB,YAAY,EAAE,WAAW,EAAE,CAAM;IAEjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;gBAGpB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQjC,uBAAuB,CAAC,SAAS,EAAE,WAAW,EAAE;IAM1C,cAAc;YA2BN,WAAW;YAqBX,eAAe;IA2E7B,2BAA2B,CAAC,YAAY,SAAS,YAAY,EACzD,GAAG,EAAE,cAAc,CAAC,YAAY,CAAC,EACjC,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC;IAUxC,wBAAwB,CAAC,YAAY,SAAS,YAAY,EACtD,GAAG,EAAE,WAAW,CAAC,YAAY,CAAC,EAC9B,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,CAAC,YAAY,CAAC;CAWrD"}
@@ -13,11 +13,11 @@ class TelegramApiService {
13
13
  this.botName = botName;
14
14
  this.chats = (0, inverseRecord_1.inverseRecord)(chats);
15
15
  this.storage = storage;
16
- this.interactions = {
17
- react: (reaction) => this.enqueue(reaction),
18
- respond: (response) => this.enqueue(response),
19
- unpin: (unpinMessage) => this.enqueue(unpinMessage)
20
- };
16
+ }
17
+ enqueueBatchedResponses(responses) {
18
+ for (const response of responses) {
19
+ this.messageQueue.push(response);
20
+ }
21
21
  }
22
22
  async flushResponses() {
23
23
  if (this.isFlushing)
@@ -87,14 +87,11 @@ class TelegramApiService {
87
87
  break;
88
88
  }
89
89
  }
90
- enqueue(response) {
91
- this.messageQueue.push(response);
92
- }
93
90
  initializeContextForMessage(ctx, incomingMessage, command) {
94
- return ctx.initializeMessageContext(this.botName, command, this.interactions, incomingMessage, this.storage);
91
+ return ctx.initializeMessageContext(this.botName, command, incomingMessage, this.storage);
95
92
  }
96
93
  initializeContextForChat(ctx, chatId, scheduledAction) {
97
- return ctx.initializeChatContext(this.botName, scheduledAction, this.interactions, chatId, this.chats[chatId], `Scheduled:${scheduledAction.key}:${chatId}`, this.storage);
94
+ return ctx.initializeChatContext(this.botName, scheduledAction, chatId, this.chats[chatId], `Scheduled:${scheduledAction.key}:${chatId}`, this.storage);
98
95
  }
99
96
  }
100
97
  exports.TelegramApiService = TelegramApiService;
@@ -1,3 +1,4 @@
1
+ import { DelayResponse } from '../entities/responses/delay';
1
2
  import { ImageMessage } from '../entities/responses/imageMessage';
2
3
  import { Reaction } from '../entities/responses/reaction';
3
4
  import { TextMessage } from '../entities/responses/textMessage';
@@ -11,8 +12,9 @@ export declare const BotResponseTypes: {
11
12
  readonly image: "image";
12
13
  readonly video: "video";
13
14
  readonly react: "react";
15
+ readonly delay: "delay";
14
16
  };
15
- export type BotResponse = UnpinResponse | Reaction | TextMessage | VideoMessage | ImageMessage;
17
+ export type BotResponse = UnpinResponse | Reaction | TextMessage | VideoMessage | DelayResponse | ImageMessage;
16
18
  export interface IChatResponse {
17
19
  kind: keyof typeof BotResponseTypes;
18
20
  chatId: number;
@@ -1 +1 @@
1
- {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../types/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAEX,MAAM,MAAM,WAAW,GACjB,aAAa,GACb,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,YAAY,CAAC;AAEnB,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,OAAO,gBAAgB,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa,CAAC,KAAK,CAAE,SAAQ,aAAa;IACvD,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../types/response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,gBAAgB;;;;;;;CAOnB,CAAC;AAEX,MAAM,MAAM,WAAW,GACjB,aAAa,GACb,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,aAAa,GACb,YAAY,CAAC;AAEnB,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,OAAO,gBAAgB,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa,CAAC,KAAK,CAAE,SAAQ,aAAa;IACvD,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;CACtB"}
@@ -6,5 +6,6 @@ exports.BotResponseTypes = {
6
6
  text: 'text',
7
7
  image: 'image',
8
8
  video: 'video',
9
- react: 'react'
9
+ react: 'react',
10
+ delay: 'delay'
10
11
  };
@@ -56,11 +56,11 @@ export class CommandAction<TActionState extends IActionState>
56
56
  `Context for ${this.key} is not initialized or already consumed`
57
57
  );
58
58
 
59
- if (!this.active || this.chatsBlacklist.includes(ctx.chatId)) return;
59
+ if (!this.active || this.chatsBlacklist.includes(ctx.chatId)) return [];
60
60
 
61
61
  const isConditionMet = await this.condition(ctx);
62
62
 
63
- if (!isConditionMet) return;
63
+ if (!isConditionMet) return [];
64
64
 
65
65
  const state = await ctx.storage.getActionState<TActionState>(
66
66
  this,
@@ -74,7 +74,7 @@ export class CommandAction<TActionState extends IActionState>
74
74
  CommandTriggerCheckResult.DoNotTrigger
75
75
  );
76
76
 
77
- if (!shouldTrigger) return;
77
+ if (!shouldTrigger) return [];
78
78
 
79
79
  Logger.logWithTraceId(
80
80
  ctx.botName,
@@ -103,6 +103,8 @@ export class CommandAction<TActionState extends IActionState>
103
103
  );
104
104
 
105
105
  ctx.isInitialized = false;
106
+
107
+ return ctx.responses;
106
108
  }
107
109
 
108
110
  private checkTrigger(
@@ -52,7 +52,8 @@ export class ScheduledAction<TActionState extends IActionState>
52
52
  `Context for ${this.key} is not initialized or already consumed`
53
53
  );
54
54
 
55
- if (!this.active || !this.chatsWhitelist.includes(ctx.chatId)) return;
55
+ if (!this.active || !this.chatsWhitelist.includes(ctx.chatId))
56
+ return [];
56
57
 
57
58
  const state = await ctx.storage.getActionState<TActionState>(
58
59
  this,
@@ -86,6 +87,8 @@ export class ScheduledAction<TActionState extends IActionState>
86
87
  }
87
88
 
88
89
  ctx.isInitialized = false;
90
+
91
+ return ctx.responses;
89
92
  }
90
93
 
91
94
  private async getCachedValue<TResult>(
@@ -169,7 +169,8 @@ export class BotInstance {
169
169
  this.api.initializeContextForChat(ctx, chatId, scheduledAction);
170
170
 
171
171
  try {
172
- await scheduledAction.exec(ctx);
172
+ const responses = await scheduledAction.exec(ctx);
173
+ this.api.enqueueBatchedResponses(responses);
173
174
  } catch (error) {
174
175
  Logger.errorWithTraceId(
175
176
  ctx.botName,
@@ -192,7 +193,8 @@ export class BotInstance {
192
193
  this.api.initializeContextForMessage(ctx, msg, commandAction);
193
194
 
194
195
  try {
195
- await commandAction.exec(ctx);
196
+ const responses = await commandAction.exec(ctx);
197
+ this.api.enqueueBatchedResponses(responses);
196
198
  } catch (error) {
197
199
  Logger.errorWithTraceId(
198
200
  ctx.botName,
@@ -1,5 +1,4 @@
1
1
  import { resolve } from 'path';
2
- import { IBotApiInteractions } from '../../services/telegramApi';
3
2
  import { IStorageClient } from '../../types/storage';
4
3
  import { ImageMessage } from '../responses/imageMessage';
5
4
  import { TextMessage } from '../responses/textMessage';
@@ -11,13 +10,15 @@ import {
11
10
  } from '../../types/messageSendingOptions';
12
11
  import { IActionWithState } from '../../types/actionWithState';
13
12
  import { IActionState } from '../../types/actionState';
13
+ import { BotResponse } from '../../types/response';
14
+ import { Milliseconds } from '../../types/timeValues';
15
+ import { DelayResponse } from '../responses/delay';
14
16
 
15
17
  /**
16
18
  * Context of action executed in chat.
17
19
  */
18
20
  export class ChatContext<TActionState extends IActionState> {
19
21
  protected action!: IActionWithState<TActionState>;
20
- protected interactions!: IBotApiInteractions;
21
22
  updateActions: Array<(state: TActionState) => void> = [];
22
23
  /** Trace id of a action execution. */
23
24
  traceId!: number | string;
@@ -29,6 +30,8 @@ export class ChatContext<TActionState extends IActionState> {
29
30
  chatName!: string;
30
31
  /** Storage client instance for this bot. */
31
32
  storage!: IStorageClient;
33
+ /** Ordered collection of responses to be processed */
34
+ responses: BotResponse[] = [];
32
35
 
33
36
  isInitialized = false;
34
37
 
@@ -37,7 +40,6 @@ export class ChatContext<TActionState extends IActionState> {
37
40
  initializeChatContext(
38
41
  botName: string,
39
42
  action: IActionWithState<TActionState>,
40
- interactions: IBotApiInteractions,
41
43
  chatId: number,
42
44
  chatName: string,
43
45
  traceId: number | string,
@@ -45,7 +47,6 @@ export class ChatContext<TActionState extends IActionState> {
45
47
  ) {
46
48
  this.botName = botName;
47
49
  this.action = action;
48
- this.interactions = interactions;
49
50
  this.chatId = chatId;
50
51
  this.chatName = chatName;
51
52
  this.traceId = traceId;
@@ -53,6 +54,7 @@ export class ChatContext<TActionState extends IActionState> {
53
54
 
54
55
  this.updateActions = [];
55
56
  this.isInitialized = true;
57
+ this.responses = [];
56
58
 
57
59
  return this;
58
60
  }
@@ -66,12 +68,13 @@ export class ChatContext<TActionState extends IActionState> {
66
68
  }
67
69
 
68
70
  /**
69
- * Sends text message to chat.
71
+ * Sends text message to chat after action execution is finished.
72
+ * 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.
70
73
  * @param text Message contents.
71
74
  * @param options Message sending option.
72
75
  */
73
76
  sendTextToChat(text: string, options?: TextMessageSendingOptions) {
74
- this.interactions.respond(
77
+ this.responses.push(
75
78
  new TextMessage(
76
79
  text,
77
80
  this.chatId,
@@ -84,13 +87,14 @@ export class ChatContext<TActionState extends IActionState> {
84
87
  }
85
88
 
86
89
  /**
87
- * Sends image message to chat.
90
+ * Sends image message to chat after action execution is finished.
91
+ * 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.
88
92
  * @param name Message contents.
89
93
  * @param options Message sending option.
90
94
  */
91
95
  sendImageToChat(name: string, options?: MessageSendingOptions) {
92
96
  const filePath = `./content/${name}.png`;
93
- this.interactions.respond(
97
+ this.responses.push(
94
98
  new ImageMessage(
95
99
  { source: resolve(filePath) },
96
100
  this.chatId,
@@ -103,13 +107,14 @@ export class ChatContext<TActionState extends IActionState> {
103
107
  }
104
108
 
105
109
  /**
106
- * Sends video/gif message to chat.
110
+ * Sends video/gif message to chat after action execution is finished.
111
+ * 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.
107
112
  * @param name Message contents.
108
113
  * @param options Message sending option.
109
114
  */
110
115
  sendVideoToChat(name: string, options?: MessageSendingOptions) {
111
116
  const filePath = `./content/${name}.mp4`;
112
- this.interactions.respond(
117
+ this.responses.push(
113
118
  new VideoMessage(
114
119
  { source: resolve(filePath) },
115
120
  this.chatId,
@@ -122,12 +127,23 @@ export class ChatContext<TActionState extends IActionState> {
122
127
  }
123
128
 
124
129
  /**
125
- * Unpins message.
130
+ * Unpins message after action execution is finished.
131
+ * 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.
126
132
  * @param messageId Message id.
127
133
  */
128
134
  unpinMessage(messageId: number) {
129
- this.interactions.unpin(
135
+ this.responses.push(
130
136
  new UnpinResponse(messageId, this.chatId, this.traceId, this.action)
131
137
  );
132
138
  }
139
+
140
+ /**
141
+ * Delays next response by specified amount of time.
142
+ * @param delay Delay in milliseconds.
143
+ */
144
+ delayNextResponse(delay: Milliseconds) {
145
+ this.responses.push(
146
+ new DelayResponse(delay, this.chatId, this.traceId, this.action)
147
+ );
148
+ }
133
149
  }
@@ -1,5 +1,4 @@
1
1
  import { resolve } from 'path';
2
- import { IBotApiInteractions } from '../../services/telegramApi';
3
2
  import { TelegramEmoji } from 'telegraf/types';
4
3
  import { IStorageClient } from '../../types/storage';
5
4
  import { IActionState } from '../../types/actionState';
@@ -16,7 +15,6 @@ import {
16
15
  } from '../../types/messageSendingOptions';
17
16
  import { IActionWithState, ActionKey } from '../../types/actionWithState';
18
17
  import { MessageTypeValue } from '../../types/messageTypes';
19
-
20
18
  /**
21
19
  * Context of action executed in chat, in response to a message
22
20
  */
@@ -45,7 +43,6 @@ export class MessageContext<
45
43
  initializeMessageContext(
46
44
  botName: string,
47
45
  action: IActionWithState<TActionState>,
48
- interactions: IBotApiInteractions,
49
46
  message: IncomingMessage,
50
47
  storage: IStorageClient
51
48
  ) {
@@ -63,7 +60,6 @@ export class MessageContext<
63
60
  return this.initializeChatContext(
64
61
  botName,
65
62
  action,
66
- interactions,
67
63
  message.chat.id,
68
64
  message.chatName,
69
65
  message.traceId,
@@ -94,12 +90,13 @@ export class MessageContext<
94
90
  }
95
91
 
96
92
  /**
97
- * Reply with text message to message that triggered this action.
93
+ * Reply with text message to message that triggered this action after action execution is finished.
94
+ * 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.
98
95
  * @param text Message contents.
99
96
  * @param options Message sending option.
100
97
  */
101
98
  replyWithText(text: string, options?: TextMessageSendingOptions) {
102
- this.interactions.respond(
99
+ this.responses.push(
103
100
  new TextMessage(
104
101
  text,
105
102
  this.chatId,
@@ -112,13 +109,14 @@ export class MessageContext<
112
109
  }
113
110
 
114
111
  /**
115
- * Reply with image message to message that triggered this action.
112
+ * Reply with image message to message that triggered this action after action execution is finished.
113
+ * 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.
116
114
  * @param text Message contents.
117
115
  * @param options Message sending option.
118
116
  */
119
117
  replyWithImage(name: string, options?: MessageSendingOptions) {
120
118
  const filePath = `./content/${name}.png`;
121
- this.interactions.respond(
119
+ this.responses.push(
122
120
  new ImageMessage(
123
121
  { source: resolve(filePath) },
124
122
  this.chatId,
@@ -131,13 +129,14 @@ export class MessageContext<
131
129
  }
132
130
 
133
131
  /**
134
- * Reply with video/gif message to message that triggered this action.
132
+ * Reply with video/gif message to message that triggered this action after action execution is finished.
133
+ * 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.
135
134
  * @param text Message contents.
136
135
  * @param options Message sending option.
137
136
  */
138
137
  replyWithVideo(name: string, options?: MessageSendingOptions) {
139
138
  const filePath = `./content/${name}.mp4`;
140
- this.interactions.respond(
139
+ this.responses.push(
141
140
  new VideoMessage(
142
141
  { source: resolve(filePath) },
143
142
  this.chatId,
@@ -150,11 +149,12 @@ export class MessageContext<
150
149
  }
151
150
 
152
151
  /**
153
- * React to the message that triggered this action.
152
+ * React to the message that triggered this action after action execution is finished.
153
+ * 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.
154
154
  * @param emoji Telegram emoji to react with.
155
155
  */
156
156
  react(emoji: TelegramEmoji) {
157
- this.interactions.react(
157
+ this.responses.push(
158
158
  new Reaction(
159
159
  this.traceId,
160
160
  this.chatId,
@@ -0,0 +1,25 @@
1
+ import { IActionState } from '../../types/actionState';
2
+ import { IActionWithState } from '../../types/actionWithState';
3
+ import { BotResponseTypes, IChatResponse } from '../../types/response';
4
+ import { Milliseconds } from '../../types/timeValues';
5
+
6
+ export class DelayResponse implements IChatResponse {
7
+ kind = BotResponseTypes.delay;
8
+
9
+ chatId: number;
10
+ traceId: number | string;
11
+ delay: Milliseconds;
12
+ action: IActionWithState<IActionState>;
13
+
14
+ constructor(
15
+ delay: Milliseconds,
16
+ chatId: number,
17
+ traceId: number | string,
18
+ action: IActionWithState<IActionState>
19
+ ) {
20
+ this.chatId = chatId;
21
+ this.delay = delay;
22
+ this.traceId = traceId;
23
+ this.action = action;
24
+ }
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chz-telegram-bot",
3
- "version": "0.0.47",
3
+ "version": "0.0.48",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "async-sema": "^3.1.1",
@@ -4,13 +4,8 @@ import { MessageContext } from '../entities/context/messageContext';
4
4
  import { inverseRecord as inverseRecord } from '../helpers/inverseRecord';
5
5
  import { IStorageClient } from '../types/storage';
6
6
  import { Logger } from './logger';
7
- import { Reaction } from '../entities/responses/reaction';
8
7
  import { IncomingMessage } from '../entities/incomingMessage';
9
8
  import { BotResponse, IReplyMessage } from '../types/response';
10
- import { UnpinResponse } from '../entities/responses/unpin';
11
- import { TextMessage } from '../entities/responses/textMessage';
12
- import { VideoMessage } from '../entities/responses/videoMessage';
13
- import { ImageMessage } from '../entities/responses/imageMessage';
14
9
  import { Telegram } from 'telegraf/typings/telegram';
15
10
  import { setTimeout } from 'timers/promises';
16
11
  import { Milliseconds } from '../types/timeValues';
@@ -28,7 +23,6 @@ export class TelegramApiService {
28
23
  telegram: Telegram;
29
24
  chats: Record<number, string>;
30
25
  storage: IStorageClient;
31
- interactions: IBotApiInteractions;
32
26
 
33
27
  constructor(
34
28
  botName: string,
@@ -40,12 +34,12 @@ export class TelegramApiService {
40
34
  this.botName = botName;
41
35
  this.chats = inverseRecord(chats);
42
36
  this.storage = storage;
37
+ }
43
38
 
44
- this.interactions = {
45
- react: (reaction) => this.enqueue(reaction),
46
- respond: (response) => this.enqueue(response),
47
- unpin: (unpinMessage) => this.enqueue(unpinMessage)
48
- } as IBotApiInteractions;
39
+ enqueueBatchedResponses(responses: BotResponse[]) {
40
+ for (const response of responses) {
41
+ this.messageQueue.push(response);
42
+ }
49
43
  }
50
44
 
51
45
  async flushResponses() {
@@ -171,10 +165,6 @@ export class TelegramApiService {
171
165
  }
172
166
  }
173
167
 
174
- private enqueue(response: BotResponse) {
175
- this.messageQueue.push(response);
176
- }
177
-
178
168
  initializeContextForMessage<TActionState extends IActionState>(
179
169
  ctx: MessageContext<TActionState>,
180
170
  incomingMessage: IncomingMessage,
@@ -183,7 +173,6 @@ export class TelegramApiService {
183
173
  return ctx.initializeMessageContext(
184
174
  this.botName,
185
175
  command,
186
- this.interactions,
187
176
  incomingMessage,
188
177
  this.storage
189
178
  );
@@ -197,7 +186,6 @@ export class TelegramApiService {
197
186
  return ctx.initializeChatContext(
198
187
  this.botName,
199
188
  scheduledAction,
200
- this.interactions,
201
189
  chatId,
202
190
  this.chats[chatId],
203
191
  `Scheduled:${scheduledAction.key}:${chatId}`,
@@ -205,9 +193,3 @@ export class TelegramApiService {
205
193
  );
206
194
  }
207
195
  }
208
-
209
- export interface IBotApiInteractions {
210
- respond: (response: TextMessage | VideoMessage | ImageMessage) => void;
211
- react: (reaction: Reaction) => void;
212
- unpin: (unpinMessage: UnpinResponse) => void;
213
- }
package/types/response.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { DelayResponse } from '../entities/responses/delay';
1
2
  import { ImageMessage } from '../entities/responses/imageMessage';
2
3
  import { Reaction } from '../entities/responses/reaction';
3
4
  import { TextMessage } from '../entities/responses/textMessage';
@@ -11,7 +12,8 @@ export const BotResponseTypes = {
11
12
  text: 'text',
12
13
  image: 'image',
13
14
  video: 'video',
14
- react: 'react'
15
+ react: 'react',
16
+ delay: 'delay'
15
17
  } as const;
16
18
 
17
19
  export type BotResponse =
@@ -19,6 +21,7 @@ export type BotResponse =
19
21
  | Reaction
20
22
  | TextMessage
21
23
  | VideoMessage
24
+ | DelayResponse
22
25
  | ImageMessage;
23
26
 
24
27
  export interface IChatResponse {