chz-telegram-bot 0.3.7 → 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/entities/context/baseContext.d.ts +35 -0
- package/dist/entities/context/baseContext.d.ts.map +1 -0
- package/dist/entities/context/baseContext.js +32 -0
- package/dist/entities/context/chatContext.d.ts +4 -27
- package/dist/entities/context/chatContext.d.ts.map +1 -1
- package/dist/entities/context/chatContext.js +3 -19
- package/dist/entities/context/inlineQueryContext.d.ts +2 -15
- package/dist/entities/context/inlineQueryContext.d.ts.map +1 -1
- package/dist/entities/context/inlineQueryContext.js +3 -4
- package/dist/entities/context/messageContext.d.ts +2 -1
- package/dist/entities/context/messageContext.d.ts.map +1 -1
- package/dist/entities/context/replyContext.d.ts +2 -20
- package/dist/entities/context/replyContext.d.ts.map +1 -1
- package/dist/entities/context/replyContext.js +3 -5
- package/dist/services/actionProcessingService.d.ts.map +1 -1
- package/dist/services/actionProcessingService.js +4 -2
- package/dist/services/actionProcessors/baseProcessor.d.ts +20 -0
- package/dist/services/actionProcessors/baseProcessor.d.ts.map +1 -0
- package/dist/services/actionProcessors/baseProcessor.js +29 -0
- package/dist/services/actionProcessors/commandActionProcessor.d.ts +2 -7
- package/dist/services/actionProcessors/commandActionProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/commandActionProcessor.js +12 -27
- package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts +2 -7
- package/dist/services/actionProcessors/inlineQueryActionProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/inlineQueryActionProcessor.js +6 -15
- package/dist/services/actionProcessors/scheduledActionProcessor.d.ts +2 -6
- package/dist/services/actionProcessors/scheduledActionProcessor.d.ts.map +1 -1
- package/dist/services/actionProcessors/scheduledActionProcessor.js +5 -14
- 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/action.d.ts +3 -0
- package/dist/types/action.d.ts.map +1 -1
- package/dist/types/storage.d.ts +1 -1
- package/dist/types/storage.d.ts.map +1 -1
- package/entities/botInstance.ts +0 -2
- package/entities/context/baseContext.ts +58 -0
- package/entities/context/chatContext.ts +8 -45
- package/entities/context/inlineQueryContext.ts +3 -20
- package/entities/context/messageContext.ts +2 -1
- package/entities/context/replyContext.ts +5 -25
- package/package.json +1 -1
- package/services/actionProcessingService.ts +9 -5
- package/services/actionProcessors/baseProcessor.ts +60 -0
- package/services/actionProcessors/commandActionProcessor.ts +19 -42
- package/services/actionProcessors/inlineQueryActionProcessor.ts +16 -32
- package/services/actionProcessors/scheduledActionProcessor.ts +7 -23
- package/services/jsonFileStorage.ts +57 -41
- package/types/action.ts +3 -0
- package/types/storage.ts +1 -2
|
@@ -4,7 +4,6 @@ import { CommandAction } from '../../entities/actions/commandAction';
|
|
|
4
4
|
import { ReplyCaptureAction } from '../../entities/actions/replyCaptureAction';
|
|
5
5
|
import { MessageContext } from '../../entities/context/messageContext';
|
|
6
6
|
import { ReplyContext } from '../../entities/context/replyContext';
|
|
7
|
-
import { IActionWithState } from '../../types/action';
|
|
8
7
|
import { IActionState } from '../../types/actionState';
|
|
9
8
|
import { ILogger } from '../../types/logger';
|
|
10
9
|
import { IScheduler } from '../../types/scheduler';
|
|
@@ -18,17 +17,11 @@ import {
|
|
|
18
17
|
MessageType
|
|
19
18
|
} from '../../types/messageTypes';
|
|
20
19
|
import { typeSafeObjectFromEntries } from '../../helpers/objectFromEntries';
|
|
20
|
+
import { BaseActionProcessor } from './baseProcessor';
|
|
21
21
|
|
|
22
|
-
export class CommandActionProcessor {
|
|
23
|
-
private readonly
|
|
24
|
-
private readonly scheduler: IScheduler;
|
|
25
|
-
private readonly logger: ILogger;
|
|
22
|
+
export class CommandActionProcessor extends BaseActionProcessor {
|
|
23
|
+
private readonly replyCaptures: ReplyCaptureAction<IActionState>[] = [];
|
|
26
24
|
|
|
27
|
-
private readonly botName: string;
|
|
28
|
-
private readonly replyCaptures: ReplyCaptureAction<IActionState>[];
|
|
29
|
-
|
|
30
|
-
private api!: TelegramApiService;
|
|
31
|
-
private telegraf!: Telegraf;
|
|
32
25
|
private commands = typeSafeObjectFromEntries(
|
|
33
26
|
Object.values(MessageType).map((x) => [
|
|
34
27
|
x,
|
|
@@ -42,12 +35,7 @@ export class CommandActionProcessor {
|
|
|
42
35
|
scheduler: IScheduler,
|
|
43
36
|
logger: ILogger
|
|
44
37
|
) {
|
|
45
|
-
|
|
46
|
-
this.scheduler = scheduler;
|
|
47
|
-
this.logger = logger;
|
|
48
|
-
|
|
49
|
-
this.botName = botName;
|
|
50
|
-
this.replyCaptures = [];
|
|
38
|
+
super(botName, storage, scheduler, logger);
|
|
51
39
|
}
|
|
52
40
|
|
|
53
41
|
initialize(
|
|
@@ -56,8 +44,7 @@ export class CommandActionProcessor {
|
|
|
56
44
|
commands: CommandAction<IActionState>[],
|
|
57
45
|
verboseLoggingForIncomingMessage: boolean
|
|
58
46
|
) {
|
|
59
|
-
this.api
|
|
60
|
-
this.telegraf = telegraf;
|
|
47
|
+
this.initializeDependencies(api, telegraf);
|
|
61
48
|
|
|
62
49
|
for (const msgType of Object.values(MessageType)) {
|
|
63
50
|
if (msgType == MessageType.Text) {
|
|
@@ -155,35 +142,25 @@ export class CommandActionProcessor {
|
|
|
155
142
|
|
|
156
143
|
const commandsToCheck = new Set(this.commands[msg.type]);
|
|
157
144
|
if (msg.type != MessageType.Text && msg.text != '') {
|
|
158
|
-
this.commands[MessageType.Text].
|
|
145
|
+
this.commands[MessageType.Text].forEach((x) =>
|
|
146
|
+
commandsToCheck.add(x)
|
|
147
|
+
);
|
|
159
148
|
}
|
|
160
149
|
|
|
161
150
|
for (const commandAction of commandsToCheck) {
|
|
162
151
|
this.initializeMessageContext(ctx, commandAction, msg);
|
|
163
|
-
|
|
164
|
-
try {
|
|
165
|
-
const responses = await commandAction.exec(ctx);
|
|
166
|
-
this.api.enqueueBatchedResponses(responses);
|
|
167
|
-
ctx.isInitialized = false;
|
|
168
|
-
} catch (error) {
|
|
169
|
-
ctx.logger.errorWithTraceId(error, ctx);
|
|
170
|
-
}
|
|
152
|
+
this.executeAction(commandAction, ctx);
|
|
171
153
|
}
|
|
172
154
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
for (const replyAction of this.replyCaptures) {
|
|
179
|
-
this.initializeReplyCaptureContext(replyCtx, replyAction, msg);
|
|
155
|
+
if (this.replyCaptures.length != 0) {
|
|
156
|
+
const replyCtx = new ReplyContext<IActionState>(
|
|
157
|
+
this.storage,
|
|
158
|
+
this.scheduler
|
|
159
|
+
);
|
|
180
160
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.
|
|
184
|
-
replyCtx.isInitialized = false;
|
|
185
|
-
} catch (error) {
|
|
186
|
-
replyCtx.logger.errorWithTraceId(error, replyCtx);
|
|
161
|
+
for (const replyAction of this.replyCaptures) {
|
|
162
|
+
this.initializeReplyCaptureContext(replyCtx, replyAction, msg);
|
|
163
|
+
this.executeAction(replyAction, replyCtx);
|
|
187
164
|
}
|
|
188
165
|
}
|
|
189
166
|
|
|
@@ -219,9 +196,9 @@ export class CommandActionProcessor {
|
|
|
219
196
|
);
|
|
220
197
|
}
|
|
221
198
|
|
|
222
|
-
private initializeMessageContext
|
|
199
|
+
private initializeMessageContext(
|
|
223
200
|
ctx: MessageContext<IActionState>,
|
|
224
|
-
action:
|
|
201
|
+
action: CommandAction<IActionState>,
|
|
225
202
|
message: IncomingMessage
|
|
226
203
|
) {
|
|
227
204
|
ctx.messageId = message.messageId;
|
|
@@ -9,16 +9,9 @@ import { IStorageClient } from '../../types/storage';
|
|
|
9
9
|
import { Milliseconds } from '../../types/timeValues';
|
|
10
10
|
import { TraceId } from '../../types/trace';
|
|
11
11
|
import { TelegramApiService } from '../telegramApi';
|
|
12
|
+
import { BaseActionProcessor } from './baseProcessor';
|
|
12
13
|
|
|
13
|
-
export class InlineQueryActionProcessor {
|
|
14
|
-
private readonly storage: IStorageClient;
|
|
15
|
-
private readonly scheduler: IScheduler;
|
|
16
|
-
private readonly logger: ILogger;
|
|
17
|
-
|
|
18
|
-
private readonly botName: string;
|
|
19
|
-
|
|
20
|
-
private api!: TelegramApiService;
|
|
21
|
-
private telegraf!: Telegraf;
|
|
14
|
+
export class InlineQueryActionProcessor extends BaseActionProcessor {
|
|
22
15
|
private inlineQueries!: InlineQueryAction[];
|
|
23
16
|
|
|
24
17
|
constructor(
|
|
@@ -27,11 +20,7 @@ export class InlineQueryActionProcessor {
|
|
|
27
20
|
scheduler: IScheduler,
|
|
28
21
|
logger: ILogger
|
|
29
22
|
) {
|
|
30
|
-
|
|
31
|
-
this.scheduler = scheduler;
|
|
32
|
-
this.logger = logger;
|
|
33
|
-
|
|
34
|
-
this.botName = botName;
|
|
23
|
+
super(botName, storage, scheduler, logger);
|
|
35
24
|
}
|
|
36
25
|
|
|
37
26
|
initialize(
|
|
@@ -40,8 +29,7 @@ export class InlineQueryActionProcessor {
|
|
|
40
29
|
inlineQueries: InlineQueryAction[],
|
|
41
30
|
period: Milliseconds
|
|
42
31
|
) {
|
|
43
|
-
this.api
|
|
44
|
-
this.telegraf = telegraf;
|
|
32
|
+
this.initializeDependencies(api, telegraf);
|
|
45
33
|
this.inlineQueries = inlineQueries;
|
|
46
34
|
|
|
47
35
|
let pendingInlineQueries: IncomingInlineQuery[] = [];
|
|
@@ -113,23 +101,19 @@ export class InlineQueryActionProcessor {
|
|
|
113
101
|
inlineQuery.traceId
|
|
114
102
|
);
|
|
115
103
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
`Aborting query ${inlineQuery.queryId} (${inlineQuery.query}) successful.`
|
|
128
|
-
);
|
|
129
|
-
} else {
|
|
130
|
-
ctx.logger.errorWithTraceId(error, ctx);
|
|
104
|
+
this.executeAction(
|
|
105
|
+
inlineQueryAction,
|
|
106
|
+
ctx,
|
|
107
|
+
(error, ctx) => {
|
|
108
|
+
if (error.name == 'AbortError') {
|
|
109
|
+
ctx.logger.logWithTraceId(
|
|
110
|
+
`Aborting query ${inlineQuery.queryId} (${inlineQuery.query}) successful.`
|
|
111
|
+
);
|
|
112
|
+
} else {
|
|
113
|
+
ctx.logger.errorWithTraceId(error, ctx);
|
|
114
|
+
}
|
|
131
115
|
}
|
|
132
|
-
|
|
116
|
+
);
|
|
133
117
|
}
|
|
134
118
|
|
|
135
119
|
queriesInProcessing.delete(inlineQuery.userId);
|
|
@@ -4,7 +4,6 @@ import { ScheduledAction } from '../../entities/actions/scheduledAction';
|
|
|
4
4
|
import { ChatContext } from '../../entities/context/chatContext';
|
|
5
5
|
import { secondsToMilliseconds } from '../../helpers/timeConvertions';
|
|
6
6
|
import { createTrace } from '../../helpers/traceFactory';
|
|
7
|
-
import { IActionWithState } from '../../types/action';
|
|
8
7
|
import { IActionState } from '../../types/actionState';
|
|
9
8
|
import { ILogger } from '../../types/logger';
|
|
10
9
|
import { IScheduler } from '../../types/scheduler';
|
|
@@ -12,16 +11,11 @@ import { IStorageClient } from '../../types/storage';
|
|
|
12
11
|
import { Seconds, Milliseconds } from '../../types/timeValues';
|
|
13
12
|
import { TraceId } from '../../types/trace';
|
|
14
13
|
import { TelegramApiService } from '../telegramApi';
|
|
14
|
+
import { BaseActionProcessor } from './baseProcessor';
|
|
15
15
|
|
|
16
|
-
export class ScheduledActionProcessor {
|
|
17
|
-
private readonly storage: IStorageClient;
|
|
18
|
-
private readonly scheduler: IScheduler;
|
|
19
|
-
private readonly logger: ILogger;
|
|
20
|
-
|
|
21
|
-
private readonly botName: string;
|
|
16
|
+
export class ScheduledActionProcessor extends BaseActionProcessor {
|
|
22
17
|
private readonly chats: Record<string, number>;
|
|
23
18
|
|
|
24
|
-
private api!: TelegramApiService;
|
|
25
19
|
private scheduled!: ScheduledAction<IActionState>[];
|
|
26
20
|
|
|
27
21
|
constructor(
|
|
@@ -31,11 +25,7 @@ export class ScheduledActionProcessor {
|
|
|
31
25
|
scheduler: IScheduler,
|
|
32
26
|
logger: ILogger
|
|
33
27
|
) {
|
|
34
|
-
|
|
35
|
-
this.scheduler = scheduler;
|
|
36
|
-
this.logger = logger;
|
|
37
|
-
|
|
38
|
-
this.botName = botName;
|
|
28
|
+
super(botName, storage, scheduler, logger);
|
|
39
29
|
this.chats = chats;
|
|
40
30
|
}
|
|
41
31
|
|
|
@@ -44,7 +34,7 @@ export class ScheduledActionProcessor {
|
|
|
44
34
|
scheduled: ScheduledAction<IActionState>[],
|
|
45
35
|
period: Seconds
|
|
46
36
|
) {
|
|
47
|
-
this.api
|
|
37
|
+
this.initializeDependencies(api, null!);
|
|
48
38
|
this.scheduled = scheduled;
|
|
49
39
|
|
|
50
40
|
if (this.scheduled.length > 0) {
|
|
@@ -106,22 +96,16 @@ export class ScheduledActionProcessor {
|
|
|
106
96
|
)
|
|
107
97
|
);
|
|
108
98
|
|
|
109
|
-
|
|
110
|
-
const responses = await scheduledAction.exec(ctx);
|
|
111
|
-
this.api.enqueueBatchedResponses(responses);
|
|
112
|
-
ctx.isInitialized = false;
|
|
113
|
-
} catch (error) {
|
|
114
|
-
ctx.logger.errorWithTraceId(error, ctx);
|
|
115
|
-
}
|
|
99
|
+
this.executeAction(scheduledAction, ctx);
|
|
116
100
|
}
|
|
117
101
|
}
|
|
118
102
|
|
|
119
103
|
this.api.flushResponses();
|
|
120
104
|
}
|
|
121
105
|
|
|
122
|
-
private initializeChatContext
|
|
106
|
+
private initializeChatContext(
|
|
123
107
|
ctx: ChatContext<IActionState>,
|
|
124
|
-
action:
|
|
108
|
+
action: ScheduledAction<IActionState>,
|
|
125
109
|
chatInfo: ChatInfo,
|
|
126
110
|
traceId: TraceId
|
|
127
111
|
) {
|
|
@@ -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/action.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { BaseContext } from '../entities/context/baseContext';
|
|
1
2
|
import { IActionState } from './actionState';
|
|
3
|
+
import { BotResponse } from './response';
|
|
2
4
|
|
|
3
5
|
export type ActionKey = string & { __brand: 'actionKey' };
|
|
4
6
|
|
|
@@ -9,4 +11,5 @@ export interface IActionWithState<TActionState extends IActionState>
|
|
|
9
11
|
|
|
10
12
|
export interface IAction {
|
|
11
13
|
readonly key: ActionKey;
|
|
14
|
+
exec(ctx: BaseContext<IAction>): Promise<BotResponse[]>;
|
|
12
15
|
}
|
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>,
|