chz-telegram-bot 0.4.0 → 0.5.1

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/bun.lock +301 -630
  2. package/dist/dtos/chatHistoryMessage.d.ts +3 -3
  3. package/dist/dtos/chatHistoryMessage.d.ts.map +1 -1
  4. package/dist/dtos/incomingMessage.d.ts +4 -4
  5. package/dist/dtos/incomingMessage.d.ts.map +1 -1
  6. package/dist/dtos/incomingMessage.js +1 -1
  7. package/dist/dtos/messageInfo.d.ts +3 -3
  8. package/dist/dtos/messageInfo.d.ts.map +1 -1
  9. package/dist/dtos/responses/inlineQueryResponse.d.ts +3 -3
  10. package/dist/dtos/responses/inlineQueryResponse.d.ts.map +1 -1
  11. package/dist/dtos/responses/reaction.d.ts +1 -1
  12. package/dist/dtos/responses/reaction.d.ts.map +1 -1
  13. package/dist/dtos/responses/textMessage.d.ts +2 -0
  14. package/dist/dtos/responses/textMessage.d.ts.map +1 -1
  15. package/dist/dtos/responses/textMessage.js +2 -0
  16. package/dist/entities/context/inlineQueryContext.d.ts +3 -3
  17. package/dist/entities/context/inlineQueryContext.d.ts.map +1 -1
  18. package/dist/entities/context/messageContext.d.ts +2 -2
  19. package/dist/entities/context/messageContext.d.ts.map +1 -1
  20. package/dist/entities/context/replyContext.d.ts +2 -2
  21. package/dist/entities/context/replyContext.d.ts.map +1 -1
  22. package/dist/index.d.ts +1 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -0
  25. package/dist/services/actionProcessingService.d.ts +1 -1
  26. package/dist/services/actionProcessingService.d.ts.map +1 -1
  27. package/dist/services/actionProcessingService.js +7 -9
  28. package/dist/services/actionProcessors/commandActionProcessor.d.ts +2 -2
  29. package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -1
  30. package/dist/services/actionProcessors/commandActionProcessor.js +3 -3
  31. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts +1 -1
  32. package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -1
  33. package/dist/services/actionProcessors/inlineQueryActionProcessor.js +1 -1
  34. package/dist/services/telegramApi.d.ts +3 -2
  35. package/dist/services/telegramApi.d.ts.map +1 -1
  36. package/dist/services/telegramApi.js +35 -32
  37. package/dist/types/externalAliases.d.ts +11 -0
  38. package/dist/types/externalAliases.d.ts.map +1 -0
  39. package/dist/types/externalAliases.js +2 -0
  40. package/dist/types/messageSendingOptions.d.ts +2 -0
  41. package/dist/types/messageSendingOptions.d.ts.map +1 -1
  42. package/dtos/chatHistoryMessage.ts +2 -2
  43. package/dtos/incomingMessage.ts +7 -7
  44. package/dtos/messageInfo.ts +2 -2
  45. package/dtos/responses/inlineQueryResponse.ts +3 -3
  46. package/dtos/responses/reaction.ts +1 -1
  47. package/dtos/responses/textMessage.ts +3 -0
  48. package/entities/context/inlineQueryContext.ts +3 -3
  49. package/entities/context/messageContext.ts +2 -2
  50. package/entities/context/replyContext.ts +2 -2
  51. package/eslint.config.js +1 -0
  52. package/index.ts +1 -0
  53. package/package.json +37 -40
  54. package/services/actionProcessingService.ts +10 -9
  55. package/services/actionProcessors/commandActionProcessor.ts +7 -7
  56. package/services/actionProcessors/inlineQueryActionProcessor.ts +2 -2
  57. package/services/telegramApi.ts +61 -49
  58. package/types/externalAliases.ts +18 -0
  59. package/types/messageSendingOptions.ts +3 -0
@@ -1,11 +1,11 @@
1
- import { User } from 'node-telegram-bot-api';
1
+ import { TelegramUser } from '../types/externalAliases';
2
2
  import { MessageTypeValue } from '../types/messageTypes';
3
3
  import { TraceId } from '../types/trace';
4
4
 
5
5
  export class ChatHistoryMessage {
6
6
  constructor(
7
7
  readonly id: number,
8
- readonly from: User | undefined,
8
+ readonly from: TelegramUser | undefined,
9
9
  readonly text: string,
10
10
  readonly type: MessageTypeValue,
11
11
  readonly traceId: TraceId,
@@ -4,20 +4,20 @@ import { ChatInfo } from './chatInfo';
4
4
  import { createTrace } from '../helpers/traceFactory';
5
5
  import { TraceId } from '../types/trace';
6
6
  import { ChatHistoryMessage } from './chatHistoryMessage';
7
- import { Message, User } from 'node-telegram-bot-api';
7
+ import { TelegramMessage, TelegramUser } from '../types/externalAliases';
8
8
 
9
9
  export class IncomingMessage {
10
10
  readonly messageId: number;
11
11
  readonly chatInfo: ChatInfo;
12
- readonly from: User | undefined;
12
+ readonly from: TelegramUser | undefined;
13
13
  readonly text: string;
14
14
  readonly type: MessageTypeValue;
15
15
  readonly traceId: TraceId;
16
16
  readonly replyToMessageId: number | undefined;
17
17
 
18
- readonly updateObject: Message;
18
+ readonly updateObject: TelegramMessage;
19
19
 
20
- private detectMessageType(message: Message) {
20
+ private detectMessageType(message: TelegramMessage) {
21
21
  if ('forward_origin' in message) return MessageType.Forward;
22
22
  if ('text' in message) return MessageType.Text;
23
23
  if ('video' in message) return MessageType.Video;
@@ -36,7 +36,7 @@ export class IncomingMessage {
36
36
  }
37
37
 
38
38
  constructor(
39
- ctxMessage: Message,
39
+ ctxMessage: TelegramMessage,
40
40
  botName: string,
41
41
  history: ChatHistoryMessage[]
42
42
  ) {
@@ -63,8 +63,8 @@ export class IncomingMessage {
63
63
  this.updateObject = ctxMessage;
64
64
  }
65
65
 
66
- private getMessageText(ctxMessage: Message) {
67
- if ('text' in ctxMessage) return ctxMessage.text ?? '';
66
+ private getMessageText(ctxMessage: TelegramMessage) {
67
+ if ('text' in ctxMessage) return ctxMessage.text;
68
68
 
69
69
  return 'caption' in ctxMessage ? ctxMessage.caption ?? '' : '';
70
70
  }
@@ -1,4 +1,4 @@
1
- import { Message } from 'node-telegram-bot-api';
1
+ import { TelegramMessage } from '../types/externalAliases';
2
2
  import { MessageTypeValue } from '../types/messageTypes';
3
3
 
4
4
  export class MessageInfo {
@@ -10,6 +10,6 @@ export class MessageInfo {
10
10
  /** Type of message being received */
11
11
  readonly type: MessageTypeValue,
12
12
  /** Message object recieved from Telegram */
13
- readonly telegramUpdateObject: Message
13
+ readonly telegramUpdateObject: TelegramMessage
14
14
  ) {}
15
15
  }
@@ -1,5 +1,5 @@
1
- import { InlineQueryResult } from 'node-telegram-bot-api';
2
1
  import { InlineQueryAction } from '../../entities/actions/inlineQueryAction';
2
+ import { TelegramInlineQueryResult } from '../../types/externalAliases';
3
3
  import { BotResponseTypes } from '../../types/response';
4
4
  import { TraceId } from '../../types/trace';
5
5
 
@@ -10,10 +10,10 @@ export class InlineQueryResponse {
10
10
  readonly queryId: string;
11
11
  readonly traceId: TraceId;
12
12
  readonly action: InlineQueryAction;
13
- readonly queryResults: InlineQueryResult[];
13
+ readonly queryResults: TelegramInlineQueryResult[];
14
14
 
15
15
  constructor(
16
- queryResult: InlineQueryResult[],
16
+ queryResult: TelegramInlineQueryResult[],
17
17
  queryId: string,
18
18
  traceId: TraceId,
19
19
  action: InlineQueryAction
@@ -2,7 +2,7 @@ import { BotResponseTypes, IChatResponse } from '../../types/response';
2
2
  import { IAction } from '../../types/action';
3
3
  import { ChatInfo } from '../chatInfo';
4
4
  import { TraceId } from '../../types/trace';
5
- import { TelegramEmoji } from 'node-telegram-bot-api';
5
+ import { TelegramEmoji } from '../../types/externalAliases';
6
6
 
7
7
  export class Reaction implements IChatResponse {
8
8
  readonly kind = BotResponseTypes.react;
@@ -8,6 +8,7 @@ import { ChatInfo } from '../chatInfo';
8
8
  import { TraceId } from '../../types/trace';
9
9
  import { ReplyInfo } from '../replyInfo';
10
10
  import { IReplyCapture } from '../../types/capture';
11
+ import { TelegramInlineKeyboardButton } from '../../types/externalAliases';
11
12
 
12
13
  export class TextMessage implements IReplyResponseWithContent<string> {
13
14
  readonly kind = BotResponseTypes.text;
@@ -21,6 +22,7 @@ export class TextMessage implements IReplyResponseWithContent<string> {
21
22
  readonly disableWebPreview: boolean;
22
23
  readonly shouldPin: boolean;
23
24
  readonly action: IAction;
25
+ readonly keyboard?: TelegramInlineKeyboardButton[][];
24
26
 
25
27
  constructor(
26
28
  text: string,
@@ -37,5 +39,6 @@ export class TextMessage implements IReplyResponseWithContent<string> {
37
39
  this.disableWebPreview = options?.disableWebPreview ?? false;
38
40
  this.shouldPin = options?.pin ?? false;
39
41
  this.action = action;
42
+ this.keyboard = options?.keyboard;
40
43
  }
41
44
  }
@@ -5,7 +5,7 @@ import {
5
5
  BaseContextInternal,
6
6
  BaseContextPropertiesToOmit
7
7
  } from './baseContext';
8
- import { InlineQueryResult } from 'node-telegram-bot-api';
8
+ import { TelegramInlineQueryResult } from '../../types/externalAliases';
9
9
 
10
10
  export type InlineQueryContext = Omit<
11
11
  InlineQueryContextInternal,
@@ -13,7 +13,7 @@ export type InlineQueryContext = Omit<
13
13
  >;
14
14
 
15
15
  export class InlineQueryContextInternal extends BaseContextInternal<InlineQueryAction> {
16
- queryResults: InlineQueryResult[] = [];
16
+ queryResults: TelegramInlineQueryResult[] = [];
17
17
  /**
18
18
  * Abort signal to be utilized in query handler.
19
19
  * Signal will be aborted if new query comes from the same user.
@@ -42,7 +42,7 @@ export class InlineQueryContextInternal extends BaseContextInternal<InlineQueryA
42
42
  * This result will be shown to user as a response to inline query.
43
43
  * @param queryResult Inline query result to be shown to user.
44
44
  */
45
- showInlineQueryResult(queryResult: InlineQueryResult) {
45
+ showInlineQueryResult(queryResult: TelegramInlineQueryResult) {
46
46
  this.queryResults.push(queryResult);
47
47
  }
48
48
  }
@@ -15,7 +15,7 @@ import { Seconds } from '../../types/timeValues';
15
15
  import { BaseContextPropertiesToOmit } from './baseContext';
16
16
  import { MessageInfo } from '../../dtos/messageInfo';
17
17
  import { UserInfo } from '../../dtos/userInfo';
18
- import { TelegramEmoji, User } from 'node-telegram-bot-api';
18
+ import { BotInfo, TelegramEmoji } from '../../types/externalAliases';
19
19
 
20
20
  export type MessageContext<TActionState extends IActionState> = Omit<
21
21
  MessageContextInternal<TActionState>,
@@ -37,7 +37,7 @@ export class MessageContextInternal<
37
37
  /** Indicates if cooldown should be started after action is executed. Set to `true` by default. */
38
38
  startCooldown: boolean = true;
39
39
  /** Bot info from Telegram */
40
- botInfo!: User;
40
+ botInfo!: BotInfo;
41
41
  customCooldown: Seconds | undefined;
42
42
 
43
43
  private getQuotePart(quote: boolean | string) {
@@ -16,7 +16,7 @@ import {
16
16
  } from './baseContext';
17
17
  import { UserInfo } from '../../dtos/userInfo';
18
18
  import { MessageInfo } from '../../dtos/messageInfo';
19
- import { TelegramEmoji, User } from 'node-telegram-bot-api';
19
+ import { TelegramUser, TelegramEmoji } from '../../types/externalAliases';
20
20
 
21
21
  export type ReplyContext<TActionState extends IActionState> = Omit<
22
22
  ReplyContextInternal<TActionState>,
@@ -38,7 +38,7 @@ export class ReplyContextInternal<
38
38
  /** Information about the message that triggered this action */
39
39
  messageInfo!: MessageInfo;
40
40
  /** Bot info from Telegram */
41
- botInfo!: User;
41
+ botInfo!: TelegramUser;
42
42
 
43
43
  isInitialized = false;
44
44
 
package/eslint.config.js CHANGED
@@ -16,6 +16,7 @@ export default tseslint.config(
16
16
  }
17
17
  },
18
18
  rules: {
19
+ '@typescript-eslint/switch-exhaustiveness-check': 'error',
19
20
  '@typescript-eslint/no-unused-vars': [
20
21
  'error',
21
22
  {
package/index.ts CHANGED
@@ -7,6 +7,7 @@ export * from './entities/states/actionStateBase';
7
7
  export * from './types/messageTypes';
8
8
  export * from './helpers/timeConvertions';
9
9
  export * from './types/action';
10
+ export * from './types/externalAliases';
10
11
  export { CommandAction } from './entities/actions/commandAction';
11
12
  export { InlineQueryAction } from './entities/actions/inlineQueryAction';
12
13
  export { ReplyCaptureAction } from './entities/actions/replyCaptureAction';
package/package.json CHANGED
@@ -1,40 +1,37 @@
1
- {
2
- "name": "chz-telegram-bot",
3
- "description": "Opinionated TypeScript framework that provides a structured approach to building Telegram bots.",
4
- "author": {
5
- "name": "Alex Halanin",
6
- "url": "https://github.com/AlexSolari"
7
- },
8
- "license": "MIT",
9
- "keywords": [
10
- "telegram",
11
- "telegram bot"
12
- ],
13
- "repository": {
14
- "type": "git",
15
- "url": "https://github.com/AlexSolari/botFramework.git"
16
- },
17
- "version": "0.4.0",
18
- "type": "module",
19
- "dependencies": {
20
- "async-sema": "^3.1.1",
21
- "moment": "^2.29.4",
22
- "node-telegram-bot-api": "^0.66.0"
23
- },
24
- "main": "dist/index.js",
25
- "types": "dist/index.d.ts",
26
- "devDependencies": {
27
- "@types/node-telegram-bot-api": "^0.64.10",
28
- "@eslint/js": "^9.29.0",
29
- "@types/markdown-escape": "^1.1.3",
30
- "@types/node": "^22.5.5",
31
- "eslint": "^9.29.0",
32
- "globals": "^16.2.0",
33
- "typescript": "^5.9.0-beta",
34
- "typescript-eslint": "^8.34.1"
35
- },
36
- "scripts": {
37
- "build": "tsc",
38
- "lint": "npx eslint && tsc --noEmit"
39
- }
40
- }
1
+ {
2
+ "name": "chz-telegram-bot",
3
+ "description": "Opinionated TypeScript framework that provides a structured approach to building Telegram bots.",
4
+ "author": {
5
+ "name": "Alex Halanin",
6
+ "url": "https://github.com/AlexSolari"
7
+ },
8
+ "license": "MIT",
9
+ "keywords": [
10
+ "telegram",
11
+ "telegram bot"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/AlexSolari/botFramework.git"
16
+ },
17
+ "version": "0.5.1",
18
+ "type": "module",
19
+ "dependencies": {
20
+ "async-sema": "^3.1.1",
21
+ "moment": "^2.29.4",
22
+ "telegraf": "^4.16.3"
23
+ },
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "devDependencies": {
27
+ "@eslint/js": "^9.29.0",
28
+ "@types/node": "^22.5.5",
29
+ "eslint": "^9.29.0",
30
+ "typescript": "^5.9.0-beta",
31
+ "typescript-eslint": "^8.34.1"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "lint": "npx eslint && tsc --noEmit"
36
+ }
37
+ }
@@ -12,7 +12,8 @@ import { buildHelpCommand } from '../builtin/helpAction';
12
12
  import { CommandActionProcessor } from './actionProcessors/commandActionProcessor';
13
13
  import { InlineQueryActionProcessor } from './actionProcessors/inlineQueryActionProcessor';
14
14
  import { ScheduledActionProcessor } from './actionProcessors/scheduledActionProcessor';
15
- import TelegramBot from 'node-telegram-bot-api';
15
+ import { TelegramBot } from '../types/externalAliases';
16
+ import { Telegraf } from 'telegraf';
16
17
 
17
18
  export class ActionProcessingService {
18
19
  private readonly storage: IStorageClient;
@@ -69,10 +70,10 @@ export class ActionProcessingService {
69
70
  scheduledPeriod?: Seconds,
70
71
  verboseLoggingForIncomingMessage?: boolean
71
72
  ) {
72
- this.telegramBot = new TelegramBot(token, { polling: true });
73
+ this.telegramBot = new Telegraf(token);
73
74
  const api = new TelegramApiService(
74
75
  this.botName,
75
- this.telegramBot,
76
+ this.telegramBot.telegram,
76
77
  this.storage,
77
78
  this.logger,
78
79
  (capture, id, chatInfo, traceId) => {
@@ -85,15 +86,13 @@ export class ActionProcessingService {
85
86
  }
86
87
  );
87
88
 
88
- const botInfo = await this.telegramBot.getMe();
89
+ const botInfo = await this.telegramBot.telegram.getMe();
89
90
  const commandActions =
90
91
  actions.commands.length > 0 && botInfo.username
91
92
  ? [
92
93
  buildHelpCommand(
93
94
  actions.commands
94
- .map((x) =>
95
- x.readmeFactory(botInfo.username as string)
96
- )
95
+ .map((x) => x.readmeFactory(botInfo.username))
97
96
  .filter((x) => !!x),
98
97
  botInfo.username
99
98
  ),
@@ -120,13 +119,15 @@ export class ActionProcessingService {
120
119
  scheduledPeriod ?? hoursToSeconds(1 as Hours)
121
120
  );
122
121
 
122
+ void this.telegramBot.launch();
123
+
123
124
  void this.storage.saveMetadata([
124
125
  ...actions.scheduled,
125
126
  ...commandActions
126
127
  ]);
127
128
  }
128
129
 
129
- async stop() {
130
- await this.telegramBot.stopPolling();
130
+ stop() {
131
+ this.telegramBot.stop();
131
132
  }
132
133
  }
@@ -18,14 +18,14 @@ import { getOrSetIfNotExists } from '../../helpers/mapUtils';
18
18
  import { MessageInfo } from '../../dtos/messageInfo';
19
19
  import { UserInfo } from '../../dtos/userInfo';
20
20
  import { ChatHistoryMessage } from '../../dtos/chatHistoryMessage';
21
- import TelegramBot from 'node-telegram-bot-api';
21
+ import { BotInfo, TelegramBot } from '../../types/externalAliases';
22
22
 
23
23
  const MESSAGE_HISTORY_LENGTH_LIMIT = 100;
24
24
 
25
25
  export class CommandActionProcessor extends BaseActionProcessor {
26
26
  private readonly replyCaptures: ReplyCaptureAction<IActionState>[] = [];
27
27
  private readonly chatHistory = new Map<number, ChatHistoryMessage[]>();
28
- private botInfo!: TelegramBot.User;
28
+ private botInfo!: BotInfo;
29
29
 
30
30
  private commands = typeSafeObjectFromEntries(
31
31
  Object.values(MessageType).map((x) => [
@@ -39,7 +39,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
39
39
  telegram: TelegramBot,
40
40
  commands: CommandAction<IActionState>[],
41
41
  verboseLoggingForIncomingMessage: boolean,
42
- botInfo: TelegramBot.User
42
+ botInfo: BotInfo
43
43
  ) {
44
44
  this.botInfo = botInfo;
45
45
  this.initializeDependencies(api);
@@ -70,11 +70,11 @@ export class CommandActionProcessor extends BaseActionProcessor {
70
70
  }
71
71
 
72
72
  if (commands.length > 0) {
73
- telegram.on('message', (msg) => {
73
+ telegram.on('message', ({ message }) => {
74
74
  const internalMessage = new IncomingMessage(
75
- msg,
75
+ message,
76
76
  this.botName,
77
- getOrSetIfNotExists(this.chatHistory, msg.chat.id, [])
77
+ getOrSetIfNotExists(this.chatHistory, message.chat.id, [])
78
78
  );
79
79
 
80
80
  const logger = this.logger.createScope(
@@ -84,7 +84,7 @@ export class CommandActionProcessor extends BaseActionProcessor {
84
84
  );
85
85
 
86
86
  if (verboseLoggingForIncomingMessage) {
87
- logger.logObjectWithTraceId(msg);
87
+ logger.logObjectWithTraceId(message);
88
88
  } else {
89
89
  logger.logWithTraceId(
90
90
  `${internalMessage.from?.first_name ?? 'Unknown'} (${
@@ -1,8 +1,8 @@
1
- import TelegramBot from 'node-telegram-bot-api';
2
1
  import { IncomingInlineQuery } from '../../dtos/incomingQuery';
3
2
  import { InlineQueryAction } from '../../entities/actions/inlineQueryAction';
4
3
  import { InlineQueryContextInternal } from '../../entities/context/inlineQueryContext';
5
4
  import { createTrace } from '../../helpers/traceFactory';
5
+ import { TelegramBot } from '../../types/externalAliases';
6
6
  import { Milliseconds } from '../../types/timeValues';
7
7
  import { TraceId } from '../../types/trace';
8
8
  import { TelegramApiService } from '../telegramApi';
@@ -25,7 +25,7 @@ export class InlineQueryActionProcessor extends BaseActionProcessor {
25
25
  const queriesInProcessing = new Map<number, IncomingInlineQuery>();
26
26
 
27
27
  if (this.inlineQueries.length > 0) {
28
- telegram.on('inline_query', (inlineQuery) => {
28
+ telegram.on('inline_query', ({ inlineQuery }) => {
29
29
  const query = new IncomingInlineQuery(
30
30
  inlineQuery.id,
31
31
  inlineQuery.query,
@@ -7,14 +7,13 @@ import { IActionWithState } from '../types/action';
7
7
  import { IActionState } from '../types/actionState';
8
8
  import { TraceId } from '../types/trace';
9
9
  import { ChatInfo } from '../dtos/chatInfo';
10
- import TelegramBot, { Message } from 'node-telegram-bot-api';
11
- import { createReadStream } from 'fs';
10
+ import { TelegramApiClient, TelegramMessage } from '../types/externalAliases';
12
11
 
13
12
  export const TELEGRAM_ERROR_QUOTE_INVALID = 'QUOTE_TEXT_INVALID';
14
13
 
15
14
  export class TelegramApiService {
16
15
  private readonly queue = new ResponseProcessingQueue();
17
- private readonly telegram: TelegramBot;
16
+ private readonly telegram: TelegramApiClient;
18
17
  private readonly storage: IStorageClient;
19
18
  private readonly logger: ILogger;
20
19
  private readonly captureRegistrationCallback: (
@@ -28,7 +27,7 @@ export class TelegramApiService {
28
27
 
29
28
  constructor(
30
29
  botName: string,
31
- telegram: TelegramBot,
30
+ telegram: TelegramApiClient,
32
31
  storage: IStorageClient,
33
32
  logger: ILogger,
34
33
  captureRegistrationCallback: (
@@ -105,7 +104,10 @@ export class TelegramApiService {
105
104
  void this.queue.flushReadyItems();
106
105
  }
107
106
 
108
- private async pinIfShould(response: IReplyResponse, message: Message) {
107
+ private async pinIfShould(
108
+ response: IReplyResponse,
109
+ message: TelegramMessage
110
+ ) {
109
111
  if (response.shouldPin) {
110
112
  await this.telegram.pinChatMessage(
111
113
  response.chatInfo.id,
@@ -124,11 +126,29 @@ export class TelegramApiService {
124
126
  }
125
127
 
126
128
  private async processResponse(response: BotResponse, ignoreQuote = false) {
127
- let sentMessage: Message | null = null;
129
+ const sentMessage = await this.sendApiRequest(response, ignoreQuote);
130
+
131
+ if (sentMessage && 'content' in response) {
132
+ await this.pinIfShould(response, sentMessage);
133
+
134
+ for (const capture of response.captures) {
135
+ this.captureRegistrationCallback(
136
+ capture,
137
+ sentMessage.message_id,
138
+ response.chatInfo,
139
+ response.traceId
140
+ );
141
+ }
142
+ }
143
+ }
128
144
 
145
+ private async sendApiRequest(
146
+ response: BotResponse,
147
+ ignoreQuote: boolean
148
+ ): Promise<TelegramMessage | null> {
129
149
  switch (response.kind) {
130
150
  case 'text':
131
- sentMessage = await this.telegram.sendMessage(
151
+ return await this.telegram.sendMessage(
132
152
  response.chatInfo.id,
133
153
  response.content,
134
154
  {
@@ -143,51 +163,54 @@ export class TelegramApiService {
143
163
  parse_mode: 'MarkdownV2',
144
164
  link_preview_options: {
145
165
  is_disabled: response.disableWebPreview
146
- }
166
+ },
167
+ reply_markup: response.keyboard
168
+ ? {
169
+ inline_keyboard: response.keyboard
170
+ }
171
+ : undefined
147
172
  }
148
173
  );
149
- break;
150
174
  case 'image':
151
- sentMessage = await this.telegram.sendPhoto(
175
+ return await this.telegram.sendPhoto(
152
176
  response.chatInfo.id,
153
- createReadStream(response.content.source),
177
+ response.content,
178
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
154
179
  response.replyInfo?.id
155
- ? {
156
- reply_to_message_id: response.replyInfo.id
157
- }
180
+ ? ({
181
+ reply_to_message_id: response.replyInfo.id // eslint-disable-next-line @typescript-eslint/no-explicit-any
182
+ } as any)
158
183
  : undefined
159
184
  );
160
- break;
161
185
  case 'video':
162
- sentMessage = await this.telegram.sendVideo(
186
+ return await this.telegram.sendVideo(
163
187
  response.chatInfo.id,
164
- createReadStream(response.content.source),
188
+ response.content,
189
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
165
190
  response.replyInfo?.id
166
- ? {
167
- reply_to_message_id: response.replyInfo.id
168
- }
191
+ ? ({
192
+ reply_to_message_id: response.replyInfo.id // eslint-disable-next-line @typescript-eslint/no-explicit-any
193
+ } as any)
169
194
  : undefined
170
195
  );
171
- break;
172
196
  case 'react':
173
197
  await this.telegram.setMessageReaction(
174
198
  response.chatInfo.id,
175
199
  response.messageId,
176
- {
177
- reaction: [
178
- {
179
- type: 'emoji',
180
- emoji: response.emoji
181
- }
182
- ]
183
- }
200
+ [
201
+ {
202
+ type: 'emoji',
203
+ emoji: response.emoji
204
+ }
205
+ ]
184
206
  );
185
207
 
186
- return;
208
+ return null;
187
209
  case 'unpin':
188
- await this.telegram.unpinChatMessage(response.chatInfo.id, {
189
- message_id: response.messageId
190
- });
210
+ await this.telegram.unpinChatMessage(
211
+ response.chatInfo.id,
212
+ response.messageId
213
+ );
191
214
 
192
215
  await this.storage.updateStateFor(
193
216
  response.action,
@@ -198,29 +221,18 @@ export class TelegramApiService {
198
221
  );
199
222
  }
200
223
  );
201
- break;
224
+
225
+ return null;
202
226
  case 'inlineQuery':
203
227
  await this.telegram.answerInlineQuery(
204
228
  response.queryId,
205
229
  response.queryResults,
206
230
  { cache_time: 0 }
207
231
  );
208
- break;
209
- case 'delay':
210
- break;
211
- }
212
-
213
- if ('content' in response && sentMessage) {
214
- await this.pinIfShould(response, sentMessage);
215
232
 
216
- for (const capture of response.captures) {
217
- this.captureRegistrationCallback(
218
- capture,
219
- sentMessage.message_id,
220
- response.chatInfo,
221
- response.traceId
222
- );
223
- }
233
+ return null;
234
+ case 'delay':
235
+ return null;
224
236
  }
225
237
  }
226
238
  }
@@ -0,0 +1,18 @@
1
+ import { Telegram, Telegraf } from 'telegraf';
2
+ import {
3
+ User,
4
+ Message,
5
+ InlineQueryResult,
6
+ UserFromGetMe,
7
+ TelegramEmoji as Emoji,
8
+ InlineKeyboardButton
9
+ } from 'telegraf/types';
10
+
11
+ export type TelegramUser = User;
12
+ export type TelegramMessage = Message;
13
+ export type TelegramInlineQueryResult = InlineQueryResult;
14
+ export type TelegramEmoji = Emoji;
15
+ export type TelegramApiClient = Telegram;
16
+ export type BotInfo = UserFromGetMe;
17
+ export type TelegramBot = Telegraf;
18
+ export type TelegramInlineKeyboardButton = InlineKeyboardButton;
@@ -1,7 +1,10 @@
1
+ import { TelegramInlineKeyboardButton } from './externalAliases';
2
+
1
3
  export interface MessageSendingOptions {
2
4
  pin?: boolean;
3
5
  }
4
6
 
5
7
  export interface TextMessageSendingOptions extends MessageSendingOptions {
6
8
  disableWebPreview?: boolean;
9
+ keyboard?: TelegramInlineKeyboardButton[][];
7
10
  }