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
@@ -0,0 +1,26 @@
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
+ export declare const BotResponseTypes: {
7
+ readonly unpin: "unpin";
8
+ readonly text: "text";
9
+ readonly image: "image";
10
+ readonly video: "video";
11
+ readonly react: "react";
12
+ };
13
+ export type BotResponse = UnpinResponse | Reaction | TextMessage | VideoMessage | ImageMessage;
14
+ export interface IChatResponse {
15
+ kind: keyof typeof BotResponseTypes;
16
+ chatId: number;
17
+ traceId: number | string;
18
+ sourceActionKey: string;
19
+ }
20
+ export interface IReplyMessage<TType> extends IChatResponse {
21
+ content: TType;
22
+ replyId: number | undefined;
23
+ disableWebPreview: boolean;
24
+ shouldPin: boolean;
25
+ }
26
+ //# sourceMappingURL=response.d.ts.map
@@ -0,0 +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;AAElE,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;IACzB,eAAe,EAAE,MAAM,CAAC;CAC3B;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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BotResponseTypes = void 0;
4
+ exports.BotResponseTypes = {
5
+ unpin: 'unpin',
6
+ text: 'text',
7
+ image: 'image',
8
+ video: 'video',
9
+ react: 'react'
10
+ };
@@ -2,6 +2,7 @@ import { ActionExecutionResult } from '../entities/actionExecutionResult';
2
2
  import { IActionState } from './actionState';
3
3
  import { IActionWithState } from './actionWithState';
4
4
  export interface IStorageClient {
5
+ updateStateFor<TActionState extends IActionState>(sourceActionKey: string, chatId: number, update: (state: TActionState) => Promise<void>): Promise<void>;
5
6
  close(): Promise<void>;
6
7
  load<TActionState extends IActionState>(key: string): Promise<Record<number, TActionState>>;
7
8
  saveMetadata(actions: IActionWithState[], botName: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,YAAY,SAAS,YAAY,EAClC,GAAG,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACzC,YAAY,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,yBAAyB,CACrB,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,qBAAqB,GACzC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC3B,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,YAAY,SAAS,YAAY,EAClC,GAAG,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACzC,YAAY,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,yBAAyB,CACrB,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,qBAAqB,GACzC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
@@ -50,7 +50,7 @@ export class BotInstance {
50
50
  new JsonFileStorage(options.name, options.storagePath);
51
51
  this.api = new TelegramApiService(
52
52
  this.name,
53
- this.telegraf,
53
+ this.telegraf.telegram,
54
54
  this.storage,
55
55
  this.chats
56
56
  );
@@ -118,7 +118,7 @@ export class BotInstance {
118
118
  private async runScheduled() {
119
119
  for (const [chatName, chatId] of this.chats.entries()) {
120
120
  for (const trig of this.scheduled) {
121
- const ctx = this.api.createContextForChat(chatId, trig.name);
121
+ const ctx = this.api.createContextForChat(chatId, trig.key);
122
122
 
123
123
  try {
124
124
  await trig.exec(ctx);
@@ -140,7 +140,7 @@ export class BotInstance {
140
140
  const msg = this.messageQueue.pop()!;
141
141
 
142
142
  for (const cmd of this.commands) {
143
- const ctx = this.api.createContextForMessage(msg);
143
+ const ctx = this.api.createContextForMessage(msg, cmd.key);
144
144
 
145
145
  try {
146
146
  await cmd.exec(ctx);
@@ -4,9 +4,11 @@ import { IStorageClient } from '../../types/storage';
4
4
  import { ImageMessage } from '../responses/imageMessage';
5
5
  import { TextMessage } from '../responses/textMessage';
6
6
  import { VideoMessage } from '../responses/videoMessage';
7
+ import { UnpinResponse } from '../responses/unpin';
7
8
 
8
9
  export class ChatContext {
9
10
  botName: string;
11
+ actionKey: string;
10
12
  interactions: IBotApiInteractions;
11
13
  chatId: number;
12
14
  chatName: string;
@@ -15,6 +17,7 @@ export class ChatContext {
15
17
 
16
18
  constructor(
17
19
  botName: string,
20
+ actionKey: string,
18
21
  interactions: IBotApiInteractions,
19
22
  chatId: number,
20
23
  chatName: string,
@@ -22,6 +25,7 @@ export class ChatContext {
22
25
  storage: IStorageClient
23
26
  ) {
24
27
  this.botName = botName;
28
+ this.actionKey = actionKey;
25
29
  this.interactions = interactions;
26
30
  this.chatId = chatId;
27
31
  this.chatName = chatName;
@@ -29,38 +33,59 @@ export class ChatContext {
29
33
  this.storage = storage;
30
34
  }
31
35
 
32
- sendTextToChat(text: string, disableWebPreview?: boolean) {
36
+ sendTextToChat(
37
+ text: string,
38
+ disableWebPreview?: boolean,
39
+ pinned?: boolean
40
+ ) {
33
41
  this.interactions.respond(
34
42
  new TextMessage(
35
43
  text,
36
44
  this.chatId,
37
45
  undefined,
38
46
  this.traceId,
39
- disableWebPreview ?? false
47
+ disableWebPreview ?? false,
48
+ pinned ?? false,
49
+ this.actionKey
40
50
  )
41
51
  );
42
52
  }
43
53
 
44
- sendImageToChat(name: string) {
54
+ sendImageToChat(name: string, pinned?: boolean) {
45
55
  const filePath = `./content/${name}.png`;
46
56
  this.interactions.respond(
47
57
  new ImageMessage(
48
58
  { source: resolve(filePath) },
49
59
  this.chatId,
50
60
  undefined,
51
- this.traceId
61
+ this.traceId,
62
+ pinned ?? false,
63
+ this.actionKey
52
64
  )
53
65
  );
54
66
  }
55
67
 
56
- sendVideoToChat(name: string) {
68
+ sendVideoToChat(name: string, pinned?: boolean) {
57
69
  const filePath = `./content/${name}.mp4`;
58
70
  this.interactions.respond(
59
71
  new VideoMessage(
60
72
  { source: resolve(filePath) },
61
73
  this.chatId,
62
74
  undefined,
63
- this.traceId
75
+ this.traceId,
76
+ pinned ?? false,
77
+ this.actionKey
78
+ )
79
+ );
80
+ }
81
+
82
+ unpinMessage(messageId: number) {
83
+ this.interactions.unpin(
84
+ new UnpinResponse(
85
+ messageId,
86
+ this.chatId,
87
+ this.traceId,
88
+ this.actionKey
64
89
  )
65
90
  );
66
91
  }
@@ -23,6 +23,7 @@ export class MessageContext<
23
23
 
24
24
  constructor(
25
25
  botName: string,
26
+ scheduledKey: string,
26
27
  interactions: IBotApiInteractions,
27
28
  chatId: number,
28
29
  chatName: string,
@@ -33,7 +34,15 @@ export class MessageContext<
33
34
  fromUserName: string,
34
35
  storage: IStorageClient
35
36
  ) {
36
- super(botName, interactions, chatId, chatName, traceId, storage);
37
+ super(
38
+ botName,
39
+ scheduledKey,
40
+ interactions,
41
+ chatId,
42
+ chatName,
43
+ traceId,
44
+ storage
45
+ );
37
46
 
38
47
  this.messageId = messageId;
39
48
  this.messageText = messageText;
@@ -59,45 +68,57 @@ export class MessageContext<
59
68
  );
60
69
  }
61
70
 
62
- replyWithText(text: string, disableWebPreview?: boolean) {
71
+ replyWithText(text: string, disableWebPreview?: boolean, pinned?: boolean) {
63
72
  this.interactions.respond(
64
73
  new TextMessage(
65
74
  text,
66
75
  this.chatId,
67
76
  this.messageId,
68
77
  this.traceId,
69
- disableWebPreview ?? false
78
+ disableWebPreview ?? false,
79
+ pinned ?? false,
80
+ this.actionKey
70
81
  )
71
82
  );
72
83
  }
73
84
 
74
- replyWithImage(name: string) {
85
+ replyWithImage(name: string, pinned?: boolean) {
75
86
  const filePath = `./content/${name}.png`;
76
87
  this.interactions.respond(
77
88
  new ImageMessage(
78
89
  { source: resolve(filePath) },
79
90
  this.chatId,
80
91
  this.messageId,
81
- this.traceId
92
+ this.traceId,
93
+ pinned ?? false,
94
+ this.actionKey
82
95
  )
83
96
  );
84
97
  }
85
98
 
86
- replyWithVideo(name: string) {
99
+ replyWithVideo(name: string, pinned?: boolean) {
87
100
  const filePath = `./content/${name}.mp4`;
88
101
  this.interactions.respond(
89
102
  new VideoMessage(
90
103
  { source: resolve(filePath) },
91
104
  this.chatId,
92
105
  this.messageId,
93
- this.traceId
106
+ this.traceId,
107
+ pinned ?? false,
108
+ this.actionKey
94
109
  )
95
110
  );
96
111
  }
97
112
 
98
113
  react(emoji: TelegramEmoji) {
99
114
  this.interactions.react(
100
- new Reaction(this.traceId, this.chatId, this.messageId, emoji)
115
+ new Reaction(
116
+ this.traceId,
117
+ this.chatId,
118
+ this.messageId,
119
+ emoji,
120
+ this.actionKey
121
+ )
101
122
  );
102
123
  }
103
124
  }
@@ -1,22 +1,30 @@
1
1
  import { InputFile } from 'telegraf/types';
2
- import { IReplyMessage } from '../../types/replyMessage';
2
+ import { BotResponseTypes, IReplyMessage } from '../../types/response';
3
3
 
4
4
  export class ImageMessage implements IReplyMessage<InputFile> {
5
+ kind = BotResponseTypes.image;
6
+
5
7
  content: InputFile;
6
8
  chatId: number;
7
9
  replyId: number | undefined;
8
10
  traceId: string | number;
9
11
  disableWebPreview = false;
12
+ shouldPin: boolean;
13
+ sourceActionKey: string;
10
14
 
11
15
  constructor(
12
16
  image: InputFile,
13
17
  chatId: number,
14
18
  replyId: number | undefined,
15
- traceId: number | string
19
+ traceId: number | string,
20
+ pinned: boolean,
21
+ sourceActionKey: string
16
22
  ) {
17
23
  this.content = image;
18
24
  this.chatId = chatId;
19
25
  this.replyId = replyId;
20
26
  this.traceId = traceId;
27
+ this.shouldPin = pinned;
28
+ this.sourceActionKey = sourceActionKey;
21
29
  }
22
30
  }
@@ -1,20 +1,26 @@
1
1
  import { TelegramEmoji } from 'telegraf/types';
2
+ import { BotResponseTypes, IChatResponse } from '../../types/response';
3
+
4
+ export class Reaction implements IChatResponse {
5
+ kind = BotResponseTypes.react;
2
6
 
3
- export class Reaction {
4
7
  chatId: number;
5
8
  messageId: number;
6
9
  traceId: number | string;
7
10
  emoji: TelegramEmoji;
11
+ sourceActionKey: string;
8
12
 
9
13
  constructor(
10
14
  traceId: number | string,
11
15
  chatId: number,
12
16
  messageId: number,
13
- emoji: TelegramEmoji
17
+ emoji: TelegramEmoji,
18
+ sourceActionKey: string
14
19
  ) {
15
20
  this.chatId = chatId;
16
21
  this.messageId = messageId;
17
22
  this.emoji = emoji;
18
23
  this.traceId = traceId;
24
+ this.sourceActionKey = sourceActionKey;
19
25
  }
20
26
  }
@@ -1,23 +1,31 @@
1
- import { IReplyMessage } from '../../types/replyMessage';
1
+ import { BotResponseTypes, IReplyMessage } from '../../types/response';
2
2
 
3
3
  export class TextMessage implements IReplyMessage<string> {
4
+ kind = BotResponseTypes.text;
5
+
4
6
  content: string;
5
7
  chatId: number;
6
8
  replyId: number | undefined;
7
9
  traceId: string | number;
8
10
  disableWebPreview: boolean;
11
+ shouldPin: boolean;
12
+ sourceActionKey: string;
9
13
 
10
14
  constructor(
11
15
  text: string,
12
16
  chatId: number,
13
17
  replyId: number | undefined,
14
18
  traceId: string | number,
15
- disableWebPreview: boolean
19
+ disableWebPreview: boolean,
20
+ pinned: boolean,
21
+ sourceActionKey: string
16
22
  ) {
17
23
  this.content = text;
18
24
  this.chatId = chatId;
19
25
  this.replyId = replyId;
20
26
  this.traceId = traceId;
21
27
  this.disableWebPreview = disableWebPreview;
28
+ this.shouldPin = pinned;
29
+ this.sourceActionKey = sourceActionKey;
22
30
  }
23
31
  }
@@ -0,0 +1,22 @@
1
+ import { BotResponseTypes, IChatResponse } from '../../types/response';
2
+
3
+ export class UnpinResponse implements IChatResponse {
4
+ kind = BotResponseTypes.unpin;
5
+
6
+ messageId: number;
7
+ chatId: number;
8
+ traceId: number | string;
9
+ sourceActionKey: string;
10
+
11
+ constructor(
12
+ messageId: number,
13
+ chatId: number,
14
+ traceId: number | string,
15
+ sourceActionKey: string
16
+ ) {
17
+ this.messageId = messageId;
18
+ this.chatId = chatId;
19
+ this.traceId = traceId;
20
+ this.sourceActionKey = sourceActionKey;
21
+ }
22
+ }
@@ -1,22 +1,30 @@
1
1
  import { InputFile } from 'telegraf/types';
2
- import { IReplyMessage } from '../../types/replyMessage';
2
+ import { BotResponseTypes, IReplyMessage } from '../../types/response';
3
3
 
4
4
  export class VideoMessage implements IReplyMessage<InputFile> {
5
+ kind = BotResponseTypes.video;
6
+
5
7
  content: InputFile;
6
8
  chatId: number;
7
9
  replyId: number | undefined;
8
10
  traceId: string | number;
9
11
  disableWebPreview = false;
12
+ shouldPin: boolean;
13
+ sourceActionKey: string;
10
14
 
11
15
  constructor(
12
16
  video: InputFile,
13
17
  chatId: number,
14
18
  replyId: number | undefined,
15
- traceId: number | string
19
+ traceId: number | string,
20
+ pinned: boolean,
21
+ sourceActionKey: string
16
22
  ) {
17
23
  this.content = video;
18
24
  this.chatId = chatId;
19
25
  this.replyId = replyId;
20
26
  this.traceId = traceId;
27
+ this.shouldPin = pinned;
28
+ this.sourceActionKey = sourceActionKey;
21
29
  }
22
30
  }
@@ -1,5 +1,6 @@
1
1
  import { IActionState } from '../../types/actionState';
2
2
 
3
3
  export class ActionStateBase implements IActionState {
4
+ pinnedMessages: number[] = [];
4
5
  lastExecutedDate = 0;
5
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chz-telegram-bot",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "async-sema": "^3.1.1",
@@ -120,4 +120,19 @@ export class JsonFileStorage implements IStorageClient {
120
120
  async close(): Promise<void> {
121
121
  await this.semaphore.acquire();
122
122
  }
123
+
124
+ async updateStateFor<TActionState extends IActionState>(
125
+ sourceActionKey: string,
126
+ chatId: number,
127
+ update: (state: TActionState) => Promise<void>
128
+ ) {
129
+ await this.lock(async () => {
130
+ const data = await this.loadInternal(sourceActionKey);
131
+ const state = data[chatId] as TActionState;
132
+
133
+ await update(state);
134
+
135
+ await this.save(data, sourceActionKey);
136
+ });
137
+ }
123
138
  }