@mtcute/core 0.2.2 → 0.3.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.
Files changed (103) hide show
  1. package/cjs/base-client.d.ts +33 -166
  2. package/cjs/base-client.js +70 -48
  3. package/cjs/base-client.js.map +1 -1
  4. package/cjs/base-client.types.d.ts +153 -0
  5. package/cjs/base-client.types.js +3 -0
  6. package/cjs/base-client.types.js.map +1 -0
  7. package/cjs/index.d.ts +1 -0
  8. package/cjs/index.js +1 -0
  9. package/cjs/index.js.map +1 -1
  10. package/cjs/network/mtproto-session.d.ts +10 -2
  11. package/cjs/network/mtproto-session.js +33 -3
  12. package/cjs/network/mtproto-session.js.map +1 -1
  13. package/cjs/network/multi-session-connection.d.ts +1 -1
  14. package/cjs/network/multi-session-connection.js +4 -3
  15. package/cjs/network/multi-session-connection.js.map +1 -1
  16. package/cjs/network/network-manager.d.ts +23 -0
  17. package/cjs/network/network-manager.js +28 -8
  18. package/cjs/network/network-manager.js.map +1 -1
  19. package/cjs/network/server-salt.d.ts +12 -0
  20. package/cjs/network/server-salt.js +45 -0
  21. package/cjs/network/server-salt.js.map +1 -0
  22. package/cjs/network/session-connection.d.ts +6 -1
  23. package/cjs/network/session-connection.js +179 -54
  24. package/cjs/network/session-connection.js.map +1 -1
  25. package/cjs/storage/abstract.d.ts +12 -1
  26. package/cjs/storage/abstract.js.map +1 -1
  27. package/cjs/storage/idb.d.ts +3 -1
  28. package/cjs/storage/idb.js +17 -0
  29. package/cjs/storage/idb.js.map +1 -1
  30. package/cjs/storage/index.d.ts +1 -0
  31. package/cjs/storage/index.js +1 -0
  32. package/cjs/storage/index.js.map +1 -1
  33. package/cjs/storage/json.js +1 -0
  34. package/cjs/storage/json.js.map +1 -1
  35. package/cjs/storage/memory.d.ts +5 -2
  36. package/cjs/storage/memory.js +16 -2
  37. package/cjs/storage/memory.js.map +1 -1
  38. package/cjs/storage/memory.test.js +2 -1
  39. package/cjs/storage/memory.test.js.map +1 -1
  40. package/cjs/utils/logger.js +8 -2
  41. package/cjs/utils/logger.js.map +1 -1
  42. package/cjs/utils/logger.test.js +12 -0
  43. package/cjs/utils/logger.test.js.map +1 -1
  44. package/cjs/utils/long-utils.d.ts +5 -0
  45. package/cjs/utils/long-utils.js +13 -1
  46. package/cjs/utils/long-utils.js.map +1 -1
  47. package/cjs/utils/sorted-array.js +1 -0
  48. package/cjs/utils/sorted-array.js.map +1 -1
  49. package/cjs/utils/type-assertions.d.ts +1 -0
  50. package/cjs/utils/type-assertions.js +7 -1
  51. package/cjs/utils/type-assertions.js.map +1 -1
  52. package/esm/base-client.d.ts +33 -166
  53. package/esm/base-client.js +70 -48
  54. package/esm/base-client.js.map +1 -1
  55. package/esm/base-client.types.d.ts +153 -0
  56. package/esm/base-client.types.js +2 -0
  57. package/esm/base-client.types.js.map +1 -0
  58. package/esm/index.d.ts +1 -0
  59. package/esm/index.js +1 -0
  60. package/esm/index.js.map +1 -1
  61. package/esm/network/mtproto-session.d.ts +10 -2
  62. package/esm/network/mtproto-session.js +34 -4
  63. package/esm/network/mtproto-session.js.map +1 -1
  64. package/esm/network/multi-session-connection.d.ts +1 -1
  65. package/esm/network/multi-session-connection.js +4 -3
  66. package/esm/network/multi-session-connection.js.map +1 -1
  67. package/esm/network/network-manager.d.ts +23 -0
  68. package/esm/network/network-manager.js +29 -9
  69. package/esm/network/network-manager.js.map +1 -1
  70. package/esm/network/server-salt.d.ts +12 -0
  71. package/esm/network/server-salt.js +38 -0
  72. package/esm/network/server-salt.js.map +1 -0
  73. package/esm/network/session-connection.d.ts +6 -1
  74. package/esm/network/session-connection.js +179 -54
  75. package/esm/network/session-connection.js.map +1 -1
  76. package/esm/storage/abstract.d.ts +12 -1
  77. package/esm/storage/abstract.js.map +1 -1
  78. package/esm/storage/idb.d.ts +3 -1
  79. package/esm/storage/idb.js +17 -0
  80. package/esm/storage/idb.js.map +1 -1
  81. package/esm/storage/index.d.ts +1 -0
  82. package/esm/storage/index.js +1 -0
  83. package/esm/storage/index.js.map +1 -1
  84. package/esm/storage/json.js +1 -0
  85. package/esm/storage/json.js.map +1 -1
  86. package/esm/storage/memory.d.ts +5 -2
  87. package/esm/storage/memory.js +16 -2
  88. package/esm/storage/memory.js.map +1 -1
  89. package/esm/storage/memory.test.js +2 -1
  90. package/esm/storage/memory.test.js.map +1 -1
  91. package/esm/utils/logger.js +8 -2
  92. package/esm/utils/logger.js.map +1 -1
  93. package/esm/utils/logger.test.js +12 -0
  94. package/esm/utils/logger.test.js.map +1 -1
  95. package/esm/utils/long-utils.d.ts +5 -0
  96. package/esm/utils/long-utils.js +11 -0
  97. package/esm/utils/long-utils.js.map +1 -1
  98. package/esm/utils/sorted-array.js +1 -0
  99. package/esm/utils/sorted-array.js.map +1 -1
  100. package/esm/utils/type-assertions.d.ts +1 -0
  101. package/esm/utils/type-assertions.js +5 -0
  102. package/esm/utils/type-assertions.js.map +1 -1
  103. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"abstract.js","sourceRoot":"","sources":["../../../src/storage/abstract.ts"],"names":[],"mappings":"","sourcesContent":["import { tl } from '@mtcute/tl'\nimport { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { BasicPeerType, MaybeAsync } from '../types/index.js'\nimport { Logger } from '../utils/index.js'\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace ITelegramStorage {\n /** Information about a cached peer */\n export interface PeerInfo {\n /** Peer marked ID */\n id: number\n /** Peer access hash */\n accessHash: tl.Long\n /** Peer type */\n type: BasicPeerType\n /** Peer username, if any */\n username?: string\n /** Peer phone number, if available */\n phone?: string\n\n /** Full TL object with the cached entity */\n full: tl.TypeUser | tl.TypeChat\n }\n\n /** Information about currently logged in user */\n export interface SelfInfo {\n /** Whether this is a bot */\n isBot: boolean\n /** Current user's ID */\n userId: number\n }\n\n /** Information about preferred DC-s for the user */\n export interface DcOptions {\n /** Main DC */\n main: tl.RawDcOption\n /** Media DC. Can be the same as main */\n media: tl.RawDcOption\n }\n}\n\n/**\n * Abstract interface for persistent storage.\n *\n * In some cases you may want to extend existing MemorySession\n * and override save()/load()/destroy() methods, but you are also free\n * to implement your own session (be sure to refer to MemorySession\n * source code to avoid shooting your leg though)\n *\n * Note that even though set methods *can* be async, you should only\n * write updates to the disk when `save()` is called.\n */\nexport interface ITelegramStorage {\n /**\n * This method is called before any other.\n * For storages that use logging, logger instance.\n * For storages that use binary storage, binary maps\n */\n setup?(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void\n\n /**\n * Load session from some external storage.\n * Should be used either to load session content from file/network/etc\n * to memory, or to open required connections to fetch session content later\n */\n load?(): MaybeAsync<void>\n /**\n * Save session to some external storage.\n * Should be used to commit pending changes in the session.\n * For example, saving session content to file/network/etc,\n * or committing a database transaction\n */\n save?(): MaybeAsync<void>\n /**\n * Cleanup session and release all used resources.\n */\n destroy?(): MaybeAsync<void>\n\n /**\n * Reset session to its default state, optionally resetting auth keys\n *\n * @param [withAuthKeys=false] Whether to also reset auth keys\n */\n reset(withAuthKeys?: boolean): void\n\n /**\n * Set default datacenter to use with this session.\n */\n setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): MaybeAsync<void>\n /**\n * Get default datacenter for this session\n * (by default should return null)\n */\n getDefaultDcs(): MaybeAsync<ITelegramStorage.DcOptions | null>\n\n /**\n * Get auth_key for a given DC\n * (returning null will start authorization)\n * For temp keys: should also return null if the key has expired\n *\n * @param dcId DC ID\n * @param tempIndex Index of the temporary key (usually 0, used for multi-connections)\n */\n getAuthKeyFor(dcId: number, tempIndex?: number): MaybeAsync<Uint8Array | null>\n /**\n * Set auth_key for a given DC\n */\n setAuthKeyFor(dcId: number, key: Uint8Array | null): MaybeAsync<void>\n /**\n * Set temp_auth_key for a given DC\n * expiresAt is unix time in ms\n */\n setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): MaybeAsync<void>\n /**\n * Remove all saved auth keys (both temp and perm)\n * for the given DC. Used when perm_key becomes invalid,\n * meaning all temp_keys also become invalid\n */\n dropAuthKeysFor(dcId: number): MaybeAsync<void>\n\n /**\n * Get information about currently logged in user (if available)\n */\n getSelf(): MaybeAsync<ITelegramStorage.SelfInfo | null>\n /**\n * Save information about currently logged in user\n */\n setSelf(self: ITelegramStorage.SelfInfo | null): MaybeAsync<void>\n\n /**\n * Update local database of input peers from the peer info list\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n updatePeers(peers: ITelegramStorage.PeerInfo[]): MaybeAsync<void>\n\n /**\n * Find a peer in local database by its marked ID\n *\n * If no peer was found, the storage should try searching its\n * reference messages database. If a reference message is found,\n * a `inputPeer*FromMessage` constructor should be returned\n */\n getPeerById(peerId: number): MaybeAsync<tl.TypeInputPeer | null>\n\n /**\n * Find a peer in local database by its username\n */\n getPeerByUsername(username: string): MaybeAsync<tl.TypeInputPeer | null>\n\n /**\n * Find a peer in local database by its phone number\n */\n getPeerByPhone(phone: string): MaybeAsync<tl.TypeInputPeer | null>\n\n /**\n * For `*FromMessage` constructors: store a reference to a `peerId` -\n * it was seen in message `messageId` in chat `chatId`.\n *\n * `peerId` and `chatId` are marked peer IDs.\n *\n * Learn more: https://core.telegram.org/api/min\n */\n saveReferenceMessage(peerId: number, chatId: number, messageId: number): MaybeAsync<void>\n\n /**\n * For `*FromMessage` constructors: messages `messageIds` in chat `chatId` were deleted,\n * so remove any stored peer references to them.\n */\n deleteReferenceMessages(chatId: number, messageIds: number[]): MaybeAsync<void>\n\n /**\n * Get updates state (if available), represented as a tuple\n * containing: `pts, qts, date, seq`\n */\n getUpdatesState(): MaybeAsync<[number, number, number, number] | null>\n\n /**\n * Set common `pts` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesPts(val: number): MaybeAsync<void>\n /**\n * Set common `qts` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesQts(val: number): MaybeAsync<void>\n /**\n * Set updates `date` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesDate(val: number): MaybeAsync<void>\n /**\n * Set updates `seq` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesSeq(val: number): MaybeAsync<void>\n\n /**\n * Get channel `pts` value\n */\n getChannelPts(entityId: number): MaybeAsync<number | null>\n /**\n * Set channels `pts` values in batch.\n *\n * Storage is supposed to replace stored channel `pts` values\n * with given in the object (key is unmarked peer id, value is the `pts`)\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setManyChannelPts(values: Map<number, number>): MaybeAsync<void>\n\n /**\n * Get cached peer information by their marked ID.\n * Return `null` if caching is not supported, or the entity\n * is not cached (yet).\n *\n * This is primarily used when a `min` entity is encountered\n * in an update, or when a *short* update is encountered.\n * Returning `null` will require re-fetching that\n * update with the peers added, which might not be very efficient.\n */\n getFullPeerById(id: number): MaybeAsync<tl.TypeUser | tl.TypeChat | null>\n}\n"]}
1
+ {"version":3,"file":"abstract.js","sourceRoot":"","sources":["../../../src/storage/abstract.ts"],"names":[],"mappings":"","sourcesContent":["import { mtp, tl } from '@mtcute/tl'\nimport { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { BasicPeerType, MaybeAsync } from '../types/index.js'\nimport { Logger } from '../utils/index.js'\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace ITelegramStorage {\n /** Information about a cached peer */\n export interface PeerInfo {\n /** Peer marked ID */\n id: number\n /** Peer access hash */\n accessHash: tl.Long\n /** Peer type */\n type: BasicPeerType\n /** Peer username, if any */\n username?: string\n /** Peer phone number, if available */\n phone?: string\n\n /** Full TL object with the cached entity */\n full: tl.TypeUser | tl.TypeChat\n }\n\n /** Information about currently logged in user */\n export interface SelfInfo {\n /** Whether this is a bot */\n isBot: boolean\n /** Current user's ID */\n userId: number\n }\n\n /** Information about preferred DC-s for the user */\n export interface DcOptions {\n /** Main DC */\n main: tl.RawDcOption\n /** Media DC. Can be the same as main */\n media: tl.RawDcOption\n }\n}\n\n/**\n * Abstract interface for persistent storage.\n *\n * In some cases you may want to extend existing MemorySession\n * and override save()/load()/destroy() methods, but you are also free\n * to implement your own session (be sure to refer to MemorySession\n * source code to avoid shooting your leg though)\n *\n * Note that even though set methods *can* be async, you should only\n * write updates to the disk when `save()` is called.\n */\nexport interface ITelegramStorage {\n /**\n * This method is called before any other.\n * For storages that use logging, logger instance.\n * For storages that use binary storage, binary maps\n */\n setup?(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void\n\n /**\n * Load session from some external storage.\n * Should be used either to load session content from file/network/etc\n * to memory, or to open required connections to fetch session content later\n */\n load?(): MaybeAsync<void>\n /**\n * Save session to some external storage.\n * Should be used to commit pending changes in the session.\n * For example, saving session content to file/network/etc,\n * or committing a database transaction\n */\n save?(): MaybeAsync<void>\n /**\n * Cleanup session and release all used resources.\n */\n destroy?(): MaybeAsync<void>\n\n /**\n * Reset session to its default state, optionally resetting auth keys\n *\n * @param [withAuthKeys=false] Whether to also reset auth keys\n */\n reset(withAuthKeys?: boolean): void\n\n /**\n * Set default datacenter to use with this session.\n */\n setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): MaybeAsync<void>\n /**\n * Get default datacenter for this session\n * (by default should return null)\n */\n getDefaultDcs(): MaybeAsync<ITelegramStorage.DcOptions | null>\n\n /**\n * Store information about future salts for a given DC\n */\n setFutureSalts(dcId: number, salts: mtp.RawMt_future_salt[]): MaybeAsync<void>\n /**\n * Get information about future salts for a given DC (if available)\n *\n * You don't need to implement any checks, they will be done by the library.\n * It is enough to just return the same array that was passed to `setFutureSalts`.\n */\n getFutureSalts(dcId: number): MaybeAsync<mtp.RawMt_future_salt[] | null>\n\n /**\n * Get auth_key for a given DC\n * (returning null will start authorization)\n * For temp keys: should also return null if the key has expired\n *\n * @param dcId DC ID\n * @param tempIndex Index of the temporary key (usually 0, used for multi-connections)\n */\n getAuthKeyFor(dcId: number, tempIndex?: number): MaybeAsync<Uint8Array | null>\n /**\n * Set auth_key for a given DC\n */\n setAuthKeyFor(dcId: number, key: Uint8Array | null): MaybeAsync<void>\n /**\n * Set temp_auth_key for a given DC\n * expiresAt is unix time in ms\n */\n setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): MaybeAsync<void>\n /**\n * Remove all saved auth keys (both temp and perm)\n * for the given DC. Used when perm_key becomes invalid,\n * meaning all temp_keys also become invalid\n */\n dropAuthKeysFor(dcId: number): MaybeAsync<void>\n\n /**\n * Get information about currently logged in user (if available)\n */\n getSelf(): MaybeAsync<ITelegramStorage.SelfInfo | null>\n /**\n * Save information about currently logged in user\n */\n setSelf(self: ITelegramStorage.SelfInfo | null): MaybeAsync<void>\n\n /**\n * Update local database of input peers from the peer info list\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n updatePeers(peers: ITelegramStorage.PeerInfo[]): MaybeAsync<void>\n\n /**\n * Find a peer in local database by its marked ID\n *\n * If no peer was found, the storage should try searching its\n * reference messages database. If a reference message is found,\n * a `inputPeer*FromMessage` constructor should be returned\n */\n getPeerById(peerId: number): MaybeAsync<tl.TypeInputPeer | null>\n\n /**\n * Find a peer in local database by its username\n */\n getPeerByUsername(username: string): MaybeAsync<tl.TypeInputPeer | null>\n\n /**\n * Find a peer in local database by its phone number\n */\n getPeerByPhone(phone: string): MaybeAsync<tl.TypeInputPeer | null>\n\n /**\n * For `*FromMessage` constructors: store a reference to a `peerId` -\n * it was seen in message `messageId` in chat `chatId`.\n *\n * `peerId` and `chatId` are marked peer IDs.\n *\n * Learn more: https://core.telegram.org/api/min\n */\n saveReferenceMessage(peerId: number, chatId: number, messageId: number): MaybeAsync<void>\n\n /**\n * For `*FromMessage` constructors: messages `messageIds` in chat `chatId` were deleted,\n * so remove any stored peer references to them.\n */\n deleteReferenceMessages(chatId: number, messageIds: number[]): MaybeAsync<void>\n\n /**\n * Get updates state (if available), represented as a tuple\n * containing: `pts, qts, date, seq`\n */\n getUpdatesState(): MaybeAsync<[number, number, number, number] | null>\n\n /**\n * Set common `pts` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesPts(val: number): MaybeAsync<void>\n /**\n * Set common `qts` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesQts(val: number): MaybeAsync<void>\n /**\n * Set updates `date` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesDate(val: number): MaybeAsync<void>\n /**\n * Set updates `seq` value\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setUpdatesSeq(val: number): MaybeAsync<void>\n\n /**\n * Get channel `pts` value\n */\n getChannelPts(entityId: number): MaybeAsync<number | null>\n /**\n * Set channels `pts` values in batch.\n *\n * Storage is supposed to replace stored channel `pts` values\n * with given in the object (key is unmarked peer id, value is the `pts`)\n *\n * Client will call `.save()` after all updates-related methods\n * are called, so you can safely batch these updates\n */\n setManyChannelPts(values: Map<number, number>): MaybeAsync<void>\n\n /**\n * Get cached peer information by their marked ID.\n * Return `null` if caching is not supported, or the entity\n * is not cached (yet).\n *\n * This is primarily used when a `min` entity is encountered\n * in an update, or when a *short* update is encountered.\n * Returning `null` will require re-fetching that\n * update with the peers added, which might not be very efficient.\n */\n getFullPeerById(id: number): MaybeAsync<tl.TypeUser | tl.TypeChat | null>\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { tl } from '@mtcute/tl';
1
+ import { mtp, tl } from '@mtcute/tl';
2
2
  import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime';
3
3
  import { Logger } from '../utils/logger.js';
4
4
  import { ITelegramStorage } from './abstract.js';
@@ -68,6 +68,8 @@ export declare class IdbStorage implements ITelegramStorage {
68
68
  private _setToKv;
69
69
  setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): Promise<void>;
70
70
  getDefaultDcs(): Promise<ITelegramStorage.DcOptions | null>;
71
+ getFutureSalts(dcId: number): Promise<mtp.RawMt_future_salt[] | null>;
72
+ setFutureSalts(dcId: number, salts: mtp.RawMt_future_salt[]): Promise<void>;
71
73
  getAuthKeyFor(dcId: number, tempIndex?: number | undefined): Promise<Uint8Array | null>;
72
74
  setAuthKeyFor(dcId: number, key: Uint8Array | null): Promise<void>;
73
75
  setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): Promise<void>;
@@ -196,6 +196,23 @@ class IdbStorage {
196
196
  getDefaultDcs() {
197
197
  return this._getFromKv('dcs');
198
198
  }
199
+ async getFutureSalts(dcId) {
200
+ const res = await this._getFromKv(`futureSalts:${dcId}`);
201
+ if (!res)
202
+ return null;
203
+ return res.map((it) => {
204
+ const [salt, validSince, validUntil] = it.split(',');
205
+ return {
206
+ _: 'mt_future_salt',
207
+ validSince: Number(validSince),
208
+ validUntil: Number(validUntil),
209
+ salt: (0, long_utils_js_1.longFromFastString)(salt),
210
+ };
211
+ });
212
+ }
213
+ setFutureSalts(dcId, salts) {
214
+ return this._setToKv(`futureSalts:${dcId}`, salts.map((salt) => `${(0, long_utils_js_1.longToFastString)(salt.salt)},${salt.validSince},${salt.validUntil}`), true);
215
+ }
199
216
  async getAuthKeyFor(dcId, tempIndex) {
200
217
  let row;
201
218
  if (tempIndex !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"idb.js","sourceRoot":"","sources":["../../../src/storage/idb.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\nimport { tl } from '@mtcute/tl'\nimport { TlBinaryReader, TlBinaryWriter, TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { Logger } from '../utils/logger.js'\nimport { longFromFastString, longToFastString } from '../utils/long-utils.js'\nimport { LruMap } from '../utils/lru-map.js'\nimport { toggleChannelIdMark } from '../utils/peer-utils.js'\nimport { ITelegramStorage } from './abstract.js'\n\nconst CURRENT_VERSION = 1\n\nconst TABLES = {\n kv: 'kv',\n state: 'state',\n authKeys: 'auth_keys',\n tempAuthKeys: 'temp_auth_keys',\n pts: 'pts',\n entities: 'entities',\n messageRefs: 'message_refs',\n} as const\nconst EMPTY_BUFFER = new Uint8Array(0)\n\ninterface AuthKeyDto {\n dc: number\n key: Uint8Array\n expiresAt?: number\n}\n\ninterface EntityDto {\n id: number\n hash: string\n type: string\n username?: string\n phone?: string\n updated: number\n full: Uint8Array\n}\n\ninterface MessageRefDto {\n peerId: number\n chatId: number\n msgId: number\n}\n\ninterface FsmItemDto {\n key: string\n value: string\n expires?: number\n}\n\nfunction txToPromise(tx: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n tx.oncomplete = () => resolve()\n tx.onerror = () => reject(tx.error)\n })\n}\n\nfunction reqToPromise<T>(req: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n req.onsuccess = () => resolve(req.result)\n req.onerror = () => reject(req.error)\n })\n}\n\nfunction getInputPeer(row: EntityDto | ITelegramStorage.PeerInfo): tl.TypeInputPeer {\n const id = row.id\n\n switch (row.type) {\n case 'user':\n return {\n _: 'inputPeerUser',\n userId: id,\n accessHash: 'accessHash' in row ? row.accessHash : longFromFastString(row.hash),\n }\n case 'chat':\n return {\n _: 'inputPeerChat',\n chatId: -id,\n }\n case 'channel':\n return {\n _: 'inputPeerChannel',\n channelId: toggleChannelIdMark(id),\n accessHash: 'accessHash' in row ? row.accessHash : longFromFastString(row.hash),\n }\n }\n\n throw new Error(`Invalid peer type: ${row.type}`)\n}\n\ninterface CachedEntity {\n peer: tl.TypeInputPeer\n full: tl.TypeUser | tl.TypeChat | null\n}\n\n/**\n * mtcute storage that uses IndexedDB as a backend.\n *\n * This storage is the default one for browsers, and is generally\n * recommended over local storage based one.\n */\nexport class IdbStorage implements ITelegramStorage {\n private _cache?: LruMap<number, CachedEntity>\n\n private _vacuumTimeout?: NodeJS.Timeout\n private _vacuumInterval: number\n\n constructor(\n readonly _dbName: string,\n params?: {\n /**\n * Entities cache size, in number of entities.\n *\n * Recently encountered entities are cached in memory,\n * to avoid redundant database calls. Set to 0 to\n * disable caching (not recommended)\n *\n * Note that by design in-memory cached is only\n * used when finding peer by ID, since other\n * kinds of lookups (phone, username) may get stale quickly\n *\n * @default `100`\n */\n cacheSize?: number\n\n /**\n * Updates to already cached in-memory entities are only\n * applied in DB once in a while, to avoid redundant\n * DB calls.\n *\n * If you are having issues with this, you can set this to `0`\n *\n * @default `30000` (30 sec)\n */\n unimportantSavesDelay?: number\n\n /**\n * Interval in milliseconds for vacuuming the storage.\n *\n * When vacuuming, the storage will remove expired FSM\n * states to reduce disk and memory usage.\n *\n * @default `300_000` (5 minutes)\n */\n vacuumInterval?: number\n },\n ) {\n if (params?.cacheSize !== 0) {\n this._cache = new LruMap(params?.cacheSize ?? 100)\n }\n\n this._vacuumInterval = params?.vacuumInterval ?? 300_000\n }\n\n db!: IDBDatabase\n\n private _upgradeDb(db: IDBDatabase, oldVer: number, newVer: number): void {\n while (oldVer < newVer) {\n switch (oldVer) {\n case 0: {\n db.createObjectStore(TABLES.kv, { keyPath: 'key' })\n db.createObjectStore(TABLES.authKeys, { keyPath: 'dc' })\n db.createObjectStore(TABLES.tempAuthKeys, { keyPath: ['dc', 'idx'] })\n db.createObjectStore(TABLES.pts, { keyPath: 'channelId' })\n\n const stateOs = db.createObjectStore(TABLES.state, { keyPath: 'key' })\n stateOs.createIndex('by_expires', 'expires')\n\n const entitiesOs = db.createObjectStore(TABLES.entities, { keyPath: 'id' })\n entitiesOs.createIndex('by_username', 'username')\n entitiesOs.createIndex('by_phone', 'phone')\n\n const msgRefsOs = db.createObjectStore(TABLES.messageRefs, { keyPath: 'peerId' })\n msgRefsOs.createIndex('by_msg', ['chatId', 'msgId'])\n\n oldVer++\n }\n }\n }\n\n if (newVer !== CURRENT_VERSION) throw new Error(`Invalid db version: ${newVer}`)\n }\n\n private log!: Logger\n private readerMap!: TlReaderMap\n private writerMap!: TlWriterMap\n private _reader!: TlBinaryReader\n\n setup(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void {\n this.log = log.create('idb')\n this.readerMap = readerMap\n this.writerMap = writerMap\n this._reader = new TlBinaryReader(readerMap, EMPTY_BUFFER)\n }\n\n private _pendingWrites: [string, unknown][] = []\n private _pendingWritesOses = new Set<string>()\n\n private _writeLater(table: string, obj: unknown): void {\n this._pendingWrites.push([table, obj])\n this._pendingWritesOses.add(table)\n }\n\n private _readFullPeer(data: Uint8Array): tl.TypeUser | tl.TypeChat | null {\n this._reader = new TlBinaryReader(this.readerMap, data)\n let obj\n\n try {\n obj = this._reader.object()\n } catch (e) {\n // object might be from an older tl layer, in which case it will be ignored\n obj = null\n }\n\n return obj as tl.TypeUser | tl.TypeChat | null\n }\n\n async load(): Promise<void> {\n this.db = await new Promise((resolve, reject) => {\n const req = indexedDB.open(this._dbName, CURRENT_VERSION)\n\n req.onerror = () => reject(req.error)\n req.onsuccess = () => resolve(req.result)\n req.onupgradeneeded = (event) =>\n this._upgradeDb(req.result, event.oldVersion, event.newVersion || CURRENT_VERSION)\n })\n\n this._vacuumTimeout = setInterval(() => {\n this._vacuum().catch((e) => {\n this.log.warn('Failed to vacuum database: %s', e)\n })\n }, this._vacuumInterval)\n }\n\n async save() {\n if (this._pendingWritesOses.size === 0) return\n\n const writes = this._pendingWrites\n const oses = this._pendingWritesOses\n this._pendingWrites = []\n this._pendingWritesOses = new Set()\n\n const tx = this.db.transaction(oses, 'readwrite')\n\n const osMap = new Map<string, IDBObjectStore>()\n\n for (const table of oses) {\n osMap.set(table, tx.objectStore(table))\n }\n\n for (const [table, obj] of writes) {\n const os = osMap.get(table)!\n\n if (obj === null) {\n os.delete(table)\n } else {\n os.put(obj)\n }\n }\n\n await txToPromise(tx)\n }\n\n private async _vacuum(): Promise<void> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const keys = await reqToPromise(os.index('by_expires').getAllKeys(IDBKeyRange.upperBound(Date.now())))\n\n for (const key of keys) {\n os.delete(key)\n }\n\n return txToPromise(tx)\n }\n\n destroy(): void {\n this.db.close()\n clearInterval(this._vacuumTimeout)\n }\n\n async reset(withAuthKeys?: boolean | undefined): Promise<void> {\n this._cache?.clear()\n const tx = this.db.transaction(Object.values(TABLES), 'readwrite')\n\n for (const table of Object.values(TABLES)) {\n if (table === TABLES.authKeys && !withAuthKeys) continue\n if (table === TABLES.tempAuthKeys && !withAuthKeys) continue\n\n tx.objectStore(table).clear()\n }\n\n return txToPromise(tx)\n }\n\n private async _getFromKv<T>(key: string): Promise<T | null> {\n const tx = this.db.transaction(TABLES.kv)\n const store = tx.objectStore(TABLES.kv)\n\n const res = await reqToPromise<{ value: string }>(store.get(key))\n\n if (res === undefined) return null\n\n return JSON.parse(res.value) as T\n }\n\n private async _setToKv<T>(key: string, value: T, now = false): Promise<void> {\n const dto = { key, value: JSON.stringify(value) }\n\n if (!now) {\n this._writeLater(TABLES.kv, dto)\n\n return\n }\n\n const tx = this.db.transaction(TABLES.kv, 'readwrite')\n const store = tx.objectStore(TABLES.kv)\n\n await reqToPromise(store.put(dto))\n }\n\n setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): Promise<void> {\n return this._setToKv('dcs', dcs, true)\n }\n\n getDefaultDcs(): Promise<ITelegramStorage.DcOptions | null> {\n return this._getFromKv('dcs')\n }\n\n async getAuthKeyFor(dcId: number, tempIndex?: number | undefined): Promise<Uint8Array | null> {\n let row: AuthKeyDto\n\n if (tempIndex !== undefined) {\n const os = this.db.transaction(TABLES.tempAuthKeys).objectStore(TABLES.tempAuthKeys)\n row = await reqToPromise<AuthKeyDto>(os.get([dcId, tempIndex]))\n if (row === undefined || row.expiresAt! < Date.now()) return null\n } else {\n const os = this.db.transaction(TABLES.authKeys).objectStore(TABLES.authKeys)\n row = await reqToPromise<AuthKeyDto>(os.get(dcId))\n if (row === undefined) return null\n }\n\n return row.key\n }\n\n async setAuthKeyFor(dcId: number, key: Uint8Array | null): Promise<void> {\n const os = this.db.transaction(TABLES.authKeys, 'readwrite').objectStore(TABLES.authKeys)\n\n if (key === null) {\n return reqToPromise(os.delete(dcId))\n }\n\n await reqToPromise(os.put({ dc: dcId, key }))\n }\n\n async setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): Promise<void> {\n const os = this.db.transaction(TABLES.tempAuthKeys, 'readwrite').objectStore(TABLES.tempAuthKeys)\n\n if (key === null) {\n return reqToPromise(os.delete([dcId, index]))\n }\n\n await reqToPromise(os.put({ dc: dcId, idx: index, key, expiresAt }))\n }\n\n async dropAuthKeysFor(dcId: number): Promise<void> {\n const tx = this.db.transaction([TABLES.authKeys, TABLES.tempAuthKeys], 'readwrite')\n\n tx.objectStore(TABLES.authKeys).delete(dcId)\n\n // IndexedDB sucks\n const tempOs = tx.objectStore(TABLES.tempAuthKeys)\n const keys = await reqToPromise(tempOs.getAllKeys())\n\n for (const key of keys) {\n if ((key as [number, number])[0] === dcId) {\n tempOs.delete(key)\n }\n }\n }\n\n private _cachedSelf?: ITelegramStorage.SelfInfo | null\n async getSelf(): Promise<ITelegramStorage.SelfInfo | null> {\n if (this._cachedSelf !== undefined) return this._cachedSelf\n\n const self = await this._getFromKv<ITelegramStorage.SelfInfo>('self')\n this._cachedSelf = self\n\n return self\n }\n\n async setSelf(self: ITelegramStorage.SelfInfo | null): Promise<void> {\n this._cachedSelf = self\n\n return this._setToKv('self', self, true)\n }\n\n async getUpdatesState(): Promise<[number, number, number, number] | null> {\n const os = this.db.transaction(TABLES.kv).objectStore(TABLES.kv)\n\n const [pts, qts, date, seq] = await Promise.all([\n reqToPromise<{ value: number }>(os.get('pts')),\n reqToPromise<{ value: number }>(os.get('qts')),\n reqToPromise<{ value: number }>(os.get('date')),\n reqToPromise<{ value: number }>(os.get('seq')),\n ])\n\n if (pts === undefined || qts === undefined || date === undefined || seq === undefined) return null\n\n return [Number(pts.value), Number(qts.value), Number(date.value), Number(seq.value)]\n }\n\n setUpdatesPts(val: number): Promise<void> {\n return this._setToKv('pts', val)\n }\n\n setUpdatesQts(val: number): Promise<void> {\n return this._setToKv('qts', val)\n }\n\n setUpdatesDate(val: number): Promise<void> {\n return this._setToKv('date', val)\n }\n\n setUpdatesSeq(val: number): Promise<void> {\n return this._setToKv('seq', val)\n }\n\n async getChannelPts(entityId: number): Promise<number | null> {\n const os = this.db.transaction(TABLES.pts).objectStore(TABLES.pts)\n const row = await reqToPromise<{ pts: number }>(os.get(entityId))\n\n if (row === undefined) return null\n\n return row.pts\n }\n\n async setManyChannelPts(values: Map<number, number>): Promise<void> {\n const tx = this.db.transaction(TABLES.pts, 'readwrite')\n const os = tx.objectStore(TABLES.pts)\n\n for (const [id, pts] of values) {\n os.put({ channelId: id, pts })\n }\n\n return txToPromise(tx)\n }\n\n updatePeers(peers: ITelegramStorage.PeerInfo[]): void {\n for (const peer of peers) {\n const dto: EntityDto = {\n id: peer.id,\n hash: longToFastString(peer.accessHash),\n type: peer.type,\n username: peer.username,\n phone: peer.phone,\n updated: Date.now(),\n full: TlBinaryWriter.serializeObject(this.writerMap, peer.full),\n }\n\n this._writeLater(TABLES.entities, dto)\n\n if (!this._cachedSelf?.isBot) {\n this._writeLater(TABLES.messageRefs, null)\n }\n\n this._cache?.set(peer.id, {\n peer: getInputPeer(peer),\n full: peer.full,\n })\n }\n }\n\n private async _findPeerByReference(os: IDBObjectStore, peerId: number): Promise<tl.TypeInputPeer | null> {\n const row = await reqToPromise<MessageRefDto>(os.get(peerId))\n if (row === undefined) return null\n\n const chat = await this.getPeerById(row.chatId, false)\n if (chat === null) return null\n\n if (peerId > 0) {\n return {\n _: 'inputPeerUserFromMessage',\n userId: peerId,\n peer: chat,\n msgId: row.msgId,\n }\n }\n\n return {\n _: 'inputPeerChannelFromMessage',\n channelId: toggleChannelIdMark(peerId),\n peer: chat,\n msgId: row.msgId,\n }\n }\n\n async getPeerById(peerId: number, allowRefs = true): Promise<tl.TypeInputPeer | null> {\n const cached = this._cache?.get(peerId)\n if (cached) return cached.peer\n\n const tx = this.db.transaction([TABLES.entities, TABLES.messageRefs])\n const entOs = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(entOs.get(peerId))\n\n if (row) {\n return getInputPeer(row)\n }\n\n if (allowRefs) {\n return this._findPeerByReference(tx.objectStore(TABLES.messageRefs), peerId)\n }\n\n return null\n }\n\n async getPeerByUsername(username: string): Promise<tl.TypeInputPeer | null> {\n const tx = this.db.transaction(TABLES.entities)\n const os = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(os.index('by_username').get(username))\n\n if (row === undefined) return null\n\n return getInputPeer(row)\n }\n\n async getPeerByPhone(phone: string): Promise<tl.TypeInputPeer | null> {\n const tx = this.db.transaction(TABLES.entities)\n const os = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(os.index('by_phone').get(phone))\n\n if (row === undefined) return null\n\n return getInputPeer(row)\n }\n\n async getFullPeerById(peerId: number): Promise<tl.TypeUser | tl.TypeChat | null> {\n const cached = this._cache?.get(peerId)\n if (cached) return cached.full\n\n const tx = this.db.transaction(TABLES.entities)\n const os = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(os.get(peerId))\n\n if (row === undefined) return null\n\n return this._readFullPeer(row.full)\n }\n\n async saveReferenceMessage(peerId: number, chatId: number, messageId: number): Promise<void> {\n const os = this.db.transaction(TABLES.messageRefs, 'readwrite').objectStore(TABLES.messageRefs)\n\n await reqToPromise(os.put({ peerId, chatId, msgId: messageId } satisfies MessageRefDto))\n }\n\n async deleteReferenceMessages(chatId: number, messageIds: number[]): Promise<void> {\n const tx = this.db.transaction(TABLES.messageRefs, 'readwrite')\n const os = tx.objectStore(TABLES.messageRefs)\n const index = os.index('by_msg')\n\n for (const msgId of messageIds) {\n const key = await reqToPromise(index.getKey([chatId, msgId]))\n if (key === undefined) continue\n\n os.delete(key)\n }\n\n return txToPromise(tx)\n }\n\n // IStateStorage implementation\n\n async getState(key: string): Promise<unknown> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const row = await reqToPromise<FsmItemDto>(os.get(key))\n if (!row) return null\n\n if (row.expires && row.expires < Date.now()) {\n await reqToPromise(os.delete(key))\n\n return null\n }\n\n return JSON.parse(row.value) as unknown\n }\n\n async setState(key: string, state: unknown, ttl?: number): Promise<void> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const dto: FsmItemDto = {\n key,\n value: JSON.stringify(state),\n expires: ttl ? Date.now() + ttl * 1000 : undefined,\n }\n\n await reqToPromise(os.put(dto))\n }\n\n async deleteState(key: string): Promise<void> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n await reqToPromise(os.delete(key))\n }\n\n getCurrentScene(key: string): Promise<string | null> {\n return this.getState(`$current_scene_${key}`) as Promise<string | null>\n }\n\n setCurrentScene(key: string, scene: string, ttl?: number): Promise<void> {\n return this.setState(`$current_scene_${key}`, scene, ttl)\n }\n\n deleteCurrentScene(key: string): Promise<void> {\n return this.deleteState(`$current_scene_${key}`)\n }\n\n async getRateLimit(key: string, limit: number, window: number): Promise<[number, number]> {\n // leaky bucket\n const now = Date.now()\n\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const row = await reqToPromise<FsmItemDto>(os.get(`$rate_limit_${key}`))\n\n if (!row || row.expires! < now) {\n // expired or does not exist\n const dto: FsmItemDto = {\n key: `$rate_limit_${key}`,\n value: limit.toString(),\n expires: now + window * 1000,\n }\n await reqToPromise(os.put(dto))\n\n return [limit, dto.expires!]\n }\n\n let value = Number(row.value)\n\n if (value > 0) {\n value -= 1\n row.value = value.toString()\n await reqToPromise(os.put(row))\n }\n\n return [value, row.expires!]\n }\n\n resetRateLimit(key: string): Promise<void> {\n return this.deleteState(`$rate_limit_${key}`)\n }\n}\n"]}
1
+ {"version":3,"file":"idb.js","sourceRoot":"","sources":["../../../src/storage/idb.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\nimport { mtp, tl } from '@mtcute/tl'\nimport { TlBinaryReader, TlBinaryWriter, TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { Logger } from '../utils/logger.js'\nimport { longFromFastString, longToFastString } from '../utils/long-utils.js'\nimport { LruMap } from '../utils/lru-map.js'\nimport { toggleChannelIdMark } from '../utils/peer-utils.js'\nimport { ITelegramStorage } from './abstract.js'\n\nconst CURRENT_VERSION = 1\n\nconst TABLES = {\n kv: 'kv',\n state: 'state',\n authKeys: 'auth_keys',\n tempAuthKeys: 'temp_auth_keys',\n pts: 'pts',\n entities: 'entities',\n messageRefs: 'message_refs',\n} as const\nconst EMPTY_BUFFER = new Uint8Array(0)\n\ninterface AuthKeyDto {\n dc: number\n key: Uint8Array\n expiresAt?: number\n}\n\ninterface EntityDto {\n id: number\n hash: string\n type: string\n username?: string\n phone?: string\n updated: number\n full: Uint8Array\n}\n\ninterface MessageRefDto {\n peerId: number\n chatId: number\n msgId: number\n}\n\ninterface FsmItemDto {\n key: string\n value: string\n expires?: number\n}\n\nfunction txToPromise(tx: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n tx.oncomplete = () => resolve()\n tx.onerror = () => reject(tx.error)\n })\n}\n\nfunction reqToPromise<T>(req: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n req.onsuccess = () => resolve(req.result)\n req.onerror = () => reject(req.error)\n })\n}\n\nfunction getInputPeer(row: EntityDto | ITelegramStorage.PeerInfo): tl.TypeInputPeer {\n const id = row.id\n\n switch (row.type) {\n case 'user':\n return {\n _: 'inputPeerUser',\n userId: id,\n accessHash: 'accessHash' in row ? row.accessHash : longFromFastString(row.hash),\n }\n case 'chat':\n return {\n _: 'inputPeerChat',\n chatId: -id,\n }\n case 'channel':\n return {\n _: 'inputPeerChannel',\n channelId: toggleChannelIdMark(id),\n accessHash: 'accessHash' in row ? row.accessHash : longFromFastString(row.hash),\n }\n }\n\n throw new Error(`Invalid peer type: ${row.type}`)\n}\n\ninterface CachedEntity {\n peer: tl.TypeInputPeer\n full: tl.TypeUser | tl.TypeChat | null\n}\n\n/**\n * mtcute storage that uses IndexedDB as a backend.\n *\n * This storage is the default one for browsers, and is generally\n * recommended over local storage based one.\n */\nexport class IdbStorage implements ITelegramStorage {\n private _cache?: LruMap<number, CachedEntity>\n\n private _vacuumTimeout?: NodeJS.Timeout\n private _vacuumInterval: number\n\n constructor(\n readonly _dbName: string,\n params?: {\n /**\n * Entities cache size, in number of entities.\n *\n * Recently encountered entities are cached in memory,\n * to avoid redundant database calls. Set to 0 to\n * disable caching (not recommended)\n *\n * Note that by design in-memory cached is only\n * used when finding peer by ID, since other\n * kinds of lookups (phone, username) may get stale quickly\n *\n * @default `100`\n */\n cacheSize?: number\n\n /**\n * Updates to already cached in-memory entities are only\n * applied in DB once in a while, to avoid redundant\n * DB calls.\n *\n * If you are having issues with this, you can set this to `0`\n *\n * @default `30000` (30 sec)\n */\n unimportantSavesDelay?: number\n\n /**\n * Interval in milliseconds for vacuuming the storage.\n *\n * When vacuuming, the storage will remove expired FSM\n * states to reduce disk and memory usage.\n *\n * @default `300_000` (5 minutes)\n */\n vacuumInterval?: number\n },\n ) {\n if (params?.cacheSize !== 0) {\n this._cache = new LruMap(params?.cacheSize ?? 100)\n }\n\n this._vacuumInterval = params?.vacuumInterval ?? 300_000\n }\n\n db!: IDBDatabase\n\n private _upgradeDb(db: IDBDatabase, oldVer: number, newVer: number): void {\n while (oldVer < newVer) {\n switch (oldVer) {\n case 0: {\n db.createObjectStore(TABLES.kv, { keyPath: 'key' })\n db.createObjectStore(TABLES.authKeys, { keyPath: 'dc' })\n db.createObjectStore(TABLES.tempAuthKeys, { keyPath: ['dc', 'idx'] })\n db.createObjectStore(TABLES.pts, { keyPath: 'channelId' })\n\n const stateOs = db.createObjectStore(TABLES.state, { keyPath: 'key' })\n stateOs.createIndex('by_expires', 'expires')\n\n const entitiesOs = db.createObjectStore(TABLES.entities, { keyPath: 'id' })\n entitiesOs.createIndex('by_username', 'username')\n entitiesOs.createIndex('by_phone', 'phone')\n\n const msgRefsOs = db.createObjectStore(TABLES.messageRefs, { keyPath: 'peerId' })\n msgRefsOs.createIndex('by_msg', ['chatId', 'msgId'])\n\n oldVer++\n }\n }\n }\n\n if (newVer !== CURRENT_VERSION) throw new Error(`Invalid db version: ${newVer}`)\n }\n\n private log!: Logger\n private readerMap!: TlReaderMap\n private writerMap!: TlWriterMap\n private _reader!: TlBinaryReader\n\n setup(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void {\n this.log = log.create('idb')\n this.readerMap = readerMap\n this.writerMap = writerMap\n this._reader = new TlBinaryReader(readerMap, EMPTY_BUFFER)\n }\n\n private _pendingWrites: [string, unknown][] = []\n private _pendingWritesOses = new Set<string>()\n\n private _writeLater(table: string, obj: unknown): void {\n this._pendingWrites.push([table, obj])\n this._pendingWritesOses.add(table)\n }\n\n private _readFullPeer(data: Uint8Array): tl.TypeUser | tl.TypeChat | null {\n this._reader = new TlBinaryReader(this.readerMap, data)\n let obj\n\n try {\n obj = this._reader.object()\n } catch (e) {\n // object might be from an older tl layer, in which case it will be ignored\n obj = null\n }\n\n return obj as tl.TypeUser | tl.TypeChat | null\n }\n\n async load(): Promise<void> {\n this.db = await new Promise((resolve, reject) => {\n const req = indexedDB.open(this._dbName, CURRENT_VERSION)\n\n req.onerror = () => reject(req.error)\n req.onsuccess = () => resolve(req.result)\n req.onupgradeneeded = (event) =>\n this._upgradeDb(req.result, event.oldVersion, event.newVersion || CURRENT_VERSION)\n })\n\n this._vacuumTimeout = setInterval(() => {\n this._vacuum().catch((e) => {\n this.log.warn('Failed to vacuum database: %s', e)\n })\n }, this._vacuumInterval)\n }\n\n async save() {\n if (this._pendingWritesOses.size === 0) return\n\n const writes = this._pendingWrites\n const oses = this._pendingWritesOses\n this._pendingWrites = []\n this._pendingWritesOses = new Set()\n\n const tx = this.db.transaction(oses, 'readwrite')\n\n const osMap = new Map<string, IDBObjectStore>()\n\n for (const table of oses) {\n osMap.set(table, tx.objectStore(table))\n }\n\n for (const [table, obj] of writes) {\n const os = osMap.get(table)!\n\n if (obj === null) {\n os.delete(table)\n } else {\n os.put(obj)\n }\n }\n\n await txToPromise(tx)\n }\n\n private async _vacuum(): Promise<void> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const keys = await reqToPromise(os.index('by_expires').getAllKeys(IDBKeyRange.upperBound(Date.now())))\n\n for (const key of keys) {\n os.delete(key)\n }\n\n return txToPromise(tx)\n }\n\n destroy(): void {\n this.db.close()\n clearInterval(this._vacuumTimeout)\n }\n\n async reset(withAuthKeys?: boolean | undefined): Promise<void> {\n this._cache?.clear()\n const tx = this.db.transaction(Object.values(TABLES), 'readwrite')\n\n for (const table of Object.values(TABLES)) {\n if (table === TABLES.authKeys && !withAuthKeys) continue\n if (table === TABLES.tempAuthKeys && !withAuthKeys) continue\n\n tx.objectStore(table).clear()\n }\n\n return txToPromise(tx)\n }\n\n private async _getFromKv<T>(key: string): Promise<T | null> {\n const tx = this.db.transaction(TABLES.kv)\n const store = tx.objectStore(TABLES.kv)\n\n const res = await reqToPromise<{ value: string }>(store.get(key))\n\n if (res === undefined) return null\n\n return JSON.parse(res.value) as T\n }\n\n private async _setToKv<T>(key: string, value: T, now = false): Promise<void> {\n const dto = { key, value: JSON.stringify(value) }\n\n if (!now) {\n this._writeLater(TABLES.kv, dto)\n\n return\n }\n\n const tx = this.db.transaction(TABLES.kv, 'readwrite')\n const store = tx.objectStore(TABLES.kv)\n\n await reqToPromise(store.put(dto))\n }\n\n setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): Promise<void> {\n return this._setToKv('dcs', dcs, true)\n }\n\n getDefaultDcs(): Promise<ITelegramStorage.DcOptions | null> {\n return this._getFromKv('dcs')\n }\n\n async getFutureSalts(dcId: number): Promise<mtp.RawMt_future_salt[] | null> {\n const res = await this._getFromKv<string[]>(`futureSalts:${dcId}`)\n if (!res) return null\n\n return res.map((it) => {\n const [salt, validSince, validUntil] = it.split(',')\n\n return {\n _: 'mt_future_salt',\n validSince: Number(validSince),\n validUntil: Number(validUntil),\n salt: longFromFastString(salt),\n }\n })\n }\n\n setFutureSalts(dcId: number, salts: mtp.RawMt_future_salt[]): Promise<void> {\n return this._setToKv(\n `futureSalts:${dcId}`,\n salts.map((salt) => `${longToFastString(salt.salt)},${salt.validSince},${salt.validUntil}`),\n true,\n )\n }\n\n async getAuthKeyFor(dcId: number, tempIndex?: number | undefined): Promise<Uint8Array | null> {\n let row: AuthKeyDto\n\n if (tempIndex !== undefined) {\n const os = this.db.transaction(TABLES.tempAuthKeys).objectStore(TABLES.tempAuthKeys)\n row = await reqToPromise<AuthKeyDto>(os.get([dcId, tempIndex]))\n if (row === undefined || row.expiresAt! < Date.now()) return null\n } else {\n const os = this.db.transaction(TABLES.authKeys).objectStore(TABLES.authKeys)\n row = await reqToPromise<AuthKeyDto>(os.get(dcId))\n if (row === undefined) return null\n }\n\n return row.key\n }\n\n async setAuthKeyFor(dcId: number, key: Uint8Array | null): Promise<void> {\n const os = this.db.transaction(TABLES.authKeys, 'readwrite').objectStore(TABLES.authKeys)\n\n if (key === null) {\n return reqToPromise(os.delete(dcId))\n }\n\n await reqToPromise(os.put({ dc: dcId, key }))\n }\n\n async setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): Promise<void> {\n const os = this.db.transaction(TABLES.tempAuthKeys, 'readwrite').objectStore(TABLES.tempAuthKeys)\n\n if (key === null) {\n return reqToPromise(os.delete([dcId, index]))\n }\n\n await reqToPromise(os.put({ dc: dcId, idx: index, key, expiresAt }))\n }\n\n async dropAuthKeysFor(dcId: number): Promise<void> {\n const tx = this.db.transaction([TABLES.authKeys, TABLES.tempAuthKeys], 'readwrite')\n\n tx.objectStore(TABLES.authKeys).delete(dcId)\n\n // IndexedDB sucks\n const tempOs = tx.objectStore(TABLES.tempAuthKeys)\n const keys = await reqToPromise(tempOs.getAllKeys())\n\n for (const key of keys) {\n if ((key as [number, number])[0] === dcId) {\n tempOs.delete(key)\n }\n }\n }\n\n private _cachedSelf?: ITelegramStorage.SelfInfo | null\n async getSelf(): Promise<ITelegramStorage.SelfInfo | null> {\n if (this._cachedSelf !== undefined) return this._cachedSelf\n\n const self = await this._getFromKv<ITelegramStorage.SelfInfo>('self')\n this._cachedSelf = self\n\n return self\n }\n\n async setSelf(self: ITelegramStorage.SelfInfo | null): Promise<void> {\n this._cachedSelf = self\n\n return this._setToKv('self', self, true)\n }\n\n async getUpdatesState(): Promise<[number, number, number, number] | null> {\n const os = this.db.transaction(TABLES.kv).objectStore(TABLES.kv)\n\n const [pts, qts, date, seq] = await Promise.all([\n reqToPromise<{ value: number }>(os.get('pts')),\n reqToPromise<{ value: number }>(os.get('qts')),\n reqToPromise<{ value: number }>(os.get('date')),\n reqToPromise<{ value: number }>(os.get('seq')),\n ])\n\n if (pts === undefined || qts === undefined || date === undefined || seq === undefined) return null\n\n return [Number(pts.value), Number(qts.value), Number(date.value), Number(seq.value)]\n }\n\n setUpdatesPts(val: number): Promise<void> {\n return this._setToKv('pts', val)\n }\n\n setUpdatesQts(val: number): Promise<void> {\n return this._setToKv('qts', val)\n }\n\n setUpdatesDate(val: number): Promise<void> {\n return this._setToKv('date', val)\n }\n\n setUpdatesSeq(val: number): Promise<void> {\n return this._setToKv('seq', val)\n }\n\n async getChannelPts(entityId: number): Promise<number | null> {\n const os = this.db.transaction(TABLES.pts).objectStore(TABLES.pts)\n const row = await reqToPromise<{ pts: number }>(os.get(entityId))\n\n if (row === undefined) return null\n\n return row.pts\n }\n\n async setManyChannelPts(values: Map<number, number>): Promise<void> {\n const tx = this.db.transaction(TABLES.pts, 'readwrite')\n const os = tx.objectStore(TABLES.pts)\n\n for (const [id, pts] of values) {\n os.put({ channelId: id, pts })\n }\n\n return txToPromise(tx)\n }\n\n updatePeers(peers: ITelegramStorage.PeerInfo[]): void {\n for (const peer of peers) {\n const dto: EntityDto = {\n id: peer.id,\n hash: longToFastString(peer.accessHash),\n type: peer.type,\n username: peer.username,\n phone: peer.phone,\n updated: Date.now(),\n full: TlBinaryWriter.serializeObject(this.writerMap, peer.full),\n }\n\n this._writeLater(TABLES.entities, dto)\n\n if (!this._cachedSelf?.isBot) {\n this._writeLater(TABLES.messageRefs, null)\n }\n\n this._cache?.set(peer.id, {\n peer: getInputPeer(peer),\n full: peer.full,\n })\n }\n }\n\n private async _findPeerByReference(os: IDBObjectStore, peerId: number): Promise<tl.TypeInputPeer | null> {\n const row = await reqToPromise<MessageRefDto>(os.get(peerId))\n if (row === undefined) return null\n\n const chat = await this.getPeerById(row.chatId, false)\n if (chat === null) return null\n\n if (peerId > 0) {\n return {\n _: 'inputPeerUserFromMessage',\n userId: peerId,\n peer: chat,\n msgId: row.msgId,\n }\n }\n\n return {\n _: 'inputPeerChannelFromMessage',\n channelId: toggleChannelIdMark(peerId),\n peer: chat,\n msgId: row.msgId,\n }\n }\n\n async getPeerById(peerId: number, allowRefs = true): Promise<tl.TypeInputPeer | null> {\n const cached = this._cache?.get(peerId)\n if (cached) return cached.peer\n\n const tx = this.db.transaction([TABLES.entities, TABLES.messageRefs])\n const entOs = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(entOs.get(peerId))\n\n if (row) {\n return getInputPeer(row)\n }\n\n if (allowRefs) {\n return this._findPeerByReference(tx.objectStore(TABLES.messageRefs), peerId)\n }\n\n return null\n }\n\n async getPeerByUsername(username: string): Promise<tl.TypeInputPeer | null> {\n const tx = this.db.transaction(TABLES.entities)\n const os = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(os.index('by_username').get(username))\n\n if (row === undefined) return null\n\n return getInputPeer(row)\n }\n\n async getPeerByPhone(phone: string): Promise<tl.TypeInputPeer | null> {\n const tx = this.db.transaction(TABLES.entities)\n const os = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(os.index('by_phone').get(phone))\n\n if (row === undefined) return null\n\n return getInputPeer(row)\n }\n\n async getFullPeerById(peerId: number): Promise<tl.TypeUser | tl.TypeChat | null> {\n const cached = this._cache?.get(peerId)\n if (cached) return cached.full\n\n const tx = this.db.transaction(TABLES.entities)\n const os = tx.objectStore(TABLES.entities)\n\n const row = await reqToPromise<EntityDto>(os.get(peerId))\n\n if (row === undefined) return null\n\n return this._readFullPeer(row.full)\n }\n\n async saveReferenceMessage(peerId: number, chatId: number, messageId: number): Promise<void> {\n const os = this.db.transaction(TABLES.messageRefs, 'readwrite').objectStore(TABLES.messageRefs)\n\n await reqToPromise(os.put({ peerId, chatId, msgId: messageId } satisfies MessageRefDto))\n }\n\n async deleteReferenceMessages(chatId: number, messageIds: number[]): Promise<void> {\n const tx = this.db.transaction(TABLES.messageRefs, 'readwrite')\n const os = tx.objectStore(TABLES.messageRefs)\n const index = os.index('by_msg')\n\n for (const msgId of messageIds) {\n const key = await reqToPromise(index.getKey([chatId, msgId]))\n if (key === undefined) continue\n\n os.delete(key)\n }\n\n return txToPromise(tx)\n }\n\n // IStateStorage implementation\n\n async getState(key: string): Promise<unknown> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const row = await reqToPromise<FsmItemDto>(os.get(key))\n if (!row) return null\n\n if (row.expires && row.expires < Date.now()) {\n await reqToPromise(os.delete(key))\n\n return null\n }\n\n return JSON.parse(row.value) as unknown\n }\n\n async setState(key: string, state: unknown, ttl?: number): Promise<void> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const dto: FsmItemDto = {\n key,\n value: JSON.stringify(state),\n expires: ttl ? Date.now() + ttl * 1000 : undefined,\n }\n\n await reqToPromise(os.put(dto))\n }\n\n async deleteState(key: string): Promise<void> {\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n await reqToPromise(os.delete(key))\n }\n\n getCurrentScene(key: string): Promise<string | null> {\n return this.getState(`$current_scene_${key}`) as Promise<string | null>\n }\n\n setCurrentScene(key: string, scene: string, ttl?: number): Promise<void> {\n return this.setState(`$current_scene_${key}`, scene, ttl)\n }\n\n deleteCurrentScene(key: string): Promise<void> {\n return this.deleteState(`$current_scene_${key}`)\n }\n\n async getRateLimit(key: string, limit: number, window: number): Promise<[number, number]> {\n // leaky bucket\n const now = Date.now()\n\n const tx = this.db.transaction(TABLES.state, 'readwrite')\n const os = tx.objectStore(TABLES.state)\n\n const row = await reqToPromise<FsmItemDto>(os.get(`$rate_limit_${key}`))\n\n if (!row || row.expires! < now) {\n // expired or does not exist\n const dto: FsmItemDto = {\n key: `$rate_limit_${key}`,\n value: limit.toString(),\n expires: now + window * 1000,\n }\n await reqToPromise(os.put(dto))\n\n return [limit, dto.expires!]\n }\n\n let value = Number(row.value)\n\n if (value > 0) {\n value -= 1\n row.value = value.toString()\n await reqToPromise(os.put(row))\n }\n\n return [value, row.expires!]\n }\n\n resetRateLimit(key: string): Promise<void> {\n return this.deleteState(`$rate_limit_${key}`)\n }\n}\n"]}
@@ -1 +1,2 @@
1
1
  export * from './abstract.js';
2
+ export * from './memory.js';
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./abstract.js"), exports);
18
+ __exportStar(require("./memory.js"), exports);
18
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B","sourcesContent":["export * from './abstract.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B;AAC7B,8CAA2B","sourcesContent":["export * from './abstract.js'\nexport * from './memory.js'\n"]}
@@ -24,6 +24,7 @@ class JsonMemoryStorage extends memory_js_1.MemoryStorage {
24
24
  }
25
25
  case 'authKeysTempExpiry':
26
26
  case 'pts':
27
+ case 'futureSalts':
27
28
  return new Map(Object.entries(value));
28
29
  case 'phoneIndex':
29
30
  case 'usernameIndex':
@@ -1 +1 @@
1
- {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/storage/json.ts"],"names":[],"mappings":";;;AAAA,wDAAwD;AACxD,mDAAuE;AAEvE,2CAA+D;AAE/D;;;GAGG;AACH,MAAa,iBAAkB,SAAQ,yBAAa;IACtC,SAAS,CAAC,IAAY;QAC5B,IAAI,CAAC,aAAa,CACd,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC5B,QAAQ,GAAG,EAAE;gBACT,KAAK,UAAU,CAAC;gBAChB,KAAK,cAAc,CAAC,CAAC;oBACjB,MAAM,GAAG,GAAG,IAAI,GAAG,EAA+B,CAEjD;oBAAC,KAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAY,EAAE,EAAE;wBACnD,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;wBACnC,MAAM,MAAM,GAAG,GAAG,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;wBAE7D,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAA,iCAAoB,EAAC,GAAG,CAAC,CAAC,CAAA;oBAC9C,CAAC,CAAC,CAAA;oBAEF,OAAO,GAAG,CAAA;iBACb;gBACD,KAAK,oBAAoB,CAAC;gBAC1B,KAAK,KAAK;oBACN,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAA+B,CAAC,CAAC,CAAA;gBACnE,KAAK,YAAY,CAAC;gBAClB,KAAK,eAAe,CAAC;gBACrB,KAAK,KAAK,CAAC;gBACX,KAAK,IAAI,CAAC;gBACV,KAAK,MAAM,CAAC;gBACZ,KAAK,UAAU;oBACX,OAAO,IAAI,GAAG,EAAE,CAAA;aACvB;YAED,OAAO,KAAK,CAAA;QAChB,CAAC,CAAuB,CAC3B,CAAA;IACL,CAAC;IAES,SAAS;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC9C,QAAQ,GAAG,EAAE;gBACT,KAAK,UAAU,CAAC;gBAChB,KAAK,cAAc,CAAC,CAAC;oBACjB,MAAM,MAAM,GAAG,KAAuC,CAAA;oBAEtD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;yBACvB,MAAM,CAAC,CAAC,EAAE,EAA8B,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;yBAC1D,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,GAAG,IAAA,yBAAY,EAAC,GAAG,CAAC,CAAC;yBACpD,IAAI,CAAC,GAAG,CAAC,CAAA;iBACjB;gBACD,KAAK,oBAAoB,CAAC;gBAC1B,KAAK,YAAY,CAAC;gBAClB,KAAK,eAAe,CAAC;gBACrB,KAAK,KAAK,CAAC;gBACX,KAAK,KAAK,CAAC;gBACX,KAAK,IAAI;oBACL,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,GAAI,KAA6B,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;gBAC5E,KAAK,UAAU;oBACX,OAAO,EAAE,CAAA;aAChB;YAED,OAAO,KAAK,CAAA;QAChB,CAAC,CAAC,CAAA;IACN,CAAC;CACJ;AA7DD,8CA6DC","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-return */\nimport { base64DecodeToBuffer, base64Encode } from '@mtcute/tl-runtime'\n\nimport { MemorySessionState, MemoryStorage } from './memory.js'\n\n/**\n * Helper class that provides json serialization functions\n * to the session.\n */\nexport class JsonMemoryStorage extends MemoryStorage {\n protected _loadJson(json: string): void {\n this._setStateFrom(\n JSON.parse(json, (key, value) => {\n switch (key) {\n case 'authKeys':\n case 'authKeysTemp': {\n const ret = new Map<string | number, Uint8Array>()\n\n ;(value as string).split('|').forEach((pair: string) => {\n const [dcId, b64] = pair.split(',')\n const mapKey = key === 'authKeysTemp' ? dcId : parseInt(dcId)\n\n ret.set(mapKey, base64DecodeToBuffer(b64))\n })\n\n return ret\n }\n case 'authKeysTempExpiry':\n case 'pts':\n return new Map(Object.entries(value as Record<string, string>))\n case 'phoneIndex':\n case 'usernameIndex':\n case 'fsm':\n case 'rl':\n case 'refs':\n case 'entities':\n return new Map()\n }\n\n return value\n }) as MemorySessionState,\n )\n }\n\n protected _saveJson(): string {\n return JSON.stringify(this._state, (key, value) => {\n switch (key) {\n case 'authKeys':\n case 'authKeysTemp': {\n const value_ = value as Map<string, Uint8Array | null>\n\n return [...value_.entries()]\n .filter((it): it is [string, Uint8Array] => it[1] !== null)\n .map(([dcId, key]) => dcId + ',' + base64Encode(key))\n .join('|')\n }\n case 'authKeysTempExpiry':\n case 'phoneIndex':\n case 'usernameIndex':\n case 'pts':\n case 'fsm':\n case 'rl':\n return Object.fromEntries([...(value as Map<string, string>).entries()])\n case 'entities':\n return {}\n }\n\n return value\n })\n }\n}\n"]}
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/storage/json.ts"],"names":[],"mappings":";;;AAAA,wDAAwD;AACxD,mDAAuE;AAEvE,2CAA+D;AAE/D;;;GAGG;AACH,MAAa,iBAAkB,SAAQ,yBAAa;IACtC,SAAS,CAAC,IAAY;QAC5B,IAAI,CAAC,aAAa,CACd,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC5B,QAAQ,GAAG,EAAE;gBACT,KAAK,UAAU,CAAC;gBAChB,KAAK,cAAc,CAAC,CAAC;oBACjB,MAAM,GAAG,GAAG,IAAI,GAAG,EAA+B,CAEjD;oBAAC,KAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAY,EAAE,EAAE;wBACnD,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;wBACnC,MAAM,MAAM,GAAG,GAAG,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;wBAE7D,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAA,iCAAoB,EAAC,GAAG,CAAC,CAAC,CAAA;oBAC9C,CAAC,CAAC,CAAA;oBAEF,OAAO,GAAG,CAAA;iBACb;gBACD,KAAK,oBAAoB,CAAC;gBAC1B,KAAK,KAAK,CAAC;gBACX,KAAK,aAAa;oBACd,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAA+B,CAAC,CAAC,CAAA;gBACnE,KAAK,YAAY,CAAC;gBAClB,KAAK,eAAe,CAAC;gBACrB,KAAK,KAAK,CAAC;gBACX,KAAK,IAAI,CAAC;gBACV,KAAK,MAAM,CAAC;gBACZ,KAAK,UAAU;oBACX,OAAO,IAAI,GAAG,EAAE,CAAA;aACvB;YAED,OAAO,KAAK,CAAA;QAChB,CAAC,CAAuB,CAC3B,CAAA;IACL,CAAC;IAES,SAAS;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC9C,QAAQ,GAAG,EAAE;gBACT,KAAK,UAAU,CAAC;gBAChB,KAAK,cAAc,CAAC,CAAC;oBACjB,MAAM,MAAM,GAAG,KAAuC,CAAA;oBAEtD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;yBACvB,MAAM,CAAC,CAAC,EAAE,EAA8B,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;yBAC1D,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,GAAG,IAAA,yBAAY,EAAC,GAAG,CAAC,CAAC;yBACpD,IAAI,CAAC,GAAG,CAAC,CAAA;iBACjB;gBACD,KAAK,oBAAoB,CAAC;gBAC1B,KAAK,YAAY,CAAC;gBAClB,KAAK,eAAe,CAAC;gBACrB,KAAK,KAAK,CAAC;gBACX,KAAK,KAAK,CAAC;gBACX,KAAK,IAAI;oBACL,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,GAAI,KAA6B,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;gBAC5E,KAAK,UAAU;oBACX,OAAO,EAAE,CAAA;aAChB;YAED,OAAO,KAAK,CAAA;QAChB,CAAC,CAAC,CAAA;IACN,CAAC;CACJ;AA9DD,8CA8DC","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-return */\nimport { base64DecodeToBuffer, base64Encode } from '@mtcute/tl-runtime'\n\nimport { MemorySessionState, MemoryStorage } from './memory.js'\n\n/**\n * Helper class that provides json serialization functions\n * to the session.\n */\nexport class JsonMemoryStorage extends MemoryStorage {\n protected _loadJson(json: string): void {\n this._setStateFrom(\n JSON.parse(json, (key, value) => {\n switch (key) {\n case 'authKeys':\n case 'authKeysTemp': {\n const ret = new Map<string | number, Uint8Array>()\n\n ;(value as string).split('|').forEach((pair: string) => {\n const [dcId, b64] = pair.split(',')\n const mapKey = key === 'authKeysTemp' ? dcId : parseInt(dcId)\n\n ret.set(mapKey, base64DecodeToBuffer(b64))\n })\n\n return ret\n }\n case 'authKeysTempExpiry':\n case 'pts':\n case 'futureSalts':\n return new Map(Object.entries(value as Record<string, string>))\n case 'phoneIndex':\n case 'usernameIndex':\n case 'fsm':\n case 'rl':\n case 'refs':\n case 'entities':\n return new Map()\n }\n\n return value\n }) as MemorySessionState,\n )\n }\n\n protected _saveJson(): string {\n return JSON.stringify(this._state, (key, value) => {\n switch (key) {\n case 'authKeys':\n case 'authKeysTemp': {\n const value_ = value as Map<string, Uint8Array | null>\n\n return [...value_.entries()]\n .filter((it): it is [string, Uint8Array] => it[1] !== null)\n .map(([dcId, key]) => dcId + ',' + base64Encode(key))\n .join('|')\n }\n case 'authKeysTempExpiry':\n case 'phoneIndex':\n case 'usernameIndex':\n case 'pts':\n case 'fsm':\n case 'rl':\n return Object.fromEntries([...(value as Map<string, string>).entries()])\n case 'entities':\n return {}\n }\n\n return value\n })\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { tl } from '@mtcute/tl';
1
+ import { mtp, tl } from '@mtcute/tl';
2
2
  import { ITelegramStorage } from './abstract.js';
3
- declare const CURRENT_VERSION = 2;
3
+ declare const CURRENT_VERSION = 3;
4
4
  type PeerInfoWithUpdated = ITelegramStorage.PeerInfo & {
5
5
  updated: number;
6
6
  };
@@ -25,6 +25,7 @@ export interface MemorySessionState {
25
25
  rem: number;
26
26
  }>;
27
27
  self: ITelegramStorage.SelfInfo | null;
28
+ futureSalts: Map<number, mtp.RawMt_future_salt[]>;
28
29
  }
29
30
  /**
30
31
  * In-memory storage implementation for mtcute.
@@ -74,6 +75,8 @@ export declare class MemoryStorage implements ITelegramStorage {
74
75
  private _vacuum;
75
76
  getDefaultDcs(): ITelegramStorage.DcOptions | null;
76
77
  setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): void;
78
+ setFutureSalts(dcId: number, salts: mtp.RawMt_future_salt[]): void;
79
+ getFutureSalts(dcId: number): mtp.RawMt_future_salt[] | null;
77
80
  setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): void;
78
81
  setAuthKeyFor(dcId: number, key: Uint8Array | null): void;
79
82
  getAuthKeyFor(dcId: number, tempIndex?: number): Uint8Array | null;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MemoryStorage = void 0;
4
4
  const index_js_1 = require("../utils/index.js");
5
- const CURRENT_VERSION = 2;
5
+ const CURRENT_VERSION = 3;
6
6
  const USERNAME_TTL = 86400000; // 24 hours
7
7
  /**
8
8
  * In-memory storage implementation for mtcute.
@@ -40,6 +40,7 @@ class MemoryStorage {
40
40
  fsm: new Map(),
41
41
  rl: new Map(),
42
42
  self: null,
43
+ futureSalts: new Map(),
43
44
  };
44
45
  this._cachedInputPeers?.clear();
45
46
  this._cachedFull?.clear();
@@ -55,7 +56,12 @@ class MemoryStorage {
55
56
  if (ver === 1) {
56
57
  // v2: introduced message references
57
58
  obj.refs = new Map();
58
- obj.$version = ver = 2;
59
+ obj.$version = ver = 2; // eslint-disable-line
60
+ }
61
+ if (ver === 2) {
62
+ // v3: introduced future salts
63
+ obj.futureSalts = new Map();
64
+ obj.$version = ver = 3;
59
65
  }
60
66
  if (ver !== CURRENT_VERSION)
61
67
  return;
@@ -104,6 +110,12 @@ class MemoryStorage {
104
110
  setDefaultDcs(dcs) {
105
111
  this._state.defaultDcs = dcs;
106
112
  }
113
+ setFutureSalts(dcId, salts) {
114
+ this._state.futureSalts.set(dcId, salts);
115
+ }
116
+ getFutureSalts(dcId) {
117
+ return this._state.futureSalts.get(dcId) ?? null;
118
+ }
107
119
  setTempAuthKeyFor(dcId, index, key, expiresAt) {
108
120
  const k = `${dcId}:${index}`;
109
121
  if (key) {
@@ -141,6 +153,8 @@ class MemoryStorage {
141
153
  this._state.authKeysTempExpiry.delete(key);
142
154
  }
143
155
  }
156
+ // future salts are linked to auth keys
157
+ this._state.futureSalts.delete(dcId);
144
158
  }
145
159
  updatePeers(peers) {
146
160
  for (const peer of peers) {
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/storage/memory.ts"],"names":[],"mappings":"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","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { LruMap, toggleChannelIdMark } from '../utils/index.js'\nimport { ITelegramStorage } from './abstract.js'\n\nconst CURRENT_VERSION = 2\n\ntype PeerInfoWithUpdated = ITelegramStorage.PeerInfo & { updated: number }\n\nexport interface MemorySessionState {\n // forwards compatibility for persistent storages\n $version: typeof CURRENT_VERSION\n\n defaultDcs: ITelegramStorage.DcOptions | null\n authKeys: Map<number, Uint8Array>\n authKeysTemp: Map<string, Uint8Array>\n authKeysTempExpiry: Map<string, number>\n\n // marked peer id -> entity info\n entities: Map<number, PeerInfoWithUpdated>\n // phone number -> peer id\n phoneIndex: Map<string, number>\n // username -> peer id\n usernameIndex: Map<string, number>\n\n // reference messages. peer id -> `${chat id}:${msg id}][]\n refs: Map<number, Set<string>>\n\n // common pts, date, seq, qts\n gpts: [number, number, number, number] | null\n // channel pts\n pts: Map<number, number>\n\n // state for fsm\n fsm: Map<\n string,\n {\n // value\n v: unknown\n // expires\n e?: number\n }\n >\n\n // state for rate limiter\n rl: Map<\n string,\n {\n // reset\n res: number\n // remaining\n rem: number\n }\n >\n\n self: ITelegramStorage.SelfInfo | null\n}\n\nconst USERNAME_TTL = 86400000 // 24 hours\n\n/**\n * In-memory storage implementation for mtcute.\n *\n * This storage is **not persistent**, meaning that all data\n * **will** be lost on restart. Only use this storage for testing,\n * or if you know what you're doing.\n */\nexport class MemoryStorage implements ITelegramStorage {\n protected _state!: MemorySessionState\n private _cachedInputPeers: LruMap<number, tl.TypeInputPeer> = new LruMap(100)\n\n private _cachedFull: LruMap<number, tl.TypeUser | tl.TypeChat>\n\n private _vacuumTimeout?: NodeJS.Timeout\n private _vacuumInterval: number\n\n constructor(params?: {\n /**\n * Maximum number of cached full entities.\n *\n * Note that full entities are **NOT** persisted\n * to the disk (in case this storage is backed\n * by a local storage), and only available within\n * the current runtime.\n *\n * @default `100`, use `0` to disable\n */\n cacheSize?: number\n\n /**\n * Interval in milliseconds for vacuuming the storage.\n *\n * When vacuuming, the storage will remove expired FSM\n * states to reduce memory usage.\n *\n * @default `300_000` (5 minutes)\n */\n vacuumInterval?: number\n }) {\n this.reset(true)\n this._cachedFull = new LruMap(params?.cacheSize ?? 100)\n this._vacuumInterval = params?.vacuumInterval ?? 300_000\n }\n\n load(): void {\n this._vacuumTimeout = setInterval(this._vacuum.bind(this), this._vacuumInterval)\n }\n\n destroy(): void {\n clearInterval(this._vacuumTimeout)\n }\n\n reset(withAuthKeys = false): void {\n this._state = {\n $version: CURRENT_VERSION,\n defaultDcs: null,\n authKeys: withAuthKeys ? new Map<number, Uint8Array>() : this._state.authKeys,\n authKeysTemp: withAuthKeys ? new Map<string, Uint8Array>() : this._state.authKeysTemp,\n authKeysTempExpiry: withAuthKeys ? new Map<string, number>() : this._state.authKeysTempExpiry,\n entities: new Map(),\n phoneIndex: new Map(),\n usernameIndex: new Map(),\n refs: new Map(),\n gpts: null,\n pts: new Map(),\n fsm: new Map(),\n rl: new Map(),\n self: null,\n }\n this._cachedInputPeers?.clear()\n this._cachedFull?.clear()\n }\n\n /**\n * Set a given object as an underlying state.\n *\n * Note that this object will be used as-is, so if\n * you plan on using it somewhere else, be sure to copy it beforehand.\n */\n protected _setStateFrom(obj: MemorySessionState): void {\n let ver = obj.$version as number\n\n if (ver === 1) {\n // v2: introduced message references\n obj.refs = new Map()\n obj.$version = ver = 2\n }\n if (ver !== CURRENT_VERSION) return\n\n // populate indexes if needed\n let populate = false\n\n if (!obj.phoneIndex?.size) {\n obj.phoneIndex = new Map()\n populate = true\n }\n if (!obj.usernameIndex?.size) {\n obj.usernameIndex = new Map()\n populate = true\n }\n\n if (populate) {\n Object.values(obj.entities).forEach((ent: ITelegramStorage.PeerInfo) => {\n if (ent.phone) obj.phoneIndex.set(ent.phone, ent.id)\n\n if (ent.username) {\n obj.usernameIndex.set(ent.username, ent.id)\n }\n })\n }\n\n this._state = obj\n }\n\n private _vacuum(): void {\n // remove expired entities from fsm and rate limit storages\n\n const now = Date.now()\n\n // make references in advance to avoid lookups\n const state = this._state\n const fsm = state.fsm\n const rl = state.rl\n\n for (const [key, item] of fsm) {\n if (item.e && item.e < now) {\n fsm.delete(key)\n }\n }\n\n for (const [key, item] of rl) {\n if (item.res < now) {\n rl.delete(key)\n }\n }\n }\n\n getDefaultDcs(): ITelegramStorage.DcOptions | null {\n return this._state.defaultDcs\n }\n\n setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): void {\n this._state.defaultDcs = dcs\n }\n\n setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): void {\n const k = `${dcId}:${index}`\n\n if (key) {\n this._state.authKeysTemp.set(k, key)\n this._state.authKeysTempExpiry.set(k, expiresAt)\n } else {\n this._state.authKeysTemp.delete(k)\n this._state.authKeysTempExpiry.delete(k)\n }\n }\n\n setAuthKeyFor(dcId: number, key: Uint8Array | null): void {\n if (key) {\n this._state.authKeys.set(dcId, key)\n } else {\n this._state.authKeys.delete(dcId)\n }\n }\n\n getAuthKeyFor(dcId: number, tempIndex?: number): Uint8Array | null {\n if (tempIndex !== undefined) {\n const k = `${dcId}:${tempIndex}`\n\n if (Date.now() > (this._state.authKeysTempExpiry.get(k) ?? 0)) {\n return null\n }\n\n return this._state.authKeysTemp.get(k) ?? null\n }\n\n return this._state.authKeys.get(dcId) ?? null\n }\n\n dropAuthKeysFor(dcId: number): void {\n this._state.authKeys.delete(dcId)\n\n for (const key of this._state.authKeysTemp.keys()) {\n if (key.startsWith(`${dcId}:`)) {\n this._state.authKeysTemp.delete(key)\n this._state.authKeysTempExpiry.delete(key)\n }\n }\n }\n\n updatePeers(peers: PeerInfoWithUpdated[]): void {\n for (const peer of peers) {\n this._cachedFull.set(peer.id, peer.full)\n\n peer.updated = Date.now()\n const old = this._state.entities.get(peer.id)\n\n if (old) {\n // delete old index entries if needed\n if (old.username && peer.username !== old.username) {\n this._state.usernameIndex.delete(old.username)\n }\n if (old.phone && old.phone !== peer.phone) {\n this._state.phoneIndex.delete(old.phone)\n }\n }\n\n if (peer.username) {\n this._state.usernameIndex.set(peer.username, peer.id)\n }\n\n if (peer.phone) this._state.phoneIndex.set(peer.phone, peer.id)\n\n this._state.entities.set(peer.id, peer)\n\n // no point in storing references anymore, since we have the full peer\n if (this._state.refs.has(peer.id)) {\n this._state.refs.delete(peer.id)\n }\n }\n }\n\n protected _getInputPeer(peerInfo?: ITelegramStorage.PeerInfo): tl.TypeInputPeer | null {\n if (!peerInfo) return null\n\n switch (peerInfo.type) {\n case 'user':\n return {\n _: 'inputPeerUser',\n userId: peerInfo.id,\n accessHash: peerInfo.accessHash,\n }\n case 'chat':\n return {\n _: 'inputPeerChat',\n chatId: -peerInfo.id,\n }\n case 'channel':\n return {\n _: 'inputPeerChannel',\n channelId: toggleChannelIdMark(peerInfo.id),\n accessHash: peerInfo.accessHash,\n }\n }\n }\n\n private _findPeerByRef(peerId: number): tl.TypeInputPeer | null {\n const refs = this._state.refs.get(peerId)\n if (!refs || refs.size === 0) return null\n\n const [ref] = refs.values()\n const [chatId, msgId] = ref.split(':').map(Number)\n\n const chatPeer = this._getInputPeer(this._state.entities.get(chatId))\n if (!chatPeer) return null\n\n if (peerId > 0) {\n // user\n return {\n _: 'inputPeerUserFromMessage',\n msgId,\n userId: peerId,\n peer: chatPeer,\n }\n }\n\n // channel\n return {\n _: 'inputPeerChannelFromMessage',\n msgId,\n channelId: toggleChannelIdMark(peerId),\n peer: chatPeer,\n }\n }\n\n getPeerById(peerId: number): tl.TypeInputPeer | null {\n if (this._cachedInputPeers.has(peerId)) {\n return this._cachedInputPeers.get(peerId)!\n }\n\n let peer = this._getInputPeer(this._state.entities.get(peerId))\n if (!peer) peer = this._findPeerByRef(peerId)\n if (peer) this._cachedInputPeers.set(peerId, peer)\n\n return peer\n }\n\n getPeerByPhone(phone: string): tl.TypeInputPeer | null {\n const peerId = this._state.phoneIndex.get(phone)\n if (!peerId) return null\n\n return this._getInputPeer(this._state.entities.get(peerId))\n }\n\n getPeerByUsername(username: string): tl.TypeInputPeer | null {\n const id = this._state.usernameIndex.get(username.toLowerCase())\n if (!id) return null\n const peer = this._state.entities.get(id)\n if (!peer) return null\n\n if (Date.now() - peer.updated > USERNAME_TTL) return null\n\n return this._getInputPeer(peer)\n }\n\n saveReferenceMessage(peerId: number, chatId: number, messageId: number): void {\n if (!this._state.refs.has(peerId)) {\n this._state.refs.set(peerId, new Set())\n }\n\n this._state.refs.get(peerId)!.add(`${chatId}:${messageId}`)\n }\n\n deleteReferenceMessages(chatId: number, messageIds: number[]): void {\n // not the most efficient way, but it's fine\n for (const refs of this._state.refs.values()) {\n for (const msg of messageIds) {\n refs.delete(`${chatId}:${msg}`)\n }\n }\n }\n\n getSelf(): ITelegramStorage.SelfInfo | null {\n return this._state.self\n }\n\n setSelf(self: ITelegramStorage.SelfInfo | null): void {\n this._state.self = self\n }\n\n setManyChannelPts(values: Map<number, number>): void {\n for (const [id, pts] of values) {\n this._state.pts.set(id, pts)\n }\n }\n\n getChannelPts(entityId: number): number | null {\n return this._state.pts.get(entityId) ?? null\n }\n\n getUpdatesState(): [number, number, number, number] | null {\n return this._state.gpts ?? null\n }\n\n setUpdatesPts(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[0] = val\n }\n\n setUpdatesQts(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[1] = val\n }\n\n setUpdatesDate(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[2] = val\n }\n\n setUpdatesSeq(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[3] = val\n }\n\n getFullPeerById(id: number): tl.TypeUser | tl.TypeChat | null {\n return this._cachedFull.get(id) ?? null\n }\n\n // IStateStorage implementation\n\n getState(key: string): unknown {\n const val = this._state.fsm.get(key)\n if (!val) return null\n\n if (val.e && val.e < Date.now()) {\n // expired\n this._state.fsm.delete(key)\n\n return null\n }\n\n return val.v\n }\n\n setState(key: string, state: unknown, ttl?: number): void {\n this._state.fsm.set(key, {\n v: state,\n e: ttl ? Date.now() + ttl * 1000 : undefined,\n })\n }\n\n deleteState(key: string): void {\n this._state.fsm.delete(key)\n }\n\n getCurrentScene(key: string): string | null {\n return this.getState(`$current_scene_${key}`) as string | null\n }\n\n setCurrentScene(key: string, scene: string, ttl?: number): void {\n return this.setState(`$current_scene_${key}`, scene, ttl)\n }\n\n deleteCurrentScene(key: string): void {\n this._state.fsm.delete(`$current_scene_${key}`)\n }\n\n getRateLimit(key: string, limit: number, window: number): [number, number] {\n // leaky bucket\n const now = Date.now()\n\n const item = this._state.rl.get(key)\n\n if (!item) {\n const state = {\n res: now + window * 1000,\n rem: limit,\n }\n\n this._state.rl.set(key, state)\n\n return [state.rem, state.res]\n }\n\n if (item.res < now) {\n // expired\n\n const state = {\n res: now + window * 1000,\n rem: limit,\n }\n\n this._state.rl.set(key, state)\n\n return [state.rem, state.res]\n }\n\n item.rem = item.rem > 0 ? item.rem - 1 : 0\n\n return [item.rem, item.res]\n }\n\n resetRateLimit(key: string): void {\n this._state.rl.delete(key)\n }\n}\n"]}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/storage/memory.ts"],"names":[],"mappings":"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","sourcesContent":["import { mtp, tl } from '@mtcute/tl'\n\nimport { LruMap, toggleChannelIdMark } from '../utils/index.js'\nimport { ITelegramStorage } from './abstract.js'\n\nconst CURRENT_VERSION = 3\n\ntype PeerInfoWithUpdated = ITelegramStorage.PeerInfo & { updated: number }\n\nexport interface MemorySessionState {\n // forwards compatibility for persistent storages\n $version: typeof CURRENT_VERSION\n\n defaultDcs: ITelegramStorage.DcOptions | null\n authKeys: Map<number, Uint8Array>\n authKeysTemp: Map<string, Uint8Array>\n authKeysTempExpiry: Map<string, number>\n\n // marked peer id -> entity info\n entities: Map<number, PeerInfoWithUpdated>\n // phone number -> peer id\n phoneIndex: Map<string, number>\n // username -> peer id\n usernameIndex: Map<string, number>\n\n // reference messages. peer id -> `${chat id}:${msg id}][]\n refs: Map<number, Set<string>>\n\n // common pts, date, seq, qts\n gpts: [number, number, number, number] | null\n // channel pts\n pts: Map<number, number>\n\n // state for fsm\n fsm: Map<\n string,\n {\n // value\n v: unknown\n // expires\n e?: number\n }\n >\n\n // state for rate limiter\n rl: Map<\n string,\n {\n // reset\n res: number\n // remaining\n rem: number\n }\n >\n\n self: ITelegramStorage.SelfInfo | null\n futureSalts: Map<number, mtp.RawMt_future_salt[]>\n}\n\nconst USERNAME_TTL = 86400000 // 24 hours\n\n/**\n * In-memory storage implementation for mtcute.\n *\n * This storage is **not persistent**, meaning that all data\n * **will** be lost on restart. Only use this storage for testing,\n * or if you know what you're doing.\n */\nexport class MemoryStorage implements ITelegramStorage {\n protected _state!: MemorySessionState\n private _cachedInputPeers: LruMap<number, tl.TypeInputPeer> = new LruMap(100)\n\n private _cachedFull: LruMap<number, tl.TypeUser | tl.TypeChat>\n\n private _vacuumTimeout?: NodeJS.Timeout\n private _vacuumInterval: number\n\n constructor(params?: {\n /**\n * Maximum number of cached full entities.\n *\n * Note that full entities are **NOT** persisted\n * to the disk (in case this storage is backed\n * by a local storage), and only available within\n * the current runtime.\n *\n * @default `100`, use `0` to disable\n */\n cacheSize?: number\n\n /**\n * Interval in milliseconds for vacuuming the storage.\n *\n * When vacuuming, the storage will remove expired FSM\n * states to reduce memory usage.\n *\n * @default `300_000` (5 minutes)\n */\n vacuumInterval?: number\n }) {\n this.reset(true)\n this._cachedFull = new LruMap(params?.cacheSize ?? 100)\n this._vacuumInterval = params?.vacuumInterval ?? 300_000\n }\n\n load(): void {\n this._vacuumTimeout = setInterval(this._vacuum.bind(this), this._vacuumInterval)\n }\n\n destroy(): void {\n clearInterval(this._vacuumTimeout)\n }\n\n reset(withAuthKeys = false): void {\n this._state = {\n $version: CURRENT_VERSION,\n defaultDcs: null,\n authKeys: withAuthKeys ? new Map<number, Uint8Array>() : this._state.authKeys,\n authKeysTemp: withAuthKeys ? new Map<string, Uint8Array>() : this._state.authKeysTemp,\n authKeysTempExpiry: withAuthKeys ? new Map<string, number>() : this._state.authKeysTempExpiry,\n entities: new Map(),\n phoneIndex: new Map(),\n usernameIndex: new Map(),\n refs: new Map(),\n gpts: null,\n pts: new Map(),\n fsm: new Map(),\n rl: new Map(),\n self: null,\n futureSalts: new Map(),\n }\n this._cachedInputPeers?.clear()\n this._cachedFull?.clear()\n }\n\n /**\n * Set a given object as an underlying state.\n *\n * Note that this object will be used as-is, so if\n * you plan on using it somewhere else, be sure to copy it beforehand.\n */\n protected _setStateFrom(obj: MemorySessionState): void {\n let ver = obj.$version as number\n\n if (ver === 1) {\n // v2: introduced message references\n obj.refs = new Map()\n obj.$version = ver = 2 as any // eslint-disable-line\n }\n if (ver === 2) {\n // v3: introduced future salts\n obj.futureSalts = new Map()\n obj.$version = ver = 3\n }\n if (ver !== CURRENT_VERSION) return\n\n // populate indexes if needed\n let populate = false\n\n if (!obj.phoneIndex?.size) {\n obj.phoneIndex = new Map()\n populate = true\n }\n if (!obj.usernameIndex?.size) {\n obj.usernameIndex = new Map()\n populate = true\n }\n\n if (populate) {\n Object.values(obj.entities).forEach((ent: ITelegramStorage.PeerInfo) => {\n if (ent.phone) obj.phoneIndex.set(ent.phone, ent.id)\n\n if (ent.username) {\n obj.usernameIndex.set(ent.username, ent.id)\n }\n })\n }\n\n this._state = obj\n }\n\n private _vacuum(): void {\n // remove expired entities from fsm and rate limit storages\n\n const now = Date.now()\n\n // make references in advance to avoid lookups\n const state = this._state\n const fsm = state.fsm\n const rl = state.rl\n\n for (const [key, item] of fsm) {\n if (item.e && item.e < now) {\n fsm.delete(key)\n }\n }\n\n for (const [key, item] of rl) {\n if (item.res < now) {\n rl.delete(key)\n }\n }\n }\n\n getDefaultDcs(): ITelegramStorage.DcOptions | null {\n return this._state.defaultDcs\n }\n\n setDefaultDcs(dcs: ITelegramStorage.DcOptions | null): void {\n this._state.defaultDcs = dcs\n }\n\n setFutureSalts(dcId: number, salts: mtp.RawMt_future_salt[]): void {\n this._state.futureSalts.set(dcId, salts)\n }\n\n getFutureSalts(dcId: number): mtp.RawMt_future_salt[] | null {\n return this._state.futureSalts.get(dcId) ?? null\n }\n\n setTempAuthKeyFor(dcId: number, index: number, key: Uint8Array | null, expiresAt: number): void {\n const k = `${dcId}:${index}`\n\n if (key) {\n this._state.authKeysTemp.set(k, key)\n this._state.authKeysTempExpiry.set(k, expiresAt)\n } else {\n this._state.authKeysTemp.delete(k)\n this._state.authKeysTempExpiry.delete(k)\n }\n }\n\n setAuthKeyFor(dcId: number, key: Uint8Array | null): void {\n if (key) {\n this._state.authKeys.set(dcId, key)\n } else {\n this._state.authKeys.delete(dcId)\n }\n }\n\n getAuthKeyFor(dcId: number, tempIndex?: number): Uint8Array | null {\n if (tempIndex !== undefined) {\n const k = `${dcId}:${tempIndex}`\n\n if (Date.now() > (this._state.authKeysTempExpiry.get(k) ?? 0)) {\n return null\n }\n\n return this._state.authKeysTemp.get(k) ?? null\n }\n\n return this._state.authKeys.get(dcId) ?? null\n }\n\n dropAuthKeysFor(dcId: number): void {\n this._state.authKeys.delete(dcId)\n\n for (const key of this._state.authKeysTemp.keys()) {\n if (key.startsWith(`${dcId}:`)) {\n this._state.authKeysTemp.delete(key)\n this._state.authKeysTempExpiry.delete(key)\n }\n }\n\n // future salts are linked to auth keys\n this._state.futureSalts.delete(dcId)\n }\n\n updatePeers(peers: PeerInfoWithUpdated[]): void {\n for (const peer of peers) {\n this._cachedFull.set(peer.id, peer.full)\n\n peer.updated = Date.now()\n const old = this._state.entities.get(peer.id)\n\n if (old) {\n // delete old index entries if needed\n if (old.username && peer.username !== old.username) {\n this._state.usernameIndex.delete(old.username)\n }\n if (old.phone && old.phone !== peer.phone) {\n this._state.phoneIndex.delete(old.phone)\n }\n }\n\n if (peer.username) {\n this._state.usernameIndex.set(peer.username, peer.id)\n }\n\n if (peer.phone) this._state.phoneIndex.set(peer.phone, peer.id)\n\n this._state.entities.set(peer.id, peer)\n\n // no point in storing references anymore, since we have the full peer\n if (this._state.refs.has(peer.id)) {\n this._state.refs.delete(peer.id)\n }\n }\n }\n\n protected _getInputPeer(peerInfo?: ITelegramStorage.PeerInfo): tl.TypeInputPeer | null {\n if (!peerInfo) return null\n\n switch (peerInfo.type) {\n case 'user':\n return {\n _: 'inputPeerUser',\n userId: peerInfo.id,\n accessHash: peerInfo.accessHash,\n }\n case 'chat':\n return {\n _: 'inputPeerChat',\n chatId: -peerInfo.id,\n }\n case 'channel':\n return {\n _: 'inputPeerChannel',\n channelId: toggleChannelIdMark(peerInfo.id),\n accessHash: peerInfo.accessHash,\n }\n }\n }\n\n private _findPeerByRef(peerId: number): tl.TypeInputPeer | null {\n const refs = this._state.refs.get(peerId)\n if (!refs || refs.size === 0) return null\n\n const [ref] = refs.values()\n const [chatId, msgId] = ref.split(':').map(Number)\n\n const chatPeer = this._getInputPeer(this._state.entities.get(chatId))\n if (!chatPeer) return null\n\n if (peerId > 0) {\n // user\n return {\n _: 'inputPeerUserFromMessage',\n msgId,\n userId: peerId,\n peer: chatPeer,\n }\n }\n\n // channel\n return {\n _: 'inputPeerChannelFromMessage',\n msgId,\n channelId: toggleChannelIdMark(peerId),\n peer: chatPeer,\n }\n }\n\n getPeerById(peerId: number): tl.TypeInputPeer | null {\n if (this._cachedInputPeers.has(peerId)) {\n return this._cachedInputPeers.get(peerId)!\n }\n\n let peer = this._getInputPeer(this._state.entities.get(peerId))\n if (!peer) peer = this._findPeerByRef(peerId)\n if (peer) this._cachedInputPeers.set(peerId, peer)\n\n return peer\n }\n\n getPeerByPhone(phone: string): tl.TypeInputPeer | null {\n const peerId = this._state.phoneIndex.get(phone)\n if (!peerId) return null\n\n return this._getInputPeer(this._state.entities.get(peerId))\n }\n\n getPeerByUsername(username: string): tl.TypeInputPeer | null {\n const id = this._state.usernameIndex.get(username.toLowerCase())\n if (!id) return null\n const peer = this._state.entities.get(id)\n if (!peer) return null\n\n if (Date.now() - peer.updated > USERNAME_TTL) return null\n\n return this._getInputPeer(peer)\n }\n\n saveReferenceMessage(peerId: number, chatId: number, messageId: number): void {\n if (!this._state.refs.has(peerId)) {\n this._state.refs.set(peerId, new Set())\n }\n\n this._state.refs.get(peerId)!.add(`${chatId}:${messageId}`)\n }\n\n deleteReferenceMessages(chatId: number, messageIds: number[]): void {\n // not the most efficient way, but it's fine\n for (const refs of this._state.refs.values()) {\n for (const msg of messageIds) {\n refs.delete(`${chatId}:${msg}`)\n }\n }\n }\n\n getSelf(): ITelegramStorage.SelfInfo | null {\n return this._state.self\n }\n\n setSelf(self: ITelegramStorage.SelfInfo | null): void {\n this._state.self = self\n }\n\n setManyChannelPts(values: Map<number, number>): void {\n for (const [id, pts] of values) {\n this._state.pts.set(id, pts)\n }\n }\n\n getChannelPts(entityId: number): number | null {\n return this._state.pts.get(entityId) ?? null\n }\n\n getUpdatesState(): [number, number, number, number] | null {\n return this._state.gpts ?? null\n }\n\n setUpdatesPts(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[0] = val\n }\n\n setUpdatesQts(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[1] = val\n }\n\n setUpdatesDate(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[2] = val\n }\n\n setUpdatesSeq(val: number): void {\n if (!this._state.gpts) this._state.gpts = [0, 0, 0, 0]\n this._state.gpts[3] = val\n }\n\n getFullPeerById(id: number): tl.TypeUser | tl.TypeChat | null {\n return this._cachedFull.get(id) ?? null\n }\n\n // IStateStorage implementation\n\n getState(key: string): unknown {\n const val = this._state.fsm.get(key)\n if (!val) return null\n\n if (val.e && val.e < Date.now()) {\n // expired\n this._state.fsm.delete(key)\n\n return null\n }\n\n return val.v\n }\n\n setState(key: string, state: unknown, ttl?: number): void {\n this._state.fsm.set(key, {\n v: state,\n e: ttl ? Date.now() + ttl * 1000 : undefined,\n })\n }\n\n deleteState(key: string): void {\n this._state.fsm.delete(key)\n }\n\n getCurrentScene(key: string): string | null {\n return this.getState(`$current_scene_${key}`) as string | null\n }\n\n setCurrentScene(key: string, scene: string, ttl?: number): void {\n return this.setState(`$current_scene_${key}`, scene, ttl)\n }\n\n deleteCurrentScene(key: string): void {\n this._state.fsm.delete(`$current_scene_${key}`)\n }\n\n getRateLimit(key: string, limit: number, window: number): [number, number] {\n // leaky bucket\n const now = Date.now()\n\n const item = this._state.rl.get(key)\n\n if (!item) {\n const state = {\n res: now + window * 1000,\n rem: limit,\n }\n\n this._state.rl.set(key, state)\n\n return [state.rem, state.res]\n }\n\n if (item.res < now) {\n // expired\n\n const state = {\n res: now + window * 1000,\n rem: limit,\n }\n\n this._state.rl.set(key, state)\n\n return [state.rem, state.res]\n }\n\n item.rem = item.rem > 0 ? item.rem - 1 : 0\n\n return [item.rem, item.res]\n }\n\n resetRateLimit(key: string): void {\n this._state.rl.delete(key)\n }\n}\n"]}
@@ -12,7 +12,7 @@ const memory_js_1 = require("./memory.js");
12
12
  constructor() {
13
13
  super();
14
14
  this._setStateFrom({
15
- $version: 2,
15
+ $version: 3,
16
16
  defaultDcs: null,
17
17
  authKeys: new Map(),
18
18
  authKeysTemp: new Map(),
@@ -26,6 +26,7 @@ const memory_js_1 = require("./memory.js");
26
26
  rl: new Map(),
27
27
  refs: new Map(),
28
28
  self: null,
29
+ futureSalts: new Map(),
29
30
  });
30
31
  }
31
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory.test.js","sourceRoot":"","sources":["../../../src/storage/memory.test.ts"],"names":[],"mappings":";;AAAA,mCAA6C;AAE7C,uCAA4D;AAE5D,2CAA2C;AAE3C,IAAA,iBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,IAAA,kBAAW,EAAC,IAAI,yBAAa,EAAE,CAAC,CAAA;IAChC,IAAA,uBAAgB,EAAC,IAAI,yBAAa,EAAE,CAAC,CAAA;IAErC,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;QACvB,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAC9C,MAAM,qBAAsB,SAAQ,yBAAa;gBAC7C;oBACI,KAAK,EAAE,CAAA;oBACP,IAAI,CAAC,aAAa,CAAC;wBACf,QAAQ,EAAE,CAAC;wBACX,UAAU,EAAE,IAAI;wBAChB,QAAQ,EAAE,IAAI,GAAG,EAAE;wBACnB,YAAY,EAAE,IAAI,GAAG,EAAE;wBACvB,kBAAkB,EAAE,IAAI,GAAG,EAAE;wBAC7B,QAAQ,EAAE,IAAI,GAAG,EAAE;wBACnB,UAAU,EAAE,IAAI,GAAG,EAAE;wBACrB,aAAa,EAAE,IAAI,GAAG,EAAE;wBACxB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;wBAClB,GAAG,EAAE,IAAI,GAAG,EAAE;wBACd,GAAG,EAAE,IAAI,GAAG,EAAE;wBACd,EAAE,EAAE,IAAI,GAAG,EAAE;wBACb,IAAI,EAAE,IAAI,GAAG,EAAE;wBACf,IAAI,EAAE,IAAI;qBACb,CAAC,CAAA;gBACN,CAAC;aACJ;YAED,MAAM,CAAC,GAAG,IAAI,qBAAqB,EAAE,CAAA;YAErC,IAAA,eAAM,EAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;QAEF,IAAA,WAAE,EAAC,0CAA0C,EAAE,GAAG,EAAE;YAChD,MAAM,qBAAsB,SAAQ,yBAAa;gBAC7C;oBACI,KAAK,EAAE,CAAA;oBACP,2BAA2B;oBAC3B,IAAI,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAS,CAAC,CAAA;gBAC9C,CAAC;aACJ;YAED,MAAM,CAAC,GAAG,IAAI,qBAAqB,EAAE,CAAA;YAErC,IAAA,eAAM,EAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA","sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { testStateStorage, testStorage } from '@mtcute/test'\n\nimport { MemoryStorage } from './memory.js'\n\ndescribe('MemoryStorage', () => {\n testStorage(new MemoryStorage())\n testStateStorage(new MemoryStorage())\n\n describe('extending', () => {\n it('should allow populating from an object', () => {\n class ExtendedMemoryStorage extends MemoryStorage {\n constructor() {\n super()\n this._setStateFrom({\n $version: 2,\n defaultDcs: null,\n authKeys: new Map(),\n authKeysTemp: new Map(),\n authKeysTempExpiry: new Map(),\n entities: new Map(),\n phoneIndex: new Map(),\n usernameIndex: new Map(),\n gpts: [1, 2, 3, 4],\n pts: new Map(),\n fsm: new Map(),\n rl: new Map(),\n refs: new Map(),\n self: null,\n })\n }\n }\n\n const s = new ExtendedMemoryStorage()\n\n expect(s.getUpdatesState()).toEqual([1, 2, 3, 4])\n })\n\n it('should silently fail if version is wrong', () => {\n class ExtendedMemoryStorage extends MemoryStorage {\n constructor() {\n super()\n // eslint-disable-next-line\n this._setStateFrom({ $version: 0 } as any)\n }\n }\n\n const s = new ExtendedMemoryStorage()\n\n expect(s.getUpdatesState()).toEqual(null)\n })\n })\n})\n"]}
1
+ {"version":3,"file":"memory.test.js","sourceRoot":"","sources":["../../../src/storage/memory.test.ts"],"names":[],"mappings":";;AAAA,mCAA6C;AAE7C,uCAA4D;AAE5D,2CAA2C;AAE3C,IAAA,iBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,IAAA,kBAAW,EAAC,IAAI,yBAAa,EAAE,CAAC,CAAA;IAChC,IAAA,uBAAgB,EAAC,IAAI,yBAAa,EAAE,CAAC,CAAA;IAErC,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;QACvB,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAC9C,MAAM,qBAAsB,SAAQ,yBAAa;gBAC7C;oBACI,KAAK,EAAE,CAAA;oBACP,IAAI,CAAC,aAAa,CAAC;wBACf,QAAQ,EAAE,CAAC;wBACX,UAAU,EAAE,IAAI;wBAChB,QAAQ,EAAE,IAAI,GAAG,EAAE;wBACnB,YAAY,EAAE,IAAI,GAAG,EAAE;wBACvB,kBAAkB,EAAE,IAAI,GAAG,EAAE;wBAC7B,QAAQ,EAAE,IAAI,GAAG,EAAE;wBACnB,UAAU,EAAE,IAAI,GAAG,EAAE;wBACrB,aAAa,EAAE,IAAI,GAAG,EAAE;wBACxB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;wBAClB,GAAG,EAAE,IAAI,GAAG,EAAE;wBACd,GAAG,EAAE,IAAI,GAAG,EAAE;wBACd,EAAE,EAAE,IAAI,GAAG,EAAE;wBACb,IAAI,EAAE,IAAI,GAAG,EAAE;wBACf,IAAI,EAAE,IAAI;wBACV,WAAW,EAAE,IAAI,GAAG,EAAE;qBACzB,CAAC,CAAA;gBACN,CAAC;aACJ;YAED,MAAM,CAAC,GAAG,IAAI,qBAAqB,EAAE,CAAA;YAErC,IAAA,eAAM,EAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;QAEF,IAAA,WAAE,EAAC,0CAA0C,EAAE,GAAG,EAAE;YAChD,MAAM,qBAAsB,SAAQ,yBAAa;gBAC7C;oBACI,KAAK,EAAE,CAAA;oBACP,2BAA2B;oBAC3B,IAAI,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAS,CAAC,CAAA;gBAC9C,CAAC;aACJ;YAED,MAAM,CAAC,GAAG,IAAI,qBAAqB,EAAE,CAAA;YAErC,IAAA,eAAM,EAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA","sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { testStateStorage, testStorage } from '@mtcute/test'\n\nimport { MemoryStorage } from './memory.js'\n\ndescribe('MemoryStorage', () => {\n testStorage(new MemoryStorage())\n testStateStorage(new MemoryStorage())\n\n describe('extending', () => {\n it('should allow populating from an object', () => {\n class ExtendedMemoryStorage extends MemoryStorage {\n constructor() {\n super()\n this._setStateFrom({\n $version: 3,\n defaultDcs: null,\n authKeys: new Map(),\n authKeysTemp: new Map(),\n authKeysTempExpiry: new Map(),\n entities: new Map(),\n phoneIndex: new Map(),\n usernameIndex: new Map(),\n gpts: [1, 2, 3, 4],\n pts: new Map(),\n fsm: new Map(),\n rl: new Map(),\n refs: new Map(),\n self: null,\n futureSalts: new Map(),\n })\n }\n }\n\n const s = new ExtendedMemoryStorage()\n\n expect(s.getUpdatesState()).toEqual([1, 2, 3, 4])\n })\n\n it('should silently fail if version is wrong', () => {\n class ExtendedMemoryStorage extends MemoryStorage {\n constructor() {\n super()\n // eslint-disable-next-line\n this._setStateFrom({ $version: 0 } as any)\n }\n }\n\n const s = new ExtendedMemoryStorage()\n\n expect(s.getUpdatesState()).toEqual(null)\n })\n })\n})\n"]}
@@ -62,10 +62,11 @@ class Logger {
62
62
  fmt.includes('%b') ||
63
63
  fmt.includes('%j') ||
64
64
  fmt.includes('%J') ||
65
- fmt.includes('%l')) {
65
+ fmt.includes('%l') ||
66
+ fmt.includes('%L')) {
66
67
  let idx = 0;
67
68
  fmt = fmt.replace(FORMATTER_RE, (m) => {
68
- if (m === '%h' || m === '%b' || m === '%j' || m === '%J' || m === '%l') {
69
+ if (m === '%h' || m === '%b' || m === '%j' || m === '%J' || m === '%l' || m === '%L') {
69
70
  let val = args[idx];
70
71
  args.splice(idx, 1);
71
72
  if (m === '%h') {
@@ -97,6 +98,11 @@ class Logger {
97
98
  }
98
99
  if (m === '%l')
99
100
  return String(val);
101
+ if (m === '%L') {
102
+ if (!Array.isArray(val))
103
+ return 'n/a';
104
+ return `[${val.map(String).join(', ')}]`;
105
+ }
100
106
  }
101
107
  idx++;
102
108
  return m;