chz-telegram-bot 0.3.8 → 0.3.9
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.
- package/dist/entities/botInstance.d.ts.map +1 -1
- package/dist/entities/botInstance.js +0 -1
- package/dist/services/actionProcessingService.d.ts.map +1 -1
- package/dist/services/actionProcessingService.js +4 -2
- package/dist/services/jsonFileStorage.d.ts +5 -4
- package/dist/services/jsonFileStorage.d.ts.map +1 -1
- package/dist/services/jsonFileStorage.js +40 -29
- package/dist/types/storage.d.ts +1 -1
- package/dist/types/storage.d.ts.map +1 -1
- package/entities/botInstance.ts +0 -2
- package/package.json +1 -1
- package/services/actionProcessingService.ts +9 -5
- package/services/jsonFileStorage.ts +57 -41
- package/types/storage.ts +1 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"botInstance.d.ts","sourceRoot":"","sources":["../../entities/botInstance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAElE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE;YACL,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;YACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3C,aAAa,EAAE,iBAAiB,EAAE,CAAC;SACtC,CAAC;QACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE;YACP,aAAa,CAAC,EAAE,cAAc,CAAC;YAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;YACjB,SAAS,CAAC,EAAE,UAAU,CAAC;SAC1B,CAAC;KACL;
|
|
1
|
+
{"version":3,"file":"botInstance.d.ts","sourceRoot":"","sources":["../../entities/botInstance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA0B;IAElE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE;YACL,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;YACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3C,aAAa,EAAE,iBAAiB,EAAE,CAAC;SACtC,CAAC;QACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE;YACP,aAAa,CAAC,EAAE,cAAc,CAAC;YAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;YACjB,SAAS,CAAC,EAAE,UAAU,CAAC;SAC1B,CAAC;KACL;IAwBK,KAAK,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACL,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,iBAAiB,EAAE,CAAC;KACtC,EACD,eAAe,CAAC,EAAE,OAAO,EACzB,gCAAgC,CAAC,EAAE,OAAO;IAiBxC,IAAI,CAAC,IAAI,EAAE,MAAM;CAY1B"}
|
|
@@ -21,7 +21,6 @@ class BotInstance {
|
|
|
21
21
|
options.services?.storageClient ??
|
|
22
22
|
new jsonFileStorage_1.JsonFileStorage(options.name, actions, options.storagePath);
|
|
23
23
|
this.actionProcessingService = new actionProcessingService_1.ActionProcessingService(this.name, options.chats, this.storage, this.scheduler, this.logger);
|
|
24
|
-
this.storage.saveMetadata(actions, this.name);
|
|
25
24
|
}
|
|
26
25
|
async start(token, actions, scheduledPeriod, verboseLoggingForIncomingMessage) {
|
|
27
26
|
this.actionProcessingService.initialize(token, actions, scheduledPeriod, verboseLoggingForIncomingMessage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actionProcessingService.d.ts","sourceRoot":"","sources":["../../services/actionProcessingService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAuB,MAAM,qBAAqB,CAAC;AAEnE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAMtE,qBAAa,uBAAuB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAC1D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA2B;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAElE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAY;gBAGxB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,UAAU,EACrB,MAAM,EAAE,OAAO;IA4Bb,UAAU,CACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACL,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,iBAAiB,EAAE,CAAC;KACtC,EACD,eAAe,CAAC,EAAE,OAAO,EACzB,gCAAgC,CAAC,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"actionProcessingService.d.ts","sourceRoot":"","sources":["../../services/actionProcessingService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAuB,MAAM,qBAAqB,CAAC;AAEnE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAMtE,qBAAa,uBAAuB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAC1D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA2B;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAElE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAY;gBAGxB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,UAAU,EACrB,MAAM,EAAE,OAAO;IA4Bb,UAAU,CACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACL,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,SAAS,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,iBAAiB,EAAE,CAAC;KACtC,EACD,eAAe,CAAC,EAAE,OAAO,EACzB,gCAAgC,CAAC,EAAE,OAAO;IAsD9C,IAAI,CAAC,IAAI,EAAE,MAAM;CAGpB"}
|
|
@@ -21,16 +21,18 @@ class ActionProcessingService {
|
|
|
21
21
|
this.telegraf = new telegraf_1.Telegraf(token);
|
|
22
22
|
const api = new telegramApi_1.TelegramApiService(this.botName, this.telegraf.telegram, this.storage, this.logger, (capture, id, chatInfo, traceId) => this.commandProcessor.captureRegistrationCallback(capture, id, chatInfo, traceId));
|
|
23
23
|
const botInfo = await this.telegraf.telegram.getMe();
|
|
24
|
-
|
|
24
|
+
const commandActions = actions.commands.length > 0
|
|
25
25
|
? [
|
|
26
26
|
(0, helpAction_1.buildHelpCommand)(actions.commands
|
|
27
27
|
.map((x) => x.readmeFactory(botInfo.username))
|
|
28
28
|
.filter((x) => !!x), botInfo.username),
|
|
29
29
|
...actions.commands
|
|
30
30
|
]
|
|
31
|
-
: []
|
|
31
|
+
: [];
|
|
32
|
+
this.commandProcessor.initialize(api, this.telegraf, commandActions, verboseLoggingForIncomingMessage ?? false);
|
|
32
33
|
this.inlineQueryProcessor.initialize(api, this.telegraf, actions.inlineQueries, 300);
|
|
33
34
|
this.scheduledProcessor.initialize(api, actions.scheduled, scheduledPeriod ?? (0, timeConvertions_1.hoursToSeconds)(1));
|
|
35
|
+
this.storage.saveMetadata([...actions.scheduled, ...commandActions]);
|
|
34
36
|
this.telegraf.launch();
|
|
35
37
|
}
|
|
36
38
|
stop(code) {
|
|
@@ -2,17 +2,18 @@ import { IStorageClient } from '../types/storage';
|
|
|
2
2
|
import { IActionState } from '../types/actionState';
|
|
3
3
|
import { IActionWithState, ActionKey } from '../types/action';
|
|
4
4
|
export declare class JsonFileStorage implements IStorageClient {
|
|
5
|
+
private readonly filePaths;
|
|
5
6
|
private readonly locks;
|
|
6
7
|
private readonly cache;
|
|
7
8
|
private readonly storagePath;
|
|
8
9
|
private readonly botName;
|
|
9
10
|
constructor(botName: string, actions: IActionWithState<IActionState>[], path?: string);
|
|
10
11
|
private lock;
|
|
11
|
-
private
|
|
12
|
-
private
|
|
13
|
-
private
|
|
12
|
+
private tryGetFromCache;
|
|
13
|
+
private loadFromFile;
|
|
14
|
+
private updateCacheAndSaveToFile;
|
|
14
15
|
load<TActionState extends IActionState>(key: ActionKey): Promise<Record<number, TActionState>>;
|
|
15
|
-
saveMetadata(actions: IActionWithState<IActionState>[]
|
|
16
|
+
saveMetadata(actions: IActionWithState<IActionState>[]): Promise<void>;
|
|
16
17
|
getActionState<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number): Promise<TActionState>;
|
|
17
18
|
saveActionExecutionResult<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, state: TActionState): Promise<void>;
|
|
18
19
|
close(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonFileStorage.d.ts","sourceRoot":"","sources":["../../services/jsonFileStorage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"jsonFileStorage.d.ts","sourceRoot":"","sources":["../../services/jsonFileStorage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM9D,qBAAa,eAAgB,YAAW,cAAc;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAG7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,EACzC,IAAI,CAAC,EAAE,MAAM;YAqBH,IAAI;IAclB,OAAO,CAAC,eAAe;YAIT,YAAY;YAwBZ,wBAAwB;IAgBhC,IAAI,CAAC,YAAY,SAAS,YAAY,EAAE,GAAG,EAAE,SAAS;IAStD,YAAY,CAAC,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE;IAQtD,cAAc,CAAC,YAAY,SAAS,YAAY,EAClD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM;IAWZ,yBAAyB,CAAC,YAAY,SAAS,YAAY,EAC7D,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY;IAajB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,cAAc,CAAC,YAAY,SAAS,YAAY,EAClD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC;CAiBrD"}
|
|
@@ -4,8 +4,12 @@ exports.JsonFileStorage = void 0;
|
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const promises_1 = require("fs/promises");
|
|
6
6
|
const async_sema_1 = require("async-sema");
|
|
7
|
+
function buildPath(storagePath, botName, actionKey) {
|
|
8
|
+
return `${storagePath}/${botName}/${actionKey.replaceAll(':', '/')}.json`;
|
|
9
|
+
}
|
|
7
10
|
class JsonFileStorage {
|
|
8
11
|
constructor(botName, actions, path) {
|
|
12
|
+
this.filePaths = new Map();
|
|
9
13
|
this.locks = new Map();
|
|
10
14
|
this.cache = new Map();
|
|
11
15
|
this.botName = botName;
|
|
@@ -17,6 +21,7 @@ class JsonFileStorage {
|
|
|
17
21
|
}
|
|
18
22
|
for (const action of actions) {
|
|
19
23
|
this.locks.set(action.key, new async_sema_1.Sema(1));
|
|
24
|
+
this.filePaths.set(action.key, buildPath(this.storagePath, this.botName, action.key));
|
|
20
25
|
}
|
|
21
26
|
}
|
|
22
27
|
async lock(key, action) {
|
|
@@ -31,50 +36,55 @@ class JsonFileStorage {
|
|
|
31
36
|
lock.release();
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
tryGetFromCache(key) {
|
|
40
|
+
return this.cache.get(key);
|
|
41
|
+
}
|
|
42
|
+
async loadFromFile(key) {
|
|
43
|
+
if (!this.filePaths.has(key))
|
|
44
|
+
this.filePaths.set(key, buildPath(this.storagePath, this.botName, key));
|
|
45
|
+
const targetPath = this.filePaths.get(key);
|
|
46
|
+
const fileContent = await (0, promises_1.readFile)(targetPath, {
|
|
47
|
+
encoding: 'utf-8',
|
|
48
|
+
flag: 'a+'
|
|
49
|
+
});
|
|
50
|
+
if (fileContent) {
|
|
51
|
+
const data = JSON.parse(fileContent);
|
|
52
|
+
this.cache.set(key, data);
|
|
45
53
|
}
|
|
46
54
|
return (this.cache.get(key) ?? {});
|
|
47
55
|
}
|
|
48
|
-
async
|
|
56
|
+
async updateCacheAndSaveToFile(data, key) {
|
|
49
57
|
this.cache.set(key, data);
|
|
50
|
-
|
|
58
|
+
if (!this.filePaths.has(key))
|
|
59
|
+
this.filePaths.set(key, buildPath(this.storagePath, this.botName, key));
|
|
60
|
+
const targetPath = this.filePaths.get(key);
|
|
51
61
|
await (0, promises_1.writeFile)(targetPath, JSON.stringify(data), { flag: 'w+' });
|
|
52
62
|
}
|
|
53
|
-
buidPathFromKey(key) {
|
|
54
|
-
return `${this.storagePath}/${this.botName}/${key.replaceAll(':', '/')}.json`;
|
|
55
|
-
}
|
|
56
63
|
async load(key) {
|
|
57
|
-
return
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
return (this.tryGetFromCache(key) ??
|
|
65
|
+
(await this.lock(key, async () => {
|
|
66
|
+
return await this.loadFromFile(key);
|
|
67
|
+
})));
|
|
60
68
|
}
|
|
61
|
-
async saveMetadata(actions
|
|
62
|
-
const targetPath = this.
|
|
69
|
+
async saveMetadata(actions) {
|
|
70
|
+
const targetPath = `${this.storagePath}/${this.botName}/Metadata-${this.botName}.json`;
|
|
63
71
|
await (0, promises_1.writeFile)(targetPath, JSON.stringify(actions), {
|
|
64
72
|
flag: 'w+'
|
|
65
73
|
});
|
|
66
74
|
}
|
|
67
75
|
async getActionState(action, chatId) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
const value = this.tryGetFromCache(action.key) ??
|
|
77
|
+
(await this.lock(action.key, async () => {
|
|
78
|
+
return await this.loadFromFile(action.key);
|
|
79
|
+
}));
|
|
80
|
+
return Object.assign(action.stateConstructor(), value[chatId]);
|
|
72
81
|
}
|
|
73
82
|
async saveActionExecutionResult(action, chatId, state) {
|
|
74
83
|
return await this.lock(action.key, async () => {
|
|
75
|
-
const data =
|
|
84
|
+
const data = this.tryGetFromCache(action.key) ??
|
|
85
|
+
(await this.loadFromFile(action.key));
|
|
76
86
|
data[chatId] = state;
|
|
77
|
-
await this.
|
|
87
|
+
await this.updateCacheAndSaveToFile(data, action.key);
|
|
78
88
|
});
|
|
79
89
|
}
|
|
80
90
|
async close() {
|
|
@@ -84,10 +94,11 @@ class JsonFileStorage {
|
|
|
84
94
|
}
|
|
85
95
|
async updateStateFor(action, chatId, update) {
|
|
86
96
|
await this.lock(action.key, async () => {
|
|
87
|
-
const data =
|
|
97
|
+
const data = this.tryGetFromCache(action.key) ??
|
|
98
|
+
(await this.loadFromFile(action.key));
|
|
88
99
|
const state = Object.assign(action.stateConstructor(), data[chatId]);
|
|
89
100
|
await update(state);
|
|
90
|
-
await this.
|
|
101
|
+
await this.updateCacheAndSaveToFile(data, action.key);
|
|
91
102
|
});
|
|
92
103
|
}
|
|
93
104
|
}
|
package/dist/types/storage.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export interface IStorageClient {
|
|
|
4
4
|
updateStateFor<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, update: (state: TActionState) => Promise<void>): Promise<void>;
|
|
5
5
|
close(): Promise<void>;
|
|
6
6
|
load<TActionState extends IActionState>(key: ActionKey): Promise<Record<number, TActionState>>;
|
|
7
|
-
saveMetadata<TActionState extends IActionState>(actions: IActionWithState<TActionState>[]
|
|
7
|
+
saveMetadata<TActionState extends IActionState>(actions: IActionWithState<TActionState>[]): Promise<void>;
|
|
8
8
|
getActionState<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number): Promise<TActionState>;
|
|
9
9
|
saveActionExecutionResult<TActionState extends IActionState>(action: IActionWithState<TActionState>, chatId: number, state: TActionState): Promise<void>;
|
|
10
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,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,SAAS,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACzC,YAAY,CAAC,YAAY,SAAS,YAAY,EAC1C,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../types/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,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,SAAS,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACzC,YAAY,CAAC,YAAY,SAAS,YAAY,EAC1C,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,cAAc,CAAC,YAAY,SAAS,YAAY,EAC5C,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,yBAAyB,CAAC,YAAY,SAAS,YAAY,EACvD,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
|
package/entities/botInstance.ts
CHANGED
package/package.json
CHANGED
|
@@ -85,10 +85,7 @@ export class ActionProcessingService {
|
|
|
85
85
|
);
|
|
86
86
|
|
|
87
87
|
const botInfo = await this.telegraf.telegram.getMe();
|
|
88
|
-
|
|
89
|
-
this.commandProcessor.initialize(
|
|
90
|
-
api,
|
|
91
|
-
this.telegraf,
|
|
88
|
+
const commandActions =
|
|
92
89
|
actions.commands.length > 0
|
|
93
90
|
? [
|
|
94
91
|
buildHelpCommand(
|
|
@@ -99,7 +96,12 @@ export class ActionProcessingService {
|
|
|
99
96
|
),
|
|
100
97
|
...actions.commands
|
|
101
98
|
]
|
|
102
|
-
: []
|
|
99
|
+
: [];
|
|
100
|
+
|
|
101
|
+
this.commandProcessor.initialize(
|
|
102
|
+
api,
|
|
103
|
+
this.telegraf,
|
|
104
|
+
commandActions,
|
|
103
105
|
verboseLoggingForIncomingMessage ?? false
|
|
104
106
|
);
|
|
105
107
|
this.inlineQueryProcessor.initialize(
|
|
@@ -114,6 +116,8 @@ export class ActionProcessingService {
|
|
|
114
116
|
scheduledPeriod ?? hoursToSeconds(1 as Hours)
|
|
115
117
|
);
|
|
116
118
|
|
|
119
|
+
this.storage.saveMetadata([...actions.scheduled, ...commandActions]);
|
|
120
|
+
|
|
117
121
|
this.telegraf.launch();
|
|
118
122
|
}
|
|
119
123
|
|
|
@@ -5,7 +5,12 @@ import { IStorageClient } from '../types/storage';
|
|
|
5
5
|
import { IActionState } from '../types/actionState';
|
|
6
6
|
import { IActionWithState, ActionKey } from '../types/action';
|
|
7
7
|
|
|
8
|
+
function buildPath(storagePath: string, botName: string, actionKey: string) {
|
|
9
|
+
return `${storagePath}/${botName}/${actionKey.replaceAll(':', '/')}.json`;
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
export class JsonFileStorage implements IStorageClient {
|
|
13
|
+
private readonly filePaths = new Map<ActionKey, string>();
|
|
9
14
|
private readonly locks = new Map<ActionKey, Semaphore>();
|
|
10
15
|
private readonly cache: Map<string, Record<number, IActionState>>;
|
|
11
16
|
private readonly storagePath: string;
|
|
@@ -28,6 +33,10 @@ export class JsonFileStorage implements IStorageClient {
|
|
|
28
33
|
|
|
29
34
|
for (const action of actions) {
|
|
30
35
|
this.locks.set(action.key, new Semaphore(1));
|
|
36
|
+
this.filePaths.set(
|
|
37
|
+
action.key,
|
|
38
|
+
buildPath(this.storagePath, this.botName, action.key)
|
|
39
|
+
);
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
|
|
@@ -45,58 +54,61 @@ export class JsonFileStorage implements IStorageClient {
|
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
private
|
|
57
|
+
private tryGetFromCache<TActionState extends IActionState>(key: ActionKey) {
|
|
58
|
+
return this.cache.get(key) as Record<number, TActionState> | undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private async loadFromFile<TActionState extends IActionState>(
|
|
49
62
|
key: ActionKey
|
|
50
63
|
) {
|
|
51
|
-
if (!this.
|
|
52
|
-
|
|
64
|
+
if (!this.filePaths.has(key))
|
|
65
|
+
this.filePaths.set(
|
|
66
|
+
key,
|
|
67
|
+
buildPath(this.storagePath, this.botName, key)
|
|
68
|
+
);
|
|
69
|
+
const targetPath = this.filePaths.get(key)!;
|
|
53
70
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
const fileContent = await readFile(targetPath, {
|
|
72
|
+
encoding: 'utf-8',
|
|
73
|
+
flag: 'a+'
|
|
74
|
+
});
|
|
58
75
|
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
if (fileContent) {
|
|
77
|
+
const data = JSON.parse(fileContent);
|
|
61
78
|
|
|
62
|
-
|
|
63
|
-
}
|
|
79
|
+
this.cache.set(key, data);
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
return (this.cache.get(key) ?? {}) as Record<number, TActionState>;
|
|
67
83
|
}
|
|
68
84
|
|
|
69
|
-
private async
|
|
85
|
+
private async updateCacheAndSaveToFile<TActionState extends IActionState>(
|
|
70
86
|
data: Record<number, TActionState>,
|
|
71
87
|
key: ActionKey
|
|
72
88
|
) {
|
|
73
89
|
this.cache.set(key, data);
|
|
74
90
|
|
|
75
|
-
|
|
91
|
+
if (!this.filePaths.has(key))
|
|
92
|
+
this.filePaths.set(
|
|
93
|
+
key,
|
|
94
|
+
buildPath(this.storagePath, this.botName, key)
|
|
95
|
+
);
|
|
96
|
+
const targetPath = this.filePaths.get(key)!;
|
|
76
97
|
|
|
77
98
|
await writeFile(targetPath, JSON.stringify(data), { flag: 'w+' });
|
|
78
99
|
}
|
|
79
100
|
|
|
80
|
-
private buidPathFromKey(key: ActionKey) {
|
|
81
|
-
return `${this.storagePath}/${this.botName}/${key.replaceAll(
|
|
82
|
-
':',
|
|
83
|
-
'/'
|
|
84
|
-
)}.json`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
101
|
async load<TActionState extends IActionState>(key: ActionKey) {
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
return (
|
|
103
|
+
this.tryGetFromCache<TActionState>(key) ??
|
|
104
|
+
(await this.lock(key, async () => {
|
|
105
|
+
return await this.loadFromFile<TActionState>(key);
|
|
106
|
+
}))
|
|
107
|
+
);
|
|
91
108
|
}
|
|
92
109
|
|
|
93
|
-
async saveMetadata(
|
|
94
|
-
|
|
95
|
-
botName: string
|
|
96
|
-
) {
|
|
97
|
-
const targetPath = this.buidPathFromKey(
|
|
98
|
-
`Metadata-${botName}` as ActionKey
|
|
99
|
-
);
|
|
110
|
+
async saveMetadata(actions: IActionWithState<IActionState>[]) {
|
|
111
|
+
const targetPath = `${this.storagePath}/${this.botName}/Metadata-${this.botName}.json`;
|
|
100
112
|
|
|
101
113
|
await writeFile(targetPath, JSON.stringify(actions), {
|
|
102
114
|
flag: 'w+'
|
|
@@ -107,14 +119,13 @@ export class JsonFileStorage implements IStorageClient {
|
|
|
107
119
|
action: IActionWithState<TActionState>,
|
|
108
120
|
chatId: number
|
|
109
121
|
) {
|
|
110
|
-
|
|
111
|
-
|
|
122
|
+
const value =
|
|
123
|
+
this.tryGetFromCache<TActionState>(action.key) ??
|
|
124
|
+
(await this.lock(action.key, async () => {
|
|
125
|
+
return await this.loadFromFile<TActionState>(action.key);
|
|
126
|
+
}));
|
|
112
127
|
|
|
113
|
-
|
|
114
|
-
action.stateConstructor(),
|
|
115
|
-
data[chatId]
|
|
116
|
-
) as TActionState;
|
|
117
|
-
});
|
|
128
|
+
return Object.assign(action.stateConstructor(), value[chatId]);
|
|
118
129
|
}
|
|
119
130
|
|
|
120
131
|
async saveActionExecutionResult<TActionState extends IActionState>(
|
|
@@ -123,11 +134,13 @@ export class JsonFileStorage implements IStorageClient {
|
|
|
123
134
|
state: TActionState
|
|
124
135
|
) {
|
|
125
136
|
return await this.lock(action.key, async () => {
|
|
126
|
-
const data =
|
|
137
|
+
const data =
|
|
138
|
+
this.tryGetFromCache<TActionState>(action.key) ??
|
|
139
|
+
(await this.loadFromFile<TActionState>(action.key));
|
|
127
140
|
|
|
128
141
|
data[chatId] = state;
|
|
129
142
|
|
|
130
|
-
await this.
|
|
143
|
+
await this.updateCacheAndSaveToFile(data, action.key);
|
|
131
144
|
});
|
|
132
145
|
}
|
|
133
146
|
|
|
@@ -143,7 +156,10 @@ export class JsonFileStorage implements IStorageClient {
|
|
|
143
156
|
update: (state: TActionState) => Promise<void>
|
|
144
157
|
) {
|
|
145
158
|
await this.lock(action.key, async () => {
|
|
146
|
-
const data =
|
|
159
|
+
const data =
|
|
160
|
+
this.tryGetFromCache<TActionState>(action.key) ??
|
|
161
|
+
(await this.loadFromFile<TActionState>(action.key));
|
|
162
|
+
|
|
147
163
|
const state = Object.assign(
|
|
148
164
|
action.stateConstructor(),
|
|
149
165
|
data[chatId]
|
|
@@ -151,7 +167,7 @@ export class JsonFileStorage implements IStorageClient {
|
|
|
151
167
|
|
|
152
168
|
await update(state);
|
|
153
169
|
|
|
154
|
-
await this.
|
|
170
|
+
await this.updateCacheAndSaveToFile(data, action.key);
|
|
155
171
|
});
|
|
156
172
|
}
|
|
157
173
|
}
|
package/types/storage.ts
CHANGED
|
@@ -12,8 +12,7 @@ export interface IStorageClient {
|
|
|
12
12
|
key: ActionKey
|
|
13
13
|
): Promise<Record<number, TActionState>>;
|
|
14
14
|
saveMetadata<TActionState extends IActionState>(
|
|
15
|
-
actions: IActionWithState<TActionState>[]
|
|
16
|
-
botName: string
|
|
15
|
+
actions: IActionWithState<TActionState>[]
|
|
17
16
|
): Promise<void>;
|
|
18
17
|
getActionState<TActionState extends IActionState>(
|
|
19
18
|
action: IActionWithState<TActionState>,
|