@adriangalilea/utils 0.8.0 → 0.10.0

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/bot/menu.js CHANGED
@@ -67,10 +67,14 @@
67
67
  * .extend(menu.plugin)
68
68
  */
69
69
  import { CallbackData, InlineKeyboard, Plugin, } from 'gramio';
70
+ import { say } from '../say/index.js';
71
+ import { inThread } from './kit.js';
72
+ const FALLBACK_LANG = 'en';
73
+ const ctxLang = (ctx) => ctx.session?.language ?? FALLBACK_LANG;
70
74
  const DEFAULT_COMMAND = 'settings';
71
75
  const DEFAULT_DESCRIPTION = 'Open settings menu';
72
76
  const DEFAULT_PRIVACY_URL = 'https://telegram.org/privacy-tpa';
73
- const DEFAULT_HEADER = '⚙️ Settings';
77
+ const DEFAULT_HEADER = { en: '⚙️ Settings', es: '⚙️ Ajustes' };
74
78
  const DEFAULT_SESSION_KEY = (userId) => String(userId);
75
79
  // ─── callback data schemas ─────────────────────────────────────────
76
80
  const navCb = new CallbackData('mNav').string('path');
@@ -111,7 +115,12 @@ export class BotMenu {
111
115
  }
112
116
  export const botMenu = (opts) => new BotMenu(opts);
113
117
  // ─── internal: rendering + plugin ──────────────────────────────────
114
- const labelOf = (l, ctx) => typeof l === 'function' ? l(ctx) : l;
118
+ const labelOf = (l, ctx) => {
119
+ const resolved = typeof l === 'function' ? l(ctx) : l;
120
+ if (typeof resolved === 'string')
121
+ return resolved;
122
+ return say(resolved, ctxLang(ctx));
123
+ };
115
124
  const itemsForPath = (root, path) => {
116
125
  if (path.length === 0)
117
126
  return root;
@@ -155,28 +164,29 @@ const renderKeyboard = (menu, items, ctx, parentPath) => {
155
164
  }
156
165
  kb.row();
157
166
  }
167
+ const lang = ctxLang(ctx);
158
168
  if (parentPath.length === 0) {
159
169
  // GDPR rights buttons at the root view.
160
170
  if (menu._opts.personalData) {
161
- kb.text('🗑 Forget my data', actCb.pack({ path: '_forget' }));
171
+ kb.text(say({ en: '🗑 Forget my data', es: '🗑 Olvidar mis datos' }, lang), actCb.pack({ path: '_forget' }));
162
172
  kb.row();
163
- kb.text('📥 Export my data', exportCb.pack({}));
173
+ kb.text(say({ en: '📥 Export my data', es: '📥 Exportar mis datos' }, lang), exportCb.pack({}));
164
174
  kb.row();
165
175
  }
166
176
  // Privacy link.
167
- kb.url('📖 Privacy', menu._opts.privacy);
177
+ kb.url(say({ en: '📖 Privacy', es: '📖 Privacidad' }, lang), menu._opts.privacy);
168
178
  kb.row();
169
179
  }
170
180
  else {
171
181
  const backPath = parentPath.slice(0, -1).join('.');
172
- kb.text('⬅️ Back', navCb.pack({ path: backPath || '_root' }));
182
+ kb.text(say({ en: '⬅️ Back', es: '⬅️ Volver' }, lang), navCb.pack({ path: backPath || '_root' }));
173
183
  }
174
184
  return kb;
175
185
  };
176
- const renderConfirmForget = () => new InlineKeyboard()
177
- .text('✅ Confirm delete', forgetConfirmCb.pack({}))
186
+ const renderConfirmForget = (lang) => new InlineKeyboard()
187
+ .text(say({ en: '✅ Confirm delete', es: '✅ Confirmar borrado' }, lang), forgetConfirmCb.pack({}))
178
188
  .row()
179
- .text('⬅️ Cancel', forgetCancelCb.pack({}));
189
+ .text(say({ en: '⬅️ Cancel', es: '⬅️ Cancelar' }, lang), forgetCancelCb.pack({}));
180
190
  const buildMenuPlugin = (menu) => {
181
191
  const { command, description, header, personalData, adminContact } = menu._opts;
182
192
  return new Plugin('@adriangalilea/utils/bot/menu')
@@ -186,11 +196,14 @@ const buildMenuPlugin = (menu) => {
186
196
  })
187
197
  // Navigate (root / submenu)
188
198
  .callbackQuery(navCb, async (ctx) => {
199
+ const lang = ctxLang(ctx);
189
200
  const raw = ctx.queryData.path;
190
201
  const segments = raw === '_root' ? [] : raw.split('.');
191
202
  const items = itemsForPath(menu._items, segments);
192
203
  if (!items) {
193
- await ctx.answer({ text: 'Menu out of date.' });
204
+ await ctx.answer({
205
+ text: say({ en: 'Menu out of date.', es: 'Menú obsoleto.' }, lang),
206
+ });
194
207
  return;
195
208
  }
196
209
  await ctx.answer({});
@@ -204,13 +217,19 @@ const buildMenuPlugin = (menu) => {
204
217
  })
205
218
  // Action items + the forget pre-confirmation
206
219
  .callbackQuery(actCb, async (ctx) => {
220
+ const lang = ctxLang(ctx);
207
221
  const raw = ctx.queryData.path;
208
222
  if (raw === '_forget') {
209
223
  await ctx.answer({});
210
224
  try {
211
- await ctx.editText('⚠️ Delete all your data?\n\n' +
212
- 'This removes the session record we keep about you ' +
213
- '(preferences, history, access state). Not reversible.', { reply_markup: renderConfirmForget() });
225
+ await ctx.editText(say({
226
+ en: '⚠️ Delete all your data?\n\n' +
227
+ 'This removes the session record we keep about you ' +
228
+ '(preferences, history, access state). Not reversible.',
229
+ es: '⚠️ ¿Borrar todos tus datos?\n\n' +
230
+ 'Esto elimina el registro de sesión que guardamos sobre ti ' +
231
+ '(preferencias, historial, estado de acceso). No se puede deshacer.',
232
+ }, lang), { reply_markup: renderConfirmForget(lang) });
214
233
  }
215
234
  catch {
216
235
  /* ignore */
@@ -219,7 +238,9 @@ const buildMenuPlugin = (menu) => {
219
238
  }
220
239
  const item = itemForPath(menu._items, raw.split('.'));
221
240
  if (!item || !('action' in item)) {
222
- await ctx.answer({ text: 'Item not found.' });
241
+ await ctx.answer({
242
+ text: say({ en: 'Item not found.', es: 'Elemento no encontrado.' }, lang),
243
+ });
223
244
  return;
224
245
  }
225
246
  await ctx.answer({});
@@ -227,18 +248,29 @@ const buildMenuPlugin = (menu) => {
227
248
  })
228
249
  // Forget — confirm path
229
250
  .callbackQuery(forgetConfirmCb, async (ctx) => {
251
+ const lang = ctxLang(ctx);
230
252
  if (!personalData) {
231
- await ctx.answer({ text: 'Not configured.', show_alert: true });
253
+ await ctx.answer({
254
+ text: say({ en: 'Not configured.', es: 'No configurado.' }, lang),
255
+ show_alert: true,
256
+ });
232
257
  return;
233
258
  }
234
259
  const userId = ctx.from?.id;
235
260
  if (userId === undefined)
236
- return ctx.answer({ text: 'No user.' });
261
+ return ctx.answer({
262
+ text: say({ en: 'No user.', es: 'Sin usuario.' }, lang),
263
+ });
237
264
  try {
238
265
  await personalData.storage.delete(personalData.sessionKey(userId));
239
- await ctx.answer({ text: 'Deleted.' });
266
+ await ctx.answer({
267
+ text: say({ en: 'Deleted.', es: 'Borrado.' }, lang),
268
+ });
240
269
  try {
241
- await ctx.editText('✅ Your data has been deleted.');
270
+ await ctx.editText(say({
271
+ en: '✅ Your data has been deleted.',
272
+ es: '✅ Tus datos han sido borrados.',
273
+ }, lang));
242
274
  }
243
275
  catch {
244
276
  /* ignore */
@@ -246,8 +278,13 @@ const buildMenuPlugin = (menu) => {
246
278
  }
247
279
  catch (e) {
248
280
  console.error('[menu] /forget failed', e);
249
- await ctx.answer({ text: 'Failed.' });
250
- await ctx.send(`❌ Could not delete your data.\n\nPlease contact ${adminContact}.`);
281
+ await ctx.answer({
282
+ text: say({ en: 'Failed.', es: 'Falló.' }, lang),
283
+ });
284
+ await ctx.send(say({
285
+ en: `❌ Could not delete your data.\n\nPlease contact ${adminContact}.`,
286
+ es: `❌ No se han podido borrar tus datos.\n\nContacta con ${adminContact}.`,
287
+ }, lang));
251
288
  }
252
289
  })
253
290
  .callbackQuery(forgetCancelCb, async (ctx) => {
@@ -262,22 +299,37 @@ const buildMenuPlugin = (menu) => {
262
299
  })
263
300
  // Export — JSON file with the user's whole session record
264
301
  .callbackQuery(exportCb, async (ctx) => {
302
+ const lang = ctxLang(ctx);
265
303
  if (!personalData) {
266
- await ctx.answer({ text: 'Not configured.', show_alert: true });
304
+ await ctx.answer({
305
+ text: say({ en: 'Not configured.', es: 'No configurado.' }, lang),
306
+ show_alert: true,
307
+ });
267
308
  return;
268
309
  }
269
310
  const userId = ctx.from?.id;
270
311
  if (userId === undefined)
271
- return ctx.answer({ text: 'No user.' });
312
+ return ctx.answer({
313
+ text: say({ en: 'No user.', es: 'Sin usuario.' }, lang),
314
+ });
272
315
  const record = (await personalData.storage.get(personalData.sessionKey(userId))) ?? {};
273
316
  const file = new File([JSON.stringify({ userId, exportedAt: Date.now(), data: record }, null, 2)], `my-data-${userId}-${Date.now()}.json`, { type: 'application/json' });
274
317
  await ctx.answer({});
275
318
  try {
276
- await ctx.sendDocument(file, { caption: '📥 Your data export' });
319
+ await ctx.sendDocument(file, {
320
+ caption: say({ en: '📥 Your data export', es: '📥 Exportación de tus datos' }, lang),
321
+ // Land the file in the same thread the menu was opened from.
322
+ // Callback ctx exposes the thread via ctx.message.threadId;
323
+ // inThread() handles both shapes.
324
+ ...inThread(ctx),
325
+ });
277
326
  }
278
327
  catch (e) {
279
328
  console.error('[menu] /export sendDocument failed', e);
280
- await ctx.send(`❌ Could not send your data export.\n\nPlease contact ${adminContact}.`);
329
+ await ctx.send(say({
330
+ en: `❌ Could not send your data export.\n\nPlease contact ${adminContact}.`,
331
+ es: `❌ No se ha podido enviar la exportación de tus datos.\n\nContacta con ${adminContact}.`,
332
+ }, lang));
281
333
  }
282
334
  });
283
335
  };
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/bot/menu.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/bot/menu.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,31 @@
1
1
  /**
2
2
  * Per-user rolling message history for GramIO bots — opt-in, with
3
- * retention.
3
+ * retention, **sharded by thread**.
4
4
  *
5
- * Follows the same shared-session pattern as `bot/language`: the
6
- * user creates a `session()` once at bot level, and each feature
7
- * plugin (including this one) declares it as a dependency. gramio
8
- * dedupes the runtime extension; the types flow.
5
+ * Each user has one session record. Inside that record, `history` keeps
6
+ * a separate ring buffer per thread:
7
+ *
8
+ * storage[userId].history.shards = {
9
+ * 'general': [ ...entries from no-thread messages ],
10
+ * '12345': [ ...entries from message_thread_id=12345 ],
11
+ * '98765': [ ...entries from message_thread_id=98765 ],
12
+ * }
13
+ *
14
+ * This makes the plugin compatible with both forum-supergroup topics
15
+ * and BotFather's Threaded Mode for private chats (which is the whole
16
+ * point of those features: parallel conversations with separate
17
+ * context). `ctx.history` returns ONLY the slice for the current
18
+ * thread; `ctx.allHistory` returns the full sharded map when you need
19
+ * a cross-thread view (e.g. for `/export`).
20
+ *
21
+ * Thread key: `String(ctx.threadId)`, or `'general'` when no thread.
9
22
  *
10
23
  * ## What this plugin owns
11
24
  *
12
- * - Appends each incoming user message to `ctx.session.history.items`
13
- * - Prunes entries older than `retentionDays` or beyond `maxMessages`
14
- * - Exposes a read-only pruned snapshot at `ctx.history` for handlers
25
+ * - Appends each incoming user message to the shard for its thread
26
+ * - Prunes per-shard by `retentionDays` and `maxMessages`
27
+ * - Exposes `ctx.history` (current thread's pruned slice) and
28
+ * `ctx.allHistory` (full map) to handlers
15
29
  *
16
30
  * ## GDPR caveat — retention IS personal data
17
31
  *
@@ -29,15 +43,6 @@
29
43
  * These are not enforced by this plugin (would couple it to menu); they
30
44
  * are documented as the bot author's legal responsibility.
31
45
  *
32
- * ## Storage layout
33
- *
34
- * Lives entirely inside the shared session record:
35
- *
36
- * storage[String(senderId)] = {
37
- * ...other plugins' fields,
38
- * history: { items: [HistoryEntry, ...] }
39
- * }
40
- *
41
46
  * Peer deps: `gramio`, `@gramio/session`.
42
47
  *
43
48
  * @example
@@ -50,7 +55,7 @@
50
55
  *
51
56
  * const history = messageHistory({
52
57
  * session: userSession,
53
- * maxMessages: 100,
58
+ * maxMessages: 100, // cap per-thread
54
59
  * retentionDays: 7,
55
60
  * })
56
61
  *
@@ -59,7 +64,7 @@
59
64
  * .extend(history.plugin)
60
65
  * .command('replay', (ctx) => {
61
66
  * const last = ctx.history.slice(-3).map((e) => e.text).join('\n---\n')
62
- * return ctx.send(last || '(no history)')
67
+ * return ctx.send(last || '(no history in this thread)')
63
68
  * })
64
69
  */
65
70
  import { type DeriveDefinitions, Plugin } from 'gramio';
@@ -72,8 +77,15 @@ export type HistoryEntry = {
72
77
  /** Message text, or empty string if non-text. */
73
78
  text: string;
74
79
  };
80
+ /**
81
+ * Per-thread shards. Key is `String(ctx.threadId)` or `'general'`
82
+ * when no thread. Each shard is an independently capped + pruned
83
+ * ring buffer.
84
+ */
75
85
  export type HistoryRecord = {
76
- items: HistoryEntry[];
86
+ shards: {
87
+ [threadKey: string]: HistoryEntry[];
88
+ };
77
89
  };
78
90
  /** Loose session shape — this plugin only touches the `history` field. */
79
91
  type SessionLike = {
@@ -87,7 +99,7 @@ export type MessageHistoryOptions = {
87
99
  * gramio's runtime dedup ensures it only runs once per update.
88
100
  */
89
101
  session: HistorySessionPluginRef;
90
- /** Ring buffer cap. Oldest entries dropped when exceeded. */
102
+ /** Ring buffer cap **per thread**. Oldest entries dropped when exceeded. */
91
103
  maxMessages: number;
92
104
  /** Entries older than this (in days) are dropped on read. */
93
105
  retentionDays: number;
@@ -96,7 +108,15 @@ export type MessageHistoryFeature = {
96
108
  plugin: ReturnType<typeof buildHistoryPlugin>;
97
109
  };
98
110
  type HistoryDerives = {
111
+ /** Pruned snapshot for the CURRENT thread only. */
99
112
  history: ReadonlyArray<HistoryEntry>;
113
+ /**
114
+ * Pruned snapshot of all threads, keyed by thread (`'general'` or
115
+ * stringified threadId). Use for cross-thread views (e.g. /export).
116
+ */
117
+ allHistory: Readonly<{
118
+ [threadKey: string]: ReadonlyArray<HistoryEntry>;
119
+ }>;
100
120
  };
101
121
  export declare const messageHistory: (opts: MessageHistoryOptions) => MessageHistoryFeature;
102
122
  declare const buildHistoryPlugin: (args: {
@@ -1 +1 @@
1
- {"version":3,"file":"message-history.d.ts","sourceRoot":"","sources":["../../src/bot/message-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAIzC,MAAM,MAAM,YAAY,GAAG;IACzB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,CAAA;AAED,0EAA0E;AAC1E,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,aAAa,CAAA;CAAE,CAAA;AAE9C,wEAAwE;AACxE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAA;AAEjF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;OAGG;IACH,OAAO,EAAE,uBAAuB,CAAA;IAChC,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;CAC9C,CAAA;AAID,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;CACrC,CAAA;AAgBD,eAAO,MAAM,cAAc,GAAI,MAAM,qBAAqB,KAAG,qBAW5D,CAAA;AAID,QAAA,MAAM,kBAAkB,GAAI,MAAM;IAChC,aAAa,EAAE,uBAAuB,CAAA;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;CACtB;YAGqD,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA8BnE,CAAA"}
1
+ {"version":3,"file":"message-history.d.ts","sourceRoot":"","sources":["../../src/bot/message-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAIzC,MAAM,MAAM,YAAY,GAAG;IACzB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE,CAAA;KAAE,CAAA;CAChD,CAAA;AAaD,0EAA0E;AAC1E,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,aAAa,CAAA;CAAE,CAAA;AAE9C,wEAAwE;AACxE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAA;AAEjF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;OAGG;IACH,OAAO,EAAE,uBAAuB,CAAA;IAChC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;CAC9C,CAAA;AAID,KAAK,cAAc,GAAG;IACpB,mDAAmD;IACnD,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IACpC;;;OAGG;IACH,UAAU,EAAE,QAAQ,CAAC;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,CAAA;KAAE,CAAC,CAAA;CAC3E,CAAA;AA6BD,eAAO,MAAM,cAAc,GAAI,MAAM,qBAAqB,KAAG,qBAW5D,CAAA;AAID,QAAA,MAAM,kBAAkB,GAAI,MAAM;IAChC,aAAa,EAAE,uBAAuB,CAAA;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;CACtB;YAGqD,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAqCnE,CAAA"}
@@ -1,17 +1,31 @@
1
1
  /**
2
2
  * Per-user rolling message history for GramIO bots — opt-in, with
3
- * retention.
3
+ * retention, **sharded by thread**.
4
4
  *
5
- * Follows the same shared-session pattern as `bot/language`: the
6
- * user creates a `session()` once at bot level, and each feature
7
- * plugin (including this one) declares it as a dependency. gramio
8
- * dedupes the runtime extension; the types flow.
5
+ * Each user has one session record. Inside that record, `history` keeps
6
+ * a separate ring buffer per thread:
7
+ *
8
+ * storage[userId].history.shards = {
9
+ * 'general': [ ...entries from no-thread messages ],
10
+ * '12345': [ ...entries from message_thread_id=12345 ],
11
+ * '98765': [ ...entries from message_thread_id=98765 ],
12
+ * }
13
+ *
14
+ * This makes the plugin compatible with both forum-supergroup topics
15
+ * and BotFather's Threaded Mode for private chats (which is the whole
16
+ * point of those features: parallel conversations with separate
17
+ * context). `ctx.history` returns ONLY the slice for the current
18
+ * thread; `ctx.allHistory` returns the full sharded map when you need
19
+ * a cross-thread view (e.g. for `/export`).
20
+ *
21
+ * Thread key: `String(ctx.threadId)`, or `'general'` when no thread.
9
22
  *
10
23
  * ## What this plugin owns
11
24
  *
12
- * - Appends each incoming user message to `ctx.session.history.items`
13
- * - Prunes entries older than `retentionDays` or beyond `maxMessages`
14
- * - Exposes a read-only pruned snapshot at `ctx.history` for handlers
25
+ * - Appends each incoming user message to the shard for its thread
26
+ * - Prunes per-shard by `retentionDays` and `maxMessages`
27
+ * - Exposes `ctx.history` (current thread's pruned slice) and
28
+ * `ctx.allHistory` (full map) to handlers
15
29
  *
16
30
  * ## GDPR caveat — retention IS personal data
17
31
  *
@@ -29,15 +43,6 @@
29
43
  * These are not enforced by this plugin (would couple it to menu); they
30
44
  * are documented as the bot author's legal responsibility.
31
45
  *
32
- * ## Storage layout
33
- *
34
- * Lives entirely inside the shared session record:
35
- *
36
- * storage[String(senderId)] = {
37
- * ...other plugins' fields,
38
- * history: { items: [HistoryEntry, ...] }
39
- * }
40
- *
41
46
  * Peer deps: `gramio`, `@gramio/session`.
42
47
  *
43
48
  * @example
@@ -50,7 +55,7 @@
50
55
  *
51
56
  * const history = messageHistory({
52
57
  * session: userSession,
53
- * maxMessages: 100,
58
+ * maxMessages: 100, // cap per-thread
54
59
  * retentionDays: 7,
55
60
  * })
56
61
  *
@@ -59,16 +64,31 @@
59
64
  * .extend(history.plugin)
60
65
  * .command('replay', (ctx) => {
61
66
  * const last = ctx.history.slice(-3).map((e) => e.text).join('\n---\n')
62
- * return ctx.send(last || '(no history)')
67
+ * return ctx.send(last || '(no history in this thread)')
63
68
  * })
64
69
  */
65
70
  import { Plugin } from 'gramio';
71
+ const GENERAL_THREAD = 'general';
72
+ const threadKey = (ctx) => {
73
+ // Message events: ctx.threadId. Callback events: ctx.message.threadId.
74
+ const tid = ctx.threadId ?? ctx.message?.threadId;
75
+ return tid !== undefined ? String(tid) : GENERAL_THREAD;
76
+ };
66
77
  // ─── helpers ───────────────────────────────────────────────────────
67
78
  const prune = (items, maxMessages, retentionDays) => {
68
79
  const cutoffSec = Math.floor(Date.now() / 1000) - retentionDays * 86400;
69
80
  const fresh = items.filter((e) => e.date >= cutoffSec);
70
81
  return fresh.slice(-maxMessages);
71
82
  };
83
+ const pruneAll = (shards, maxMessages, retentionDays) => {
84
+ const out = {};
85
+ for (const k of Object.keys(shards)) {
86
+ const pruned = prune(shards[k], maxMessages, retentionDays);
87
+ if (pruned.length > 0)
88
+ out[k] = pruned;
89
+ }
90
+ return out;
91
+ };
72
92
  // ─── feature factory ───────────────────────────────────────────────
73
93
  export const messageHistory = (opts) => {
74
94
  if (opts.maxMessages <= 0)
@@ -87,8 +107,9 @@ const buildHistoryPlugin = (args) => {
87
107
  const { sessionPlugin, maxMessages, retentionDays } = args;
88
108
  return new Plugin('@adriangalilea/utils/bot/message-history')
89
109
  .extend(sessionPlugin)
90
- // Record incoming messages with text. Service messages, edits,
91
- // and callback queries don't append — only direct user input.
110
+ // Record incoming messages with text into their thread's shard.
111
+ // Service messages, edits, and callback queries don't append —
112
+ // only direct user input.
92
113
  .on('message', async (ctx, next) => {
93
114
  if (ctx.text !== undefined) {
94
115
  const entry = {
@@ -96,16 +117,26 @@ const buildHistoryPlugin = (args) => {
96
117
  date: ctx.payload.date,
97
118
  text: ctx.text,
98
119
  };
99
- const cur = ctx.session.history?.items ?? [];
100
- ctx.session.history = {
101
- items: [...prune(cur, maxMessages, retentionDays), entry].slice(-maxMessages),
102
- };
120
+ const key = threadKey(ctx);
121
+ const shards = { ...(ctx.session.history?.shards ?? {}) };
122
+ const cur = shards[key] ?? [];
123
+ shards[key] = [
124
+ ...prune(cur, maxMessages, retentionDays),
125
+ entry,
126
+ ].slice(-maxMessages);
127
+ ctx.session.history = { shards };
103
128
  }
104
129
  return next();
105
130
  })
106
- // Pruned read-only view for handlers downstream.
107
- .derive(['message', 'callback_query'], (ctx) => ({
108
- history: prune(ctx.session.history?.items ?? [], maxMessages, retentionDays),
109
- }));
131
+ // Read-only views for handlers downstream.
132
+ .derive(['message', 'callback_query'], (ctx) => {
133
+ const shards = ctx.session.history?.shards ?? {};
134
+ const allPruned = pruneAll(shards, maxMessages, retentionDays);
135
+ const key = threadKey(ctx);
136
+ return {
137
+ history: (allPruned[key] ?? []),
138
+ allHistory: allPruned,
139
+ };
140
+ });
110
141
  };
111
142
  //# sourceMappingURL=message-history.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-history.js","sourceRoot":"","sources":["../../src/bot/message-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,OAAO,EAA0B,MAAM,EAAE,MAAM,QAAQ,CAAA;AA8CvD,sEAAsE;AAEtE,MAAM,KAAK,GAAG,CACZ,KAAqB,EACrB,WAAmB,EACnB,aAAqB,EACL,EAAE;IAClB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,aAAa,GAAG,KAAK,CAAA;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAA;IACtD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAA;AAClC,CAAC,CAAA;AAED,sEAAsE;AAEtE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAA2B,EAAyB,EAAE;IACnF,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IACrF,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAEzF,MAAM,MAAM,GAAG,kBAAkB,CAAC;QAChC,aAAa,EAAE,IAAI,CAAC,OAAO;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,CAAA;AACnB,CAAC,CAAA;AAED,sEAAsE;AAEtE,MAAM,kBAAkB,GAAG,CAAC,IAI3B,EAAE,EAAE;IACH,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,IAAI,CAAA;IAE1D,OAAO,IAAI,MAAM,CACf,0CAA0C,CAC3C;SACE,MAAM,CAAC,aAAa,CAAC;QACtB,+DAA+D;QAC/D,8DAA8D;SAC7D,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACjC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAiB;gBAC1B,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI;gBACtB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAA;YACD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAA;YAC5C,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG;gBACpB,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAC7D,CAAC,WAAW,CACb;aACF,CAAA;QACH,CAAC;QACD,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,CAAC;QACF,iDAAiD;SAChD,MAAM,CAAC,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAkB,EAAE,CAAC,CAAC;QAC/D,OAAO,EAAE,KAAK,CACZ,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,EAChC,WAAW,EACX,aAAa,CACiB;KACjC,CAAC,CAAC,CAAA;AACP,CAAC,CAAA"}
1
+ {"version":3,"file":"message-history.js","sourceRoot":"","sources":["../../src/bot/message-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,OAAO,EAA0B,MAAM,EAAE,MAAM,QAAQ,CAAA;AAuBvD,MAAM,cAAc,GAAG,SAAS,CAAA;AAEhC,MAAM,SAAS,GAAG,CAAC,GAGlB,EAAU,EAAE;IACX,uEAAuE;IACvE,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAA;IACjD,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAA;AACzD,CAAC,CAAA;AAoCD,sEAAsE;AAEtE,MAAM,KAAK,GAAG,CACZ,KAAqB,EACrB,WAAmB,EACnB,aAAqB,EACL,EAAE;IAClB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,aAAa,GAAG,KAAK,CAAA;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAA;IACtD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CACf,MAA+B,EAC/B,WAAmB,EACnB,aAAqB,EACI,EAAE;IAC3B,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC,CAAA;QAC3D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAA;IACxC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED,sEAAsE;AAEtE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAA2B,EAAyB,EAAE;IACnF,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IACrF,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAEzF,MAAM,MAAM,GAAG,kBAAkB,CAAC;QAChC,aAAa,EAAE,IAAI,CAAC,OAAO;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,CAAA;AACnB,CAAC,CAAA;AAED,sEAAsE;AAEtE,MAAM,kBAAkB,GAAG,CAAC,IAI3B,EAAE,EAAE;IACH,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,IAAI,CAAA;IAE1D,OAAO,IAAI,MAAM,CACf,0CAA0C,CAC3C;SACE,MAAM,CAAC,aAAa,CAAC;QACtB,gEAAgE;QAChE,+DAA+D;QAC/D,0BAA0B;SACzB,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACjC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAiB;gBAC1B,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI;gBACtB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAA;YACD,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;YAC1B,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,EAAE,CAAA;YACzD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;YAC7B,MAAM,CAAC,GAAG,CAAC,GAAG;gBACZ,GAAG,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC;gBACzC,KAAK;aACN,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAA;YACrB,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG,EAAE,MAAM,EAAE,CAAA;QAClC,CAAC;QACD,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,CAAC;QACF,2CAA2C;SAC1C,MAAM,CAAC,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAkB,EAAE;QAC7D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAA;QAChD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,aAAa,CAAC,CAAA;QAC9D,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;QAC1B,OAAO;YACL,OAAO,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAgC;YAC9D,UAAU,EAAE,SAEV;SACH,CAAA;IACH,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './universal/log.js';
8
8
  export * from './universal/format.js';
9
9
  export * from './universal/currency/index.js';
10
10
  export * from './offensive.js';
11
+ export * from './say/index.js';
11
12
  export * from './platform/file.js';
12
13
  export * from './platform/dir.js';
13
14
  export * from './platform/path.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGvD,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAG7C,cAAc,gBAAgB,CAAA;AAI9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGvD,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAG7C,cAAc,gBAAgB,CAAA;AAG9B,cAAc,gBAAgB,CAAA;AAI9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ export * from './universal/format.js';
10
10
  export * from './universal/currency/index.js';
11
11
  // Offensive programming - pure throws, zero dependencies
12
12
  export * from './offensive.js';
13
+ // Polyglot strings — TS-enforced multi-language values
14
+ export * from './say/index.js';
13
15
  // Platform-specific utilities
14
16
  // These will throw helpful errors in browser environment when used
15
17
  export * from './platform/file.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGtC,wCAAwC;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAE7C,yDAAyD;AACzD,cAAc,gBAAgB,CAAA;AAE9B,8BAA8B;AAC9B,mEAAmE;AACnE,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGtC,wCAAwC;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAE7C,yDAAyD;AACzD,cAAc,gBAAgB,CAAA;AAE9B,uDAAuD;AACvD,cAAc,gBAAgB,CAAA;AAE9B,8BAA8B;AAC9B,mEAAmE;AACnE,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `say` — TypeScript-enforced polyglot strings, framework-agnostic.
3
+ *
4
+ * A "polyglot value" is a plain object literal with one string per
5
+ * supported language:
6
+ *
7
+ * { en: 'Hello', es: 'Hola' }
8
+ *
9
+ * The keys are the source of truth. There is no JSON file, no key
10
+ * registry, no extraction tool, no namespaces. The TS compiler
11
+ * enforces completeness: add a language to the plugin's `supported`
12
+ * list and every call site without that key becomes a compile error.
13
+ *
14
+ * Two entry points:
15
+ *
16
+ * `say(value, lang)` — pure resolver, no context, returns string.
17
+ * Use it for 3rd-party SDKs / cron / email
18
+ * / anything outside a bot ctx.
19
+ *
20
+ * `ctx.say(value)` — bot-bound; uses `ctx.lang`. Provided by
21
+ * `bot/language` (see that plugin for the
22
+ * `ctx.say.send / .edit / .answer` methods).
23
+ *
24
+ * @example
25
+ * import { say, type Polyglot } from '@adriangalilea/utils/say'
26
+ *
27
+ * await pushover.send({
28
+ * message: say({ en: 'Drop!', es: '¡Drop!' }, user.lang),
29
+ * })
30
+ *
31
+ * // typing your own adapter:
32
+ * const notify = (msg: string | Polyglot<'en' | 'es'>, lang: 'en' | 'es') =>
33
+ * transport.send(typeof msg === 'string' ? msg : say(msg, lang))
34
+ */
35
+ /**
36
+ * A value that exists in N languages. `L` is the union of supported
37
+ * language tags (typically inferred from the object literal's keys).
38
+ *
39
+ * Authoring: `{ en: 'Hi', es: 'Hola' }` — TS infers `L = 'en' | 'es'`.
40
+ *
41
+ * Typing your own API: `function notify(msg: Polyglot<'en' | 'es'>)`
42
+ * — callers must provide both keys.
43
+ */
44
+ export type Polyglot<L extends string> = Readonly<Record<L, string>>;
45
+ /**
46
+ * Resolve a polyglot value to a string at `lang`.
47
+ *
48
+ * If `lang` is missing from `value`, returns the first available key
49
+ * (lexicographic). This is a structural fallback — it should never
50
+ * happen when `lang` is constrained by the same `L` as `value`'s
51
+ * keys; it exists only for the dynamic-string escape hatch.
52
+ *
53
+ * @example
54
+ * say({ en: 'Hi', es: 'Hola' }, 'es') // → 'Hola'
55
+ * say({ en: 'Hi', es: 'Hola' }, 'fr') // TS error: '"fr"' not in '"en" | "es"'
56
+ *
57
+ * @example // typing-loose escape hatch with `as Polyglot<string>`
58
+ * const raw: Polyglot<string> = JSON.parse(blob)
59
+ * say(raw, userLang) // dynamic, falls back if missing
60
+ */
61
+ export declare const say: <L extends string>(value: Polyglot<L>, lang: L) => string;
62
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/say/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;AAEpE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,SAAS,MAAM,EAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAG,MAKnE,CAAA"}