chz-telegram-bot 0.3.1 → 0.3.3

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 (59) hide show
  1. package/dist/entities/actions/commandAction.d.ts.map +1 -1
  2. package/dist/entities/actions/commandAction.js +3 -2
  3. package/dist/entities/actions/inlineQueryAction.d.ts.map +1 -1
  4. package/dist/entities/actions/inlineQueryAction.js +1 -1
  5. package/dist/entities/actions/replyCaptureAction.d.ts.map +1 -1
  6. package/dist/entities/actions/replyCaptureAction.js +1 -1
  7. package/dist/entities/actions/scheduledAction.d.ts.map +1 -1
  8. package/dist/entities/actions/scheduledAction.js +1 -1
  9. package/dist/entities/context/chatContext.d.ts +10 -4
  10. package/dist/entities/context/chatContext.d.ts.map +1 -1
  11. package/dist/entities/context/chatContext.js +18 -6
  12. package/dist/entities/context/inlineQueryContext.d.ts +4 -4
  13. package/dist/entities/context/inlineQueryContext.d.ts.map +1 -1
  14. package/dist/entities/context/inlineQueryContext.js +1 -2
  15. package/dist/entities/context/messageContext.d.ts +1 -8
  16. package/dist/entities/context/messageContext.d.ts.map +1 -1
  17. package/dist/entities/context/messageContext.js +5 -20
  18. package/dist/entities/context/replyContext.d.ts +4 -4
  19. package/dist/entities/context/replyContext.d.ts.map +1 -1
  20. package/dist/entities/context/replyContext.js +1 -2
  21. package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -1
  22. package/dist/services/actionProcessors/commandActionProcessor.js +12 -8
  23. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -1
  24. package/dist/services/actionProcessors/inlineQueryActionProcessor.js +7 -5
  25. package/dist/services/actionProcessors/scheduledActionProcessor.d.ts.map +1 -1
  26. package/dist/services/actionProcessors/scheduledActionProcessor.js +3 -2
  27. package/dist/services/jsonLogger.d.ts +3 -2
  28. package/dist/services/jsonLogger.d.ts.map +1 -1
  29. package/dist/services/jsonLogger.js +8 -4
  30. package/dist/services/telegramApi.d.ts +1 -0
  31. package/dist/services/telegramApi.d.ts.map +1 -1
  32. package/dist/services/telegramApi.js +23 -6
  33. package/dist/types/capture.d.ts +11 -1
  34. package/dist/types/capture.d.ts.map +1 -1
  35. package/dist/types/commandCondition.d.ts +5 -1
  36. package/dist/types/commandCondition.d.ts.map +1 -1
  37. package/dist/types/logger.d.ts +6 -0
  38. package/dist/types/logger.d.ts.map +1 -1
  39. package/dist/types/messageTypes.d.ts +1 -0
  40. package/dist/types/messageTypes.d.ts.map +1 -1
  41. package/dist/types/messageTypes.js +1 -0
  42. package/entities/actions/commandAction.ts +2 -4
  43. package/entities/actions/inlineQueryAction.ts +1 -6
  44. package/entities/actions/replyCaptureAction.ts +0 -3
  45. package/entities/actions/scheduledAction.ts +0 -3
  46. package/entities/context/chatContext.ts +25 -12
  47. package/entities/context/inlineQueryContext.ts +4 -9
  48. package/entities/context/messageContext.ts +5 -34
  49. package/entities/context/replyContext.ts +4 -9
  50. package/package.json +1 -1
  51. package/services/actionProcessors/commandActionProcessor.ts +28 -32
  52. package/services/actionProcessors/inlineQueryActionProcessor.ts +10 -18
  53. package/services/actionProcessors/scheduledActionProcessor.ts +8 -12
  54. package/services/jsonLogger.ts +20 -4
  55. package/services/telegramApi.ts +40 -11
  56. package/types/capture.ts +7 -0
  57. package/types/commandCondition.ts +2 -0
  58. package/types/logger.ts +20 -0
  59. package/types/messageTypes.ts +1 -0
@@ -57,10 +57,13 @@ export class InlineQueryActionProcessor {
57
57
  createTrace('InlineQuery', this.botName, ctx.inlineQuery.id)
58
58
  );
59
59
 
60
- this.logger.logWithTraceId(
60
+ const logger = this.logger.createScope(
61
61
  this.botName,
62
62
  query.traceId,
63
- 'Query',
63
+ 'Query'
64
+ );
65
+
66
+ logger.logWithTraceId(
64
67
  `${ctx.inlineQuery.from.username} (${ctx.inlineQuery.from.id}): Query for ${ctx.inlineQuery.query}`
65
68
  );
66
69
 
@@ -68,10 +71,7 @@ export class InlineQueryActionProcessor {
68
71
  query.userId
69
72
  );
70
73
  if (queryBeingProcessed) {
71
- this.logger.logWithTraceId(
72
- this.botName,
73
- query.traceId,
74
- 'Query',
74
+ logger.logWithTraceId(
75
75
  `Aborting query ${queryBeingProcessed.queryId} (${queryBeingProcessed.query}): new query recieved from ${query.userId}`
76
76
  );
77
77
 
@@ -91,7 +91,6 @@ export class InlineQueryActionProcessor {
91
91
  async () => {
92
92
  const ctx = new InlineQueryContext(
93
93
  this.storage,
94
- this.logger,
95
94
  this.scheduler
96
95
  );
97
96
 
@@ -124,20 +123,11 @@ export class InlineQueryActionProcessor {
124
123
  const error = err as Error;
125
124
 
126
125
  if (error.name == 'AbortError') {
127
- this.logger.logWithTraceId(
128
- this.botName,
129
- inlineQuery.traceId,
130
- 'Query',
126
+ ctx.logger.logWithTraceId(
131
127
  `Aborting query ${inlineQuery.queryId} (${inlineQuery.query}) successful.`
132
128
  );
133
129
  } else {
134
- this.logger.errorWithTraceId(
135
- ctx.botName,
136
- ctx.traceId,
137
- 'Unknown',
138
- error,
139
- ctx
140
- );
130
+ ctx.logger.errorWithTraceId(error, ctx);
141
131
  }
142
132
  }
143
133
  }
@@ -172,5 +162,7 @@ export class InlineQueryActionProcessor {
172
162
  ctx.isInitialized = true;
173
163
  ctx.queryResults = [];
174
164
  ctx.matchResults = [];
165
+
166
+ ctx.logger = this.logger.createScope(this.botName, traceId, 'Unknown');
175
167
  }
176
168
  }
@@ -91,11 +91,7 @@ export class ScheduledActionProcessor {
91
91
  }
92
92
 
93
93
  private async runScheduled() {
94
- const ctx = new ChatContext<IActionState>(
95
- this.storage,
96
- this.logger,
97
- this.scheduler
98
- );
94
+ const ctx = new ChatContext<IActionState>(this.storage, this.scheduler);
99
95
 
100
96
  for (const [chatName, chatId] of Object.entries(this.chats)) {
101
97
  for (const scheduledAction of this.scheduled) {
@@ -115,13 +111,7 @@ export class ScheduledActionProcessor {
115
111
  this.api.enqueueBatchedResponses(responses);
116
112
  ctx.isInitialized = false;
117
113
  } catch (error) {
118
- this.logger.errorWithTraceId(
119
- ctx.botName,
120
- ctx.traceId,
121
- chatName,
122
- error,
123
- ctx
124
- );
114
+ ctx.logger.errorWithTraceId(error, ctx);
125
115
  }
126
116
  }
127
117
  }
@@ -141,5 +131,11 @@ export class ScheduledActionProcessor {
141
131
  ctx.action = action;
142
132
  ctx.chatInfo = chatInfo;
143
133
  ctx.traceId = traceId;
134
+
135
+ ctx.logger = this.logger.createScope(
136
+ this.botName,
137
+ traceId,
138
+ chatInfo.name
139
+ );
144
140
  }
145
141
  }
@@ -1,8 +1,8 @@
1
- import { ILogger } from '../types/logger';
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { ILogger, IScopedLogger } from '../types/logger';
2
3
  import { TraceId } from '../types/trace';
3
4
 
4
5
  export class JsonLogger implements ILogger {
5
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
6
  private serializeError(error: any) {
7
7
  const plainObject: Record<string, unknown> = {};
8
8
  Object.getOwnPropertyNames(error).forEach(function (key) {
@@ -11,11 +11,27 @@ export class JsonLogger implements ILogger {
11
11
  return JSON.stringify(plainObject);
12
12
  }
13
13
 
14
+ createScope(botName: string, traceId: TraceId, chatName: string) {
15
+ return {
16
+ logObjectWithTraceId: (data: any) =>
17
+ this.logObjectWithTraceId(botName, traceId, chatName, data),
18
+ logWithTraceId: (text: string) =>
19
+ this.logWithTraceId(botName, traceId, chatName, text),
20
+ errorWithTraceId: <TData>(errorObj: unknown, extraData?: TData) =>
21
+ this.errorWithTraceId(
22
+ botName,
23
+ traceId,
24
+ chatName,
25
+ errorObj,
26
+ extraData
27
+ )
28
+ } as IScopedLogger;
29
+ }
30
+
14
31
  logObjectWithTraceId(
15
32
  botName: string,
16
33
  traceId: TraceId,
17
34
  chatName: string,
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
35
  data: any
20
36
  ) {
21
37
  data.botName = botName;
@@ -40,7 +56,7 @@ export class JsonLogger implements ILogger {
40
56
  traceId: TraceId,
41
57
  chatName: string,
42
58
  errorObj: unknown,
43
- extraData?: TData | undefined
59
+ extraData?: TData
44
60
  ) {
45
61
  console.error(
46
62
  `{"botName":"${botName}","traceId":"${traceId}","chatName":"${chatName}","error":${this.serializeError(
@@ -9,6 +9,9 @@ import { IActionWithState } from '../types/action';
9
9
  import { IActionState } from '../types/actionState';
10
10
  import { TraceId } from '../types/trace';
11
11
  import { ChatInfo } from '../dtos/chatInfo';
12
+ import { TelegramError } from 'telegraf';
13
+
14
+ export const TELEGRAM_ERROR_QUOTE_INVALID = 'QUOTE_TEXT_INVALID';
12
15
 
13
16
  export class TelegramApiService {
14
17
  private readonly queue = new ResponseProcessingQueue();
@@ -53,18 +56,42 @@ export class TelegramApiService {
53
56
 
54
57
  const queueItem: QueueItem = {
55
58
  callback: async () => {
59
+ const scopedLogger = this.logger.createScope(
60
+ this.botName,
61
+ response.traceId,
62
+ 'chatInfo' in response
63
+ ? response.chatInfo.name
64
+ : 'Unknown'
65
+ );
66
+
56
67
  try {
57
68
  await this.processResponse(response);
58
69
  } catch (error) {
59
- this.logger.errorWithTraceId(
60
- this.botName,
61
- response.traceId,
62
- 'chatInfo' in response
63
- ? response.chatInfo.name
64
- : 'Unknown',
65
- error,
66
- response
67
- );
70
+ if ('message' in (error as TelegramError)) {
71
+ const telegramResponse = error as TelegramError;
72
+
73
+ if (
74
+ telegramResponse.message.includes(
75
+ TELEGRAM_ERROR_QUOTE_INVALID
76
+ )
77
+ ) {
78
+ scopedLogger.logWithTraceId(
79
+ 'Quote error recieved, retrying without quote'
80
+ );
81
+ try {
82
+ await this.processResponse(response, true);
83
+ } catch (error) {
84
+ scopedLogger.errorWithTraceId(
85
+ error,
86
+ response
87
+ );
88
+ }
89
+
90
+ return;
91
+ }
92
+ }
93
+
94
+ scopedLogger.errorWithTraceId(error, response);
68
95
  }
69
96
  },
70
97
  priority: response.createdAt + offset
@@ -95,7 +122,7 @@ export class TelegramApiService {
95
122
  }
96
123
  }
97
124
 
98
- private async processResponse(response: BotResponse) {
125
+ private async processResponse(response: BotResponse, ignoreQuote = false) {
99
126
  let sentMessage: Message | null = null;
100
127
 
101
128
  switch (response.kind) {
@@ -107,7 +134,9 @@ export class TelegramApiService {
107
134
  reply_parameters: response.replyInfo
108
135
  ? {
109
136
  message_id: response.replyInfo.id,
110
- quote: response.replyInfo.quote
137
+ quote: ignoreQuote
138
+ ? undefined
139
+ : response.replyInfo.quote
111
140
  }
112
141
  : undefined,
113
142
  parse_mode: 'MarkdownV2',
package/types/capture.ts CHANGED
@@ -5,10 +5,17 @@ import { IActionWithState } from './action';
5
5
 
6
6
  export interface ICaptureController {
7
7
  captureReplies: <TParentActionState extends IActionState>(
8
+ /**
9
+ * Defines action trigger.
10
+ * If `string` or `string[]` is provided, will be triggered only on exact message match.
11
+ * If `RegExp` or `RegExp[]` is provided, will be triggered on successful match.
12
+ */
8
13
  trigger: CommandTrigger[],
14
+ /** Callback that will be called on trigger */
9
15
  handler: (
10
16
  replyContext: ReplyContext<TParentActionState>
11
17
  ) => Promise<void>,
18
+ /** Abort controller to abort capturing manually */
12
19
  abortController: AbortController
13
20
  ) => void;
14
21
  }
@@ -2,6 +2,8 @@ import { MessageContext } from '../entities/context/messageContext';
2
2
  import { IActionState } from './actionState';
3
3
 
4
4
  export type CommandCondition<TActionState extends IActionState> = (
5
+ /** Context of action executed in chat, in response to a message. */
5
6
  ctx: MessageContext<TActionState>,
7
+ /** State of an action being executed. */
6
8
  state: TActionState
7
9
  ) => boolean;
package/types/logger.ts CHANGED
@@ -1,6 +1,26 @@
1
1
  import { TraceId } from './trace';
2
2
 
3
+ export interface IScopedLogger {
4
+ logObjectWithTraceId(
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ data: any
7
+ ): void;
8
+
9
+ logWithTraceId(text: string): void;
10
+
11
+ errorWithTraceId<TData>(
12
+ errorObj: unknown,
13
+ extraData?: TData | undefined
14
+ ): void;
15
+ }
16
+
3
17
  export interface ILogger {
18
+ createScope(
19
+ botName: string,
20
+ traceId: TraceId,
21
+ chatName: string
22
+ ): IScopedLogger;
23
+
4
24
  logObjectWithTraceId(
5
25
  botName: string,
6
26
  traceId: TraceId,
@@ -3,6 +3,7 @@ import { Message, Update } from 'telegraf/types';
3
3
  export const INTERNAL_MESSAGE_TYPE_PREFIX = `__msg:`;
4
4
 
5
5
  export const MessageType = {
6
+ Any: `${INTERNAL_MESSAGE_TYPE_PREFIX}ANY`,
6
7
  Text: `${INTERNAL_MESSAGE_TYPE_PREFIX}Text`,
7
8
  Sticker: `${INTERNAL_MESSAGE_TYPE_PREFIX}Sticker`,
8
9
  Animation: `${INTERNAL_MESSAGE_TYPE_PREFIX}Animation`,