chz-telegram-bot 0.0.16 → 0.0.17

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 (54) hide show
  1. package/dist/entities/botInstance.js +3 -3
  2. package/dist/entities/context/chatContext.d.ts +6 -4
  3. package/dist/entities/context/chatContext.d.ts.map +1 -1
  4. package/dist/entities/context/chatContext.js +12 -7
  5. package/dist/entities/context/messageContext.d.ts +4 -4
  6. package/dist/entities/context/messageContext.d.ts.map +1 -1
  7. package/dist/entities/context/messageContext.js +9 -9
  8. package/dist/entities/responses/imageMessage.d.ts +5 -2
  9. package/dist/entities/responses/imageMessage.d.ts.map +1 -1
  10. package/dist/entities/responses/imageMessage.js +5 -1
  11. package/dist/entities/responses/reaction.d.ts +5 -2
  12. package/dist/entities/responses/reaction.d.ts.map +1 -1
  13. package/dist/entities/responses/reaction.js +4 -1
  14. package/dist/entities/responses/textMessage.d.ts +5 -2
  15. package/dist/entities/responses/textMessage.d.ts.map +1 -1
  16. package/dist/entities/responses/textMessage.js +5 -1
  17. package/dist/entities/responses/unpin.d.ts +10 -0
  18. package/dist/entities/responses/unpin.d.ts.map +1 -0
  19. package/dist/entities/responses/unpin.js +14 -0
  20. package/dist/entities/responses/videoMessage.d.ts +5 -2
  21. package/dist/entities/responses/videoMessage.d.ts.map +1 -1
  22. package/dist/entities/responses/videoMessage.js +5 -1
  23. package/dist/entities/states/actionStateBase.d.ts +1 -0
  24. package/dist/entities/states/actionStateBase.d.ts.map +1 -1
  25. package/dist/entities/states/actionStateBase.js +1 -0
  26. package/dist/services/jsonFileStorage.d.ts +1 -0
  27. package/dist/services/jsonFileStorage.d.ts.map +1 -1
  28. package/dist/services/jsonFileStorage.js +8 -0
  29. package/dist/services/telegramApi.d.ts +15 -10
  30. package/dist/services/telegramApi.d.ts.map +1 -1
  31. package/dist/services/telegramApi.js +42 -33
  32. package/dist/types/actionState.d.ts +1 -0
  33. package/dist/types/actionState.d.ts.map +1 -1
  34. package/dist/types/response.d.ts +26 -0
  35. package/dist/types/response.d.ts.map +1 -0
  36. package/dist/types/response.js +10 -0
  37. package/dist/types/storage.d.ts +1 -0
  38. package/dist/types/storage.d.ts.map +1 -1
  39. package/entities/botInstance.ts +3 -3
  40. package/entities/context/chatContext.ts +31 -6
  41. package/entities/context/messageContext.ts +29 -8
  42. package/entities/responses/imageMessage.ts +10 -2
  43. package/entities/responses/reaction.ts +8 -2
  44. package/entities/responses/textMessage.ts +10 -2
  45. package/entities/responses/unpin.ts +22 -0
  46. package/entities/responses/videoMessage.ts +10 -2
  47. package/entities/states/actionStateBase.ts +1 -0
  48. package/package.json +1 -1
  49. package/services/jsonFileStorage.ts +15 -0
  50. package/services/telegramApi.ts +84 -48
  51. package/types/actionState.ts +1 -0
  52. package/types/response.ts +34 -0
  53. package/types/storage.ts +5 -0
  54. package/types/replyMessage.ts +0 -7
@@ -1,33 +1,34 @@
1
- import { Telegraf } from 'telegraf';
2
- import { InputFile } from 'telegraf/types';
1
+ import { InputFile, Message } from 'telegraf/types';
3
2
  import { ChatContext } from '../entities/context/chatContext';
4
3
  import { MessageContext } from '../entities/context/messageContext';
5
- import { ImageMessage } from '../entities/responses/imageMessage';
6
- import { TextMessage } from '../entities/responses/textMessage';
7
- import { VideoMessage } from '../entities/responses/videoMessage';
8
4
  import { reverseMap } from '../helpers/reverseMap';
9
- import { IReplyMessage } from '../types/replyMessage';
10
5
  import { IStorageClient } from '../types/storage';
11
6
  import { Milliseconds } from '../types/timeValues';
12
7
  import { Scheduler } from './taskScheduler';
13
8
  import { Logger } from './logger';
14
9
  import { Reaction } from '../entities/responses/reaction';
15
10
  import { IncomingMessage } from '../entities/incomingMessage';
11
+ import { BotResponse, IReplyMessage } from '../types/response';
12
+ import { UnpinResponse } from '../entities/responses/unpin';
13
+ import { TextMessage } from '../entities/responses/textMessage';
14
+ import { VideoMessage } from '../entities/responses/videoMessage';
15
+ import { ImageMessage } from '../entities/responses/imageMessage';
16
+ import { Telegram } from 'telegraf/typings/telegram';
16
17
 
17
18
  export class TelegramApiService {
18
19
  botName: string;
19
- telegraf: Telegraf;
20
+ telegram: Telegram;
20
21
  chats: Map<number, string>;
21
- messageQueue: Array<IReplyMessage<unknown> | Reaction> = [];
22
+ messageQueue: Array<BotResponse> = [];
22
23
  storage: IStorageClient;
23
24
 
24
25
  constructor(
25
26
  botName: string,
26
- telegraf: Telegraf,
27
+ telegram: Telegram,
27
28
  storage: IStorageClient,
28
29
  chats: Map<string, number>
29
30
  ) {
30
- this.telegraf = telegraf;
31
+ this.telegram = telegram;
31
32
  this.botName = botName;
32
33
  this.chats = reverseMap(chats);
33
34
  this.storage = storage;
@@ -61,28 +62,33 @@ export class TelegramApiService {
61
62
  }
62
63
  }
63
64
 
64
- private async processResponse<TType>(
65
- response: IReplyMessage<TType> | Reaction
65
+ private async pinIfShould<T>(
66
+ response: IReplyMessage<T>,
67
+ sentMessage: Message
66
68
  ) {
67
- if ('emoji' in response) {
68
- this.telegraf.telegram.setMessageReaction(
69
+ if (response.shouldPin) {
70
+ await this.telegram.pinChatMessage(
69
71
  response.chatId,
70
- response.messageId,
71
- [
72
- {
73
- type: 'emoji',
74
- emoji: response.emoji
75
- }
76
- ],
77
- true
72
+ sentMessage.message_id,
73
+ { disable_notification: true }
78
74
  );
79
75
 
80
- return;
76
+ await this.storage.updateStateFor(
77
+ response.sourceActionKey,
78
+ response.chatId,
79
+ async (state) => {
80
+ state.pinnedMessages.push(sentMessage.message_id);
81
+ }
82
+ );
81
83
  }
84
+ }
85
+
86
+ private async processResponse(response: BotResponse) {
87
+ let sentMessage: Message;
82
88
 
83
- switch (response.constructor) {
84
- case TextMessage:
85
- await this.telegraf.telegram.sendMessage(
89
+ switch (response.kind) {
90
+ case 'text':
91
+ sentMessage = await this.telegram.sendMessage(
86
92
  response.chatId,
87
93
  response.content as string,
88
94
  {
@@ -92,9 +98,11 @@ export class TelegramApiService {
92
98
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
99
  } as any
94
100
  );
101
+
102
+ await this.pinIfShould(response, sentMessage);
95
103
  break;
96
- case ImageMessage:
97
- await this.telegraf.telegram.sendPhoto(
104
+ case 'image':
105
+ sentMessage = await this.telegram.sendPhoto(
98
106
  response.chatId,
99
107
  response.content as InputFile,
100
108
  response.replyId
@@ -102,9 +110,11 @@ export class TelegramApiService {
102
110
  ({ reply_to_message_id: response.replyId } as any)
103
111
  : undefined
104
112
  );
113
+
114
+ await this.pinIfShould(response, sentMessage);
105
115
  break;
106
- case VideoMessage:
107
- await this.telegraf.telegram.sendVideo(
116
+ case 'video':
117
+ sentMessage = await this.telegram.sendVideo(
108
118
  response.chatId,
109
119
  response.content as InputFile,
110
120
  response.replyId
@@ -112,35 +122,58 @@ export class TelegramApiService {
112
122
  ({ reply_to_message_id: response.replyId } as any)
113
123
  : undefined
114
124
  );
125
+
126
+ await this.pinIfShould(response, sentMessage);
115
127
  break;
116
- default:
117
- Logger.errorWithTraceId(
118
- this.botName,
119
- response.traceId,
120
- this.chats.get(response.chatId)!,
121
- `Unknown message type: ${response.constructor}`,
122
- response
128
+ case 'react':
129
+ await this.telegram.setMessageReaction(
130
+ response.chatId,
131
+ response.messageId,
132
+ [
133
+ {
134
+ type: 'emoji',
135
+ emoji: response.emoji
136
+ }
137
+ ],
138
+ true
139
+ );
140
+
141
+ return;
142
+ case 'unpin':
143
+ await this.telegram.unpinChatMessage(
144
+ response.chatId,
145
+ response.messageId
146
+ );
147
+
148
+ await this.storage.updateStateFor(
149
+ response.sourceActionKey,
150
+ response.chatId,
151
+ async (state) => {
152
+ state.pinnedMessages = state.pinnedMessages.filter(
153
+ (x) => x != response.messageId
154
+ );
155
+ }
123
156
  );
124
157
  break;
125
158
  }
126
159
  }
127
160
 
128
- private enqueueResponse<TType>(response: IReplyMessage<TType>) {
129
- this.messageQueue.push(response);
130
- }
131
-
132
- private enqueueReaction(reaction: Reaction) {
161
+ private enqueue(reaction: BotResponse) {
133
162
  this.messageQueue.push(reaction);
134
163
  }
135
164
 
136
165
  private getInteractions() {
137
166
  return {
138
- react: (reaction) => this.enqueueReaction(reaction),
139
- respond: (response) => this.enqueueResponse(response)
167
+ react: (reaction) => this.enqueue(reaction),
168
+ respond: (response) => this.enqueue(response),
169
+ unpin: (unpinMessage) => this.enqueue(unpinMessage)
140
170
  } as IBotApiInteractions;
141
171
  }
142
172
 
143
- createContextForMessage(incomingMessage: IncomingMessage) {
173
+ createContextForMessage(
174
+ incomingMessage: IncomingMessage,
175
+ commandKey: string
176
+ ) {
144
177
  const firstName = incomingMessage.from?.first_name ?? 'Unknown user';
145
178
  const lastName = incomingMessage.from?.last_name
146
179
  ? ` ${incomingMessage.from?.last_name}`
@@ -148,6 +181,7 @@ export class TelegramApiService {
148
181
 
149
182
  return new MessageContext(
150
183
  this.botName,
184
+ commandKey,
151
185
  this.getInteractions(),
152
186
  incomingMessage.chat.id,
153
187
  incomingMessage.chatName,
@@ -160,19 +194,21 @@ export class TelegramApiService {
160
194
  );
161
195
  }
162
196
 
163
- createContextForChat(chatId: number, scheduledName: string) {
197
+ createContextForChat(chatId: number, scheduledKey: string) {
164
198
  return new ChatContext(
165
199
  this.botName,
200
+ scheduledKey,
166
201
  this.getInteractions(),
167
202
  chatId,
168
203
  this.chats.get(chatId)!,
169
- `Scheduled:${scheduledName}:${chatId}`,
204
+ `Scheduled:${scheduledKey}:${chatId}`,
170
205
  this.storage
171
206
  );
172
207
  }
173
208
  }
174
209
 
175
210
  export interface IBotApiInteractions {
176
- respond: <TType>(response: IReplyMessage<TType>) => void;
211
+ respond: (response: TextMessage | VideoMessage | ImageMessage) => void;
177
212
  react: (reaction: Reaction) => void;
213
+ unpin: (unpinMessage: UnpinResponse) => void;
178
214
  }
@@ -1,3 +1,4 @@
1
1
  export interface IActionState {
2
2
  lastExecutedDate: number;
3
+ pinnedMessages: number[];
3
4
  }
@@ -0,0 +1,34 @@
1
+ import { ImageMessage } from '../entities/responses/imageMessage';
2
+ import { Reaction } from '../entities/responses/reaction';
3
+ import { TextMessage } from '../entities/responses/textMessage';
4
+ import { UnpinResponse } from '../entities/responses/unpin';
5
+ import { VideoMessage } from '../entities/responses/videoMessage';
6
+
7
+ export const BotResponseTypes = {
8
+ unpin: 'unpin',
9
+ text: 'text',
10
+ image: 'image',
11
+ video: 'video',
12
+ react: 'react'
13
+ } as const;
14
+
15
+ export type BotResponse =
16
+ | UnpinResponse
17
+ | Reaction
18
+ | TextMessage
19
+ | VideoMessage
20
+ | ImageMessage;
21
+
22
+ export interface IChatResponse {
23
+ kind: keyof typeof BotResponseTypes;
24
+ chatId: number;
25
+ traceId: number | string;
26
+ sourceActionKey: string;
27
+ }
28
+
29
+ export interface IReplyMessage<TType> extends IChatResponse {
30
+ content: TType;
31
+ replyId: number | undefined;
32
+ disableWebPreview: boolean;
33
+ shouldPin: boolean;
34
+ }
package/types/storage.ts CHANGED
@@ -3,6 +3,11 @@ import { IActionState } from './actionState';
3
3
  import { IActionWithState } from './actionWithState';
4
4
 
5
5
  export interface IStorageClient {
6
+ updateStateFor<TActionState extends IActionState>(
7
+ sourceActionKey: string,
8
+ chatId: number,
9
+ update: (state: TActionState) => Promise<void>
10
+ ): Promise<void>;
6
11
  close(): Promise<void>;
7
12
  load<TActionState extends IActionState>(
8
13
  key: string
@@ -1,7 +0,0 @@
1
- export interface IReplyMessage<TType> {
2
- content: TType;
3
- chatId: number;
4
- replyId: number | undefined;
5
- traceId: number | string;
6
- disableWebPreview: boolean;
7
- }