@mtcute/core 0.13.3 → 0.14.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 (113) hide show
  1. package/cjs/highlevel/base.d.ts +1 -0
  2. package/cjs/highlevel/base.js +3 -0
  3. package/cjs/highlevel/base.js.map +1 -1
  4. package/cjs/highlevel/client.d.ts +2 -4
  5. package/cjs/highlevel/client.js +3 -0
  6. package/cjs/highlevel/client.js.map +1 -1
  7. package/cjs/highlevel/client.types.d.ts +1 -0
  8. package/cjs/highlevel/client.types.js.map +1 -1
  9. package/cjs/highlevel/methods/_init.js +3 -0
  10. package/cjs/highlevel/methods/_init.js.map +1 -1
  11. package/cjs/highlevel/methods/chats/delete-history.d.ts +2 -4
  12. package/cjs/highlevel/methods/chats/delete-history.js.map +1 -1
  13. package/cjs/highlevel/methods/chats/kick-chat-member.js +1 -1
  14. package/cjs/highlevel/methods/chats/kick-chat-member.js.map +1 -1
  15. package/cjs/highlevel/methods/messages/find-in-update.js +4 -2
  16. package/cjs/highlevel/methods/messages/find-in-update.js.map +1 -1
  17. package/cjs/highlevel/types/stories/interactive/index.d.ts +3 -2
  18. package/cjs/highlevel/types/stories/interactive/index.js +5 -1
  19. package/cjs/highlevel/types/stories/interactive/index.js.map +1 -1
  20. package/cjs/highlevel/types/stories/interactive/input.d.ts +1 -0
  21. package/cjs/highlevel/types/stories/interactive/input.js +7 -0
  22. package/cjs/highlevel/types/stories/interactive/input.js.map +1 -1
  23. package/cjs/highlevel/types/stories/interactive/url.d.ts +11 -0
  24. package/cjs/highlevel/types/stories/interactive/url.js +20 -0
  25. package/cjs/highlevel/types/stories/interactive/url.js.map +1 -0
  26. package/cjs/highlevel/types/updates/callback-query.d.ts +16 -2
  27. package/cjs/highlevel/types/updates/callback-query.js +31 -1
  28. package/cjs/highlevel/types/updates/callback-query.js.map +1 -1
  29. package/cjs/highlevel/types/updates/index.d.ts +5 -2
  30. package/cjs/highlevel/types/updates/index.js +2 -1
  31. package/cjs/highlevel/types/updates/index.js.map +1 -1
  32. package/cjs/highlevel/types/updates/parse-update.js +2 -0
  33. package/cjs/highlevel/types/updates/parse-update.js.map +1 -1
  34. package/cjs/highlevel/worker/port.d.ts +2 -0
  35. package/cjs/highlevel/worker/port.js +5 -0
  36. package/cjs/highlevel/worker/port.js.map +1 -1
  37. package/cjs/highlevel/worker/protocol.d.ts +2 -0
  38. package/cjs/highlevel/worker/protocol.js.map +1 -1
  39. package/cjs/highlevel/worker/worker.js +1 -0
  40. package/cjs/highlevel/worker/worker.js.map +1 -1
  41. package/cjs/network/client.d.ts +2 -0
  42. package/cjs/network/client.js +8 -0
  43. package/cjs/network/client.js.map +1 -1
  44. package/cjs/network/mtproto-session.js +2 -0
  45. package/cjs/network/mtproto-session.js.map +1 -1
  46. package/cjs/network/network-manager.d.ts +9 -2
  47. package/cjs/network/network-manager.js +26 -13
  48. package/cjs/network/network-manager.js.map +1 -1
  49. package/cjs/network/session-connection.js +12 -3
  50. package/cjs/network/session-connection.js.map +1 -1
  51. package/cjs/storage/sqlite/repository/peers.d.ts +2 -0
  52. package/cjs/storage/sqlite/repository/peers.js +14 -0
  53. package/cjs/storage/sqlite/repository/peers.js.map +1 -1
  54. package/cjs/utils/misc-utils.d.ts +1 -0
  55. package/cjs/utils/misc-utils.js +17 -1
  56. package/cjs/utils/misc-utils.js.map +1 -1
  57. package/esm/highlevel/base.d.ts +1 -0
  58. package/esm/highlevel/base.js +3 -0
  59. package/esm/highlevel/base.js.map +1 -1
  60. package/esm/highlevel/client.d.ts +2 -4
  61. package/esm/highlevel/client.js +3 -0
  62. package/esm/highlevel/client.js.map +1 -1
  63. package/esm/highlevel/client.types.d.ts +1 -0
  64. package/esm/highlevel/client.types.js.map +1 -1
  65. package/esm/highlevel/methods/_init.js +3 -0
  66. package/esm/highlevel/methods/_init.js.map +1 -1
  67. package/esm/highlevel/methods/chats/delete-history.d.ts +2 -4
  68. package/esm/highlevel/methods/chats/delete-history.js.map +1 -1
  69. package/esm/highlevel/methods/chats/kick-chat-member.js +2 -2
  70. package/esm/highlevel/methods/chats/kick-chat-member.js.map +1 -1
  71. package/esm/highlevel/methods/messages/find-in-update.js +4 -2
  72. package/esm/highlevel/methods/messages/find-in-update.js.map +1 -1
  73. package/esm/highlevel/types/stories/interactive/index.d.ts +3 -2
  74. package/esm/highlevel/types/stories/interactive/index.js +4 -1
  75. package/esm/highlevel/types/stories/interactive/index.js.map +1 -1
  76. package/esm/highlevel/types/stories/interactive/input.d.ts +1 -0
  77. package/esm/highlevel/types/stories/interactive/input.js +7 -0
  78. package/esm/highlevel/types/stories/interactive/input.js.map +1 -1
  79. package/esm/highlevel/types/stories/interactive/url.d.ts +11 -0
  80. package/esm/highlevel/types/stories/interactive/url.js +16 -0
  81. package/esm/highlevel/types/stories/interactive/url.js.map +1 -0
  82. package/esm/highlevel/types/updates/callback-query.d.ts +16 -2
  83. package/esm/highlevel/types/updates/callback-query.js +30 -0
  84. package/esm/highlevel/types/updates/callback-query.js.map +1 -1
  85. package/esm/highlevel/types/updates/index.d.ts +5 -2
  86. package/esm/highlevel/types/updates/index.js +2 -2
  87. package/esm/highlevel/types/updates/index.js.map +1 -1
  88. package/esm/highlevel/types/updates/parse-update.js +3 -1
  89. package/esm/highlevel/types/updates/parse-update.js.map +1 -1
  90. package/esm/highlevel/worker/port.d.ts +2 -0
  91. package/esm/highlevel/worker/port.js +5 -0
  92. package/esm/highlevel/worker/port.js.map +1 -1
  93. package/esm/highlevel/worker/protocol.d.ts +2 -0
  94. package/esm/highlevel/worker/protocol.js.map +1 -1
  95. package/esm/highlevel/worker/worker.js +1 -0
  96. package/esm/highlevel/worker/worker.js.map +1 -1
  97. package/esm/network/client.d.ts +2 -0
  98. package/esm/network/client.js +8 -0
  99. package/esm/network/client.js.map +1 -1
  100. package/esm/network/mtproto-session.js +2 -0
  101. package/esm/network/mtproto-session.js.map +1 -1
  102. package/esm/network/network-manager.d.ts +9 -2
  103. package/esm/network/network-manager.js +27 -14
  104. package/esm/network/network-manager.js.map +1 -1
  105. package/esm/network/session-connection.js +12 -3
  106. package/esm/network/session-connection.js.map +1 -1
  107. package/esm/storage/sqlite/repository/peers.d.ts +2 -0
  108. package/esm/storage/sqlite/repository/peers.js +14 -0
  109. package/esm/storage/sqlite/repository/peers.js.map +1 -1
  110. package/esm/utils/misc-utils.d.ts +1 -0
  111. package/esm/utils/misc-utils.js +15 -0
  112. package/esm/utils/misc-utils.js.map +1 -1
  113. package/package.json +4 -4
@@ -29,6 +29,8 @@ export class TelegramWorkerPort {
29
29
  computeNewPasswordHash;
30
30
  startUpdatesLoop;
31
31
  stopUpdatesLoop;
32
+ _abortController = new AbortController();
33
+ stopSignal = this._abortController.signal;
32
34
  constructor(options) {
33
35
  this.options = options;
34
36
  this.log = new LogManager('worker');
@@ -98,6 +100,9 @@ export class TelegramWorkerPort {
98
100
  case 'error':
99
101
  this.emitError(message.error);
100
102
  break;
103
+ case 'stop':
104
+ this._abortController.abort();
105
+ break;
101
106
  }
102
107
  };
103
108
  _destroyed = false;
@@ -1 +1 @@
1
- {"version":3,"file":"port.js","sourceRoot":"","sources":["../../../../src/highlevel/worker/port.ts"],"names":[],"mappings":"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","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { LogManager } from '../../utils/logger.js'\nimport { ConnectionState, ITelegramClient } from '../client.types.js'\nimport { PeersIndex } from '../types/peers/peers-index.js'\nimport { RawUpdateHandler } from '../updates/types.js'\nimport { AppConfigManagerProxy } from './app-config.js'\nimport { WorkerInvoker } from './invoker.js'\nimport { ClientMessageHandler, SendFn, SomeWorker, WorkerCustomMethods } from './protocol.js'\nimport { TelegramStorageProxy } from './storage.js'\n\nexport interface TelegramWorkerPortOptions {\n worker: SomeWorker\n}\n\nexport abstract class TelegramWorkerPort<Custom extends WorkerCustomMethods> implements ITelegramClient {\n readonly log\n\n private _connection\n private _invoker\n\n readonly storage\n readonly appConfig\n\n // bound methods\n readonly prepare\n private _connect\n readonly close\n readonly notifyLoggedIn\n readonly notifyLoggedOut\n readonly notifyChannelOpened\n readonly notifyChannelClosed\n readonly call\n readonly importSession\n readonly exportSession\n readonly handleClientUpdate\n readonly getApiCrenetials\n readonly getPoolSize\n readonly getPrimaryDcId\n readonly computeSrpParams\n readonly computeNewPasswordHash\n readonly startUpdatesLoop\n readonly stopUpdatesLoop\n\n constructor(readonly options: TelegramWorkerPortOptions) {\n this.log = new LogManager('worker')\n\n this._connection = this.connectToWorker(this.options.worker, this._onMessage)\n this._invoker = new WorkerInvoker(this._connection[0])\n\n this.storage = new TelegramStorageProxy(this._invoker)\n this.appConfig = new AppConfigManagerProxy(this._invoker)\n\n const bind = this._invoker.makeBinder<ITelegramClient>('client')\n\n this.prepare = bind('prepare')\n this._connect = bind('connect')\n\n this.close = bind('close')\n this.notifyLoggedIn = bind('notifyLoggedIn')\n this.notifyLoggedOut = bind('notifyLoggedOut')\n this.notifyChannelOpened = bind('notifyChannelOpened')\n this.notifyChannelClosed = bind('notifyChannelClosed')\n this.call = bind('call')\n this.importSession = bind('importSession')\n this.exportSession = bind('exportSession')\n this.handleClientUpdate = bind('handleClientUpdate', true)\n this.getApiCrenetials = bind('getApiCrenetials')\n this.getPoolSize = bind('getPoolSize')\n this.getPrimaryDcId = bind('getPrimaryDcId')\n this.computeSrpParams = bind('computeSrpParams')\n this.computeNewPasswordHash = bind('computeNewPasswordHash')\n this.startUpdatesLoop = bind('startUpdatesLoop')\n this.stopUpdatesLoop = bind('stopUpdatesLoop')\n }\n\n abstract connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void]\n\n private _serverUpdatesHandler: (updates: tl.TypeUpdates) => void = () => {}\n onServerUpdate(handler: (updates: tl.TypeUpdates) => void): void {\n this._serverUpdatesHandler = handler\n }\n\n private _errorHandler: (err: unknown) => void = () => {}\n onError(handler: (err: unknown) => void): void {\n this._errorHandler = handler\n }\n emitError(err: unknown): void {\n this._errorHandler(err)\n }\n\n private _updateHandler: RawUpdateHandler = () => {}\n onUpdate(handler: RawUpdateHandler): void {\n this._updateHandler = handler\n }\n\n private _connectionStateHandler: (state: ConnectionState) => void = () => {}\n onConnectionState(handler: (state: ConnectionState) => void): void {\n this._connectionStateHandler = handler\n }\n\n private _onMessage: ClientMessageHandler = (message) => {\n switch (message.type) {\n case 'log':\n this.log.handler(message.color, message.level, message.tag, message.fmt, message.args)\n break\n case 'server_update':\n this._serverUpdatesHandler(message.update)\n break\n case 'conn_state':\n this._connectionStateHandler(message.state)\n break\n case 'update': {\n const peers = new PeersIndex(message.users, message.chats)\n peers.hasMin = message.hasMin\n this._updateHandler(message.update, peers)\n break\n }\n case 'result':\n this._invoker.handleResult(message)\n break\n case 'error':\n this.emitError(message.error)\n break\n }\n }\n\n private _destroyed = false\n destroy(terminate = false): void {\n if (this._destroyed) return\n this._connection[1]()\n this._destroyed = true\n\n if (terminate && 'terminate' in this.options.worker) {\n Promise.resolve(this.options.worker.terminate()).catch(() => {})\n }\n }\n\n invokeCustom<T extends keyof Custom>(method: T, ...args: Parameters<Custom[T]>): Promise<ReturnType<Custom[T]>> {\n return this._invoker.invoke('custom', method as string, args) as Promise<ReturnType<Custom[T]>>\n }\n\n async connect(): Promise<void> {\n await this._connect()\n await this.storage.self.fetch() // force cache self locally\n }\n}\n"]}
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../../../../src/highlevel/worker/port.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAMnD,MAAM,OAAgB,kBAAkB;IAgCf;IA/BZ,GAAG,CAAA;IAEJ,WAAW,CAAA;IACX,QAAQ,CAAA;IAEP,OAAO,CAAA;IACP,SAAS,CAAA;IAElB,gBAAgB;IACP,OAAO,CAAA;IACR,QAAQ,CAAA;IACP,KAAK,CAAA;IACL,cAAc,CAAA;IACd,eAAe,CAAA;IACf,mBAAmB,CAAA;IACnB,mBAAmB,CAAA;IACnB,IAAI,CAAA;IACJ,aAAa,CAAA;IACb,aAAa,CAAA;IACb,kBAAkB,CAAA;IAClB,gBAAgB,CAAA;IAChB,WAAW,CAAA;IACX,cAAc,CAAA;IACd,gBAAgB,CAAA;IAChB,sBAAsB,CAAA;IACtB,gBAAgB,CAAA;IAChB,eAAe,CAAA;IAEhB,gBAAgB,GAAG,IAAI,eAAe,EAAE,CAAA;IACvC,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAA;IAElD,YAAqB,OAAkC;QAAlC,YAAO,GAAP,OAAO,CAA2B;QACnD,IAAI,CAAC,GAAG,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAA;QAEnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QAC7E,IAAI,CAAC,QAAQ,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;QAEtD,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACtD,IAAI,CAAC,SAAS,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAEzD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAkB,QAAQ,CAAC,CAAA;QAEhE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;QAC9B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;QAE/B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAC5C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAC9C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAA;QACtD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAA;QACtD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,CAAA;QAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,CAAA;QAC1C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAA;QAC1D,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAChD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,CAAA;QACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAC5C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAChD,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,wBAAwB,CAAC,CAAA;QAC5D,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAChD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAClD,CAAC;IAIO,qBAAqB,GAAsC,GAAG,EAAE,GAAE,CAAC,CAAA;IAC3E,cAAc,CAAC,OAA0C;QACrD,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAA;IACxC,CAAC;IAEO,aAAa,GAA2B,GAAG,EAAE,GAAE,CAAC,CAAA;IACxD,OAAO,CAAC,OAA+B;QACnC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAA;IAChC,CAAC;IACD,SAAS,CAAC,GAAY;QAClB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IAEO,cAAc,GAAqB,GAAG,EAAE,GAAE,CAAC,CAAA;IACnD,QAAQ,CAAC,OAAyB;QAC9B,IAAI,CAAC,cAAc,GAAG,OAAO,CAAA;IACjC,CAAC;IAEO,uBAAuB,GAAqC,GAAG,EAAE,GAAE,CAAC,CAAA;IAC5E,iBAAiB,CAAC,OAAyC;QACvD,IAAI,CAAC,uBAAuB,GAAG,OAAO,CAAA;IAC1C,CAAC;IAEO,UAAU,GAAyB,CAAC,OAAO,EAAE,EAAE;QACnD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,KAAK;gBACN,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;gBACtF,MAAK;YACT,KAAK,eAAe;gBAChB,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;gBAC1C,MAAK;YACT,KAAK,YAAY;gBACb,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;gBAC3C,MAAK;YACT,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACZ,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;gBAC1D,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;gBAC7B,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;gBAC1C,MAAK;YACT,CAAC;YACD,KAAK,QAAQ;gBACT,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;gBACnC,MAAK;YACT,KAAK,OAAO;gBACR,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;gBAC7B,MAAK;YACT,KAAK,MAAM;gBACP,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAA;gBAC7B,MAAK;QACb,CAAC;IACL,CAAC,CAAA;IAEO,UAAU,GAAG,KAAK,CAAA;IAC1B,OAAO,CAAC,SAAS,GAAG,KAAK;QACrB,IAAI,IAAI,CAAC,UAAU;YAAE,OAAM;QAC3B,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QAEtB,IAAI,SAAS,IAAI,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAClD,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpE,CAAC;IACL,CAAC;IAED,YAAY,CAAyB,MAAS,EAAE,GAAG,IAA2B;QAC1E,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAgB,EAAE,IAAI,CAAmC,CAAA;IACnG,CAAC;IAED,KAAK,CAAC,OAAO;QACT,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;QACrB,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA,CAAC,2BAA2B;IAC/D,CAAC;CACJ","sourcesContent":["import { tl } from '@mtcute/tl'\n\nimport { LogManager } from '../../utils/logger.js'\nimport { ConnectionState, ITelegramClient } from '../client.types.js'\nimport { PeersIndex } from '../types/peers/peers-index.js'\nimport { RawUpdateHandler } from '../updates/types.js'\nimport { AppConfigManagerProxy } from './app-config.js'\nimport { WorkerInvoker } from './invoker.js'\nimport { ClientMessageHandler, SendFn, SomeWorker, WorkerCustomMethods } from './protocol.js'\nimport { TelegramStorageProxy } from './storage.js'\n\nexport interface TelegramWorkerPortOptions {\n worker: SomeWorker\n}\n\nexport abstract class TelegramWorkerPort<Custom extends WorkerCustomMethods> implements ITelegramClient {\n readonly log\n\n private _connection\n private _invoker\n\n readonly storage\n readonly appConfig\n\n // bound methods\n readonly prepare\n private _connect\n readonly close\n readonly notifyLoggedIn\n readonly notifyLoggedOut\n readonly notifyChannelOpened\n readonly notifyChannelClosed\n readonly call\n readonly importSession\n readonly exportSession\n readonly handleClientUpdate\n readonly getApiCrenetials\n readonly getPoolSize\n readonly getPrimaryDcId\n readonly computeSrpParams\n readonly computeNewPasswordHash\n readonly startUpdatesLoop\n readonly stopUpdatesLoop\n\n private _abortController = new AbortController()\n readonly stopSignal = this._abortController.signal\n\n constructor(readonly options: TelegramWorkerPortOptions) {\n this.log = new LogManager('worker')\n\n this._connection = this.connectToWorker(this.options.worker, this._onMessage)\n this._invoker = new WorkerInvoker(this._connection[0])\n\n this.storage = new TelegramStorageProxy(this._invoker)\n this.appConfig = new AppConfigManagerProxy(this._invoker)\n\n const bind = this._invoker.makeBinder<ITelegramClient>('client')\n\n this.prepare = bind('prepare')\n this._connect = bind('connect')\n\n this.close = bind('close')\n this.notifyLoggedIn = bind('notifyLoggedIn')\n this.notifyLoggedOut = bind('notifyLoggedOut')\n this.notifyChannelOpened = bind('notifyChannelOpened')\n this.notifyChannelClosed = bind('notifyChannelClosed')\n this.call = bind('call')\n this.importSession = bind('importSession')\n this.exportSession = bind('exportSession')\n this.handleClientUpdate = bind('handleClientUpdate', true)\n this.getApiCrenetials = bind('getApiCrenetials')\n this.getPoolSize = bind('getPoolSize')\n this.getPrimaryDcId = bind('getPrimaryDcId')\n this.computeSrpParams = bind('computeSrpParams')\n this.computeNewPasswordHash = bind('computeNewPasswordHash')\n this.startUpdatesLoop = bind('startUpdatesLoop')\n this.stopUpdatesLoop = bind('stopUpdatesLoop')\n }\n\n abstract connectToWorker(worker: SomeWorker, handler: ClientMessageHandler): [SendFn, () => void]\n\n private _serverUpdatesHandler: (updates: tl.TypeUpdates) => void = () => {}\n onServerUpdate(handler: (updates: tl.TypeUpdates) => void): void {\n this._serverUpdatesHandler = handler\n }\n\n private _errorHandler: (err: unknown) => void = () => {}\n onError(handler: (err: unknown) => void): void {\n this._errorHandler = handler\n }\n emitError(err: unknown): void {\n this._errorHandler(err)\n }\n\n private _updateHandler: RawUpdateHandler = () => {}\n onUpdate(handler: RawUpdateHandler): void {\n this._updateHandler = handler\n }\n\n private _connectionStateHandler: (state: ConnectionState) => void = () => {}\n onConnectionState(handler: (state: ConnectionState) => void): void {\n this._connectionStateHandler = handler\n }\n\n private _onMessage: ClientMessageHandler = (message) => {\n switch (message.type) {\n case 'log':\n this.log.handler(message.color, message.level, message.tag, message.fmt, message.args)\n break\n case 'server_update':\n this._serverUpdatesHandler(message.update)\n break\n case 'conn_state':\n this._connectionStateHandler(message.state)\n break\n case 'update': {\n const peers = new PeersIndex(message.users, message.chats)\n peers.hasMin = message.hasMin\n this._updateHandler(message.update, peers)\n break\n }\n case 'result':\n this._invoker.handleResult(message)\n break\n case 'error':\n this.emitError(message.error)\n break\n case 'stop':\n this._abortController.abort()\n break\n }\n }\n\n private _destroyed = false\n destroy(terminate = false): void {\n if (this._destroyed) return\n this._connection[1]()\n this._destroyed = true\n\n if (terminate && 'terminate' in this.options.worker) {\n Promise.resolve(this.options.worker.terminate()).catch(() => {})\n }\n }\n\n invokeCustom<T extends keyof Custom>(method: T, ...args: Parameters<Custom[T]>): Promise<ReturnType<Custom[T]>> {\n return this._invoker.invoke('custom', method as string, args) as Promise<ReturnType<Custom[T]>>\n }\n\n async connect(): Promise<void> {\n await this._connect()\n await this.storage.self.fetch() // force cache self locally\n }\n}\n"]}
@@ -22,6 +22,8 @@ export type WorkerOutboundMessage = {
22
22
  } | {
23
23
  type: 'error';
24
24
  error: unknown;
25
+ } | {
26
+ type: 'stop';
25
27
  } | {
26
28
  type: 'conn_state';
27
29
  state: ConnectionState;
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../src/highlevel/worker/protocol.ts"],"names":[],"mappings":"","sourcesContent":["import type { Worker as NodeWorker } from 'node:worker_threads'\n\nimport { tl } from '@mtcute/tl'\n\nimport { ConnectionState } from '../client.types.js'\nimport { SerializedError } from './errors.js'\n\nexport type WorkerInboundMessage = {\n type: 'invoke'\n id: number\n target: 'custom' | 'client' | 'storage' | 'storage-self' | 'storage-peers' | 'app-config'\n method: string\n args: unknown[]\n void: boolean\n}\n\nexport type WorkerOutboundMessage =\n | { type: 'server_update'; update: tl.TypeUpdates }\n | {\n type: 'update'\n update: tl.TypeUpdate\n users: Map<number, tl.TypeUser>\n chats: Map<number, tl.TypeChat>\n hasMin: boolean\n }\n | { type: 'error'; error: unknown }\n | { type: 'conn_state'; state: ConnectionState }\n | {\n type: 'log'\n color: number\n level: number\n tag: string\n fmt: string\n args: unknown[]\n }\n | {\n type: 'result'\n id: number\n result?: unknown\n error?: SerializedError\n }\n\nexport type SomeWorker = NodeWorker | Worker | SharedWorker\n\nexport type SendFn = (message: WorkerInboundMessage) => void\nexport type ClientMessageHandler = (message: WorkerOutboundMessage) => void\n\nexport type RespondFn = (message: WorkerOutboundMessage) => void\nexport type WorkerMessageHandler = (message: WorkerInboundMessage, respond: RespondFn) => void\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type WorkerCustomMethods = Record<string, (...args: any[]) => Promise<any>>\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../src/highlevel/worker/protocol.ts"],"names":[],"mappings":"","sourcesContent":["import type { Worker as NodeWorker } from 'node:worker_threads'\n\nimport { tl } from '@mtcute/tl'\n\nimport { ConnectionState } from '../client.types.js'\nimport { SerializedError } from './errors.js'\n\nexport type WorkerInboundMessage = {\n type: 'invoke'\n id: number\n target: 'custom' | 'client' | 'storage' | 'storage-self' | 'storage-peers' | 'app-config'\n method: string\n args: unknown[]\n void: boolean\n}\n\nexport type WorkerOutboundMessage =\n | { type: 'server_update'; update: tl.TypeUpdates }\n | {\n type: 'update'\n update: tl.TypeUpdate\n users: Map<number, tl.TypeUser>\n chats: Map<number, tl.TypeChat>\n hasMin: boolean\n }\n | { type: 'error'; error: unknown }\n | { type: 'stop' }\n | { type: 'conn_state'; state: ConnectionState }\n | {\n type: 'log'\n color: number\n level: number\n tag: string\n fmt: string\n args: unknown[]\n }\n | {\n type: 'result'\n id: number\n result?: unknown\n error?: SerializedError\n }\n\nexport type SomeWorker = NodeWorker | Worker | SharedWorker\n\nexport type SendFn = (message: WorkerInboundMessage) => void\nexport type ClientMessageHandler = (message: WorkerOutboundMessage) => void\n\nexport type RespondFn = (message: WorkerOutboundMessage) => void\nexport type WorkerMessageHandler = (message: WorkerInboundMessage, respond: RespondFn) => void\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type WorkerCustomMethods = Record<string, (...args: any[]) => Promise<any>>\n"]}
@@ -30,6 +30,7 @@ export class TelegramWorker {
30
30
  type: 'conn_state',
31
31
  state,
32
32
  }));
33
+ client.stopSignal.addEventListener('abort', () => this.broadcast({ type: 'stop' }));
33
34
  if (client.updates) {
34
35
  client.onUpdate((update, peers) => this.broadcast({
35
36
  type: 'update',
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../../src/highlevel/worker/worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTelegramClient } from '../base.js'\nimport { serializeError } from './errors.js'\nimport { RespondFn, WorkerCustomMethods, WorkerInboundMessage, WorkerMessageHandler } from './protocol.js'\n\nexport interface TelegramWorkerOptions<T extends WorkerCustomMethods> {\n client: BaseTelegramClient\n customMethods?: T\n}\n\nexport abstract class TelegramWorker<T extends WorkerCustomMethods> {\n readonly client: BaseTelegramClient\n readonly broadcast: RespondFn\n\n abstract registerWorker(handler: WorkerMessageHandler): RespondFn\n\n constructor(readonly params: TelegramWorkerOptions<T>) {\n this.broadcast = this.registerWorker((message, respond) => {\n switch (message.type) {\n case 'invoke':\n this.onInvoke(message, respond)\n break\n }\n })\n\n const client = params.client\n this.client = client\n\n client.log.mgr.handler = (color, level, tag, fmt, args) =>\n this.broadcast({\n type: 'log',\n color,\n level,\n tag,\n fmt,\n args,\n })\n client.onError((err) =>\n this.broadcast({\n type: 'error',\n error: err,\n }),\n )\n client.onConnectionState((state) =>\n this.broadcast({\n type: 'conn_state',\n state,\n }),\n )\n\n if (client.updates) {\n client.onUpdate((update, peers) =>\n this.broadcast({\n type: 'update',\n update,\n users: peers.users,\n chats: peers.chats,\n hasMin: peers.hasMin,\n }),\n )\n } else {\n client.onServerUpdate((update) =>\n this.broadcast({\n type: 'server_update',\n update,\n }),\n )\n }\n }\n\n private onInvoke(msg: Extract<WorkerInboundMessage, { type: 'invoke' }>, respond: RespondFn) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let target: any\n\n switch (msg.target) {\n case 'custom':\n target = this.params.customMethods\n break\n case 'client':\n target = this.client\n break\n case 'storage':\n target = this.client.storage\n break\n case 'storage-self':\n target = this.client.storage.self\n break\n case 'storage-peers':\n target = this.client.storage.peers\n break\n case 'app-config':\n target = this.client.appConfig\n break\n\n default: {\n respond({\n type: 'result',\n id: msg.id,\n error: new Error(`Unknown target ${msg.target}`),\n })\n\n return\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const method = target[msg.method]\n\n if (!method) {\n respond({\n type: 'result',\n id: msg.id,\n error: new Error(`Method ${msg.method} not found on ${msg.target}`),\n })\n\n return\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n Promise.resolve(method.apply(target, msg.args))\n .then((res) => {\n if (msg.void) return\n\n respond({\n type: 'result',\n id: msg.id,\n result: res,\n })\n })\n .catch((err) => {\n respond({\n type: 'result',\n id: msg.id,\n error: serializeError(err),\n })\n })\n }\n}\n"]}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../../src/highlevel/worker/worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTelegramClient } from '../base.js'\nimport { serializeError } from './errors.js'\nimport { RespondFn, WorkerCustomMethods, WorkerInboundMessage, WorkerMessageHandler } from './protocol.js'\n\nexport interface TelegramWorkerOptions<T extends WorkerCustomMethods> {\n client: BaseTelegramClient\n customMethods?: T\n}\n\nexport abstract class TelegramWorker<T extends WorkerCustomMethods> {\n readonly client: BaseTelegramClient\n readonly broadcast: RespondFn\n\n abstract registerWorker(handler: WorkerMessageHandler): RespondFn\n\n constructor(readonly params: TelegramWorkerOptions<T>) {\n this.broadcast = this.registerWorker((message, respond) => {\n switch (message.type) {\n case 'invoke':\n this.onInvoke(message, respond)\n break\n }\n })\n\n const client = params.client\n this.client = client\n\n client.log.mgr.handler = (color, level, tag, fmt, args) =>\n this.broadcast({\n type: 'log',\n color,\n level,\n tag,\n fmt,\n args,\n })\n client.onError((err) =>\n this.broadcast({\n type: 'error',\n error: err,\n }),\n )\n client.onConnectionState((state) =>\n this.broadcast({\n type: 'conn_state',\n state,\n }),\n )\n client.stopSignal.addEventListener('abort', () => this.broadcast({ type: 'stop' }))\n\n if (client.updates) {\n client.onUpdate((update, peers) =>\n this.broadcast({\n type: 'update',\n update,\n users: peers.users,\n chats: peers.chats,\n hasMin: peers.hasMin,\n }),\n )\n } else {\n client.onServerUpdate((update) =>\n this.broadcast({\n type: 'server_update',\n update,\n }),\n )\n }\n }\n\n private onInvoke(msg: Extract<WorkerInboundMessage, { type: 'invoke' }>, respond: RespondFn) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let target: any\n\n switch (msg.target) {\n case 'custom':\n target = this.params.customMethods\n break\n case 'client':\n target = this.client\n break\n case 'storage':\n target = this.client.storage\n break\n case 'storage-self':\n target = this.client.storage.self\n break\n case 'storage-peers':\n target = this.client.storage.peers\n break\n case 'app-config':\n target = this.client.appConfig\n break\n\n default: {\n respond({\n type: 'result',\n id: msg.id,\n error: new Error(`Unknown target ${msg.target}`),\n })\n\n return\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const method = target[msg.method]\n\n if (!method) {\n respond({\n type: 'result',\n id: msg.id,\n error: new Error(`Method ${msg.method} not found on ${msg.target}`),\n })\n\n return\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n Promise.resolve(method.apply(target, msg.args))\n .then((res) => {\n if (msg.void) return\n\n respond({\n type: 'result',\n id: msg.id,\n result: res,\n })\n })\n .catch((err) => {\n respond({\n type: 'result',\n id: msg.id,\n error: serializeError(err),\n })\n })\n }\n}\n"]}
@@ -194,6 +194,8 @@ export declare class MtClient extends EventEmitter {
194
194
  private _emitError?;
195
195
  readonly log: Logger;
196
196
  readonly network: NetworkManager;
197
+ private _abortController;
198
+ readonly stopSignal: AbortSignal;
197
199
  constructor(params: MtClientOptions);
198
200
  emitError(err: unknown): void;
199
201
  private _prepare;
@@ -40,6 +40,8 @@ export class MtClient extends EventEmitter {
40
40
  _emitError;
41
41
  log;
42
42
  network;
43
+ _abortController;
44
+ stopSignal;
43
45
  constructor(params) {
44
46
  super();
45
47
  this.params = params;
@@ -63,6 +65,8 @@ export class MtClient extends EventEmitter {
63
65
  this._layer = params.overrideLayer ?? tl.LAYER;
64
66
  this._readerMap = params.readerMap ?? defaultReaderMap;
65
67
  this._writerMap = params.writerMap ?? defaultWriterMap;
68
+ this._abortController = new AbortController();
69
+ this.stopSignal = this._abortController.signal;
66
70
  this.storage = new StorageManager({
67
71
  provider: params.storage,
68
72
  log: this.log,
@@ -93,6 +97,7 @@ export class MtClient extends EventEmitter {
93
97
  onConnecting: () => this.emit('connecting'),
94
98
  onNetworkChanged: (connected) => this.emit('networkChanged', connected),
95
99
  onUpdate: (upd) => this.emit('update', upd),
100
+ stopSignal: this.stopSignal,
96
101
  ...params.network,
97
102
  }, this._config);
98
103
  }
@@ -140,12 +145,15 @@ export class MtClient extends EventEmitter {
140
145
  * Close all connections and finalize the client.
141
146
  */
142
147
  async close() {
148
+ this.log.debug('closing client');
143
149
  this._config.destroy();
144
150
  await this.network.destroy();
145
151
  await this.storage.save();
146
152
  await this.storage.destroy?.();
147
153
  this._prepare.reset();
148
154
  this._connect.reset();
155
+ this._abortController.abort();
156
+ this.log.debug('client closed successfully');
149
157
  }
150
158
  /**
151
159
  * Make an RPC call.
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/network/client.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport EventEmitter from 'events'\n\nimport { tl } from '@mtcute/tl'\nimport { __tlReaderMap as defaultReaderMap } from '@mtcute/tl/binary/reader.js'\nimport { __tlWriterMap as defaultWriterMap } from '@mtcute/tl/binary/writer.js'\nimport { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { IMtStorageProvider } from '../storage/provider.js'\nimport { StorageManager, StorageManagerExtraOptions } from '../storage/storage.js'\nimport { MustEqual } from '../types/index.js'\nimport {\n asyncResettable,\n DcOptions,\n defaultProductionDc,\n defaultProductionIpv6Dc,\n defaultTestDc,\n defaultTestIpv6Dc,\n ICryptoProvider,\n Logger,\n LogManager,\n} from '../utils/index.js'\nimport { ConfigManager } from './config-manager.js'\nimport { NetworkManager, NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js'\nimport { PersistentConnectionParams } from './persistent-connection.js'\nimport { ReconnectionStrategy } from './reconnection.js'\nimport { TransportFactory } from './transports/index.js'\n\n/** Options for {@link MtClient} */\nexport interface MtClientOptions {\n /**\n * API ID from my.telegram.org\n */\n apiId: number\n /**\n * API hash from my.telegram.org\n */\n apiHash: string\n\n /**\n * Storage to use for this client.\n */\n storage: IMtStorageProvider\n\n /** Additional options for the storage manager */\n storageOptions?: StorageManagerExtraOptions\n\n /**\n * Cryptography provider to allow delegating\n * crypto to native addon, worker, etc.\n */\n crypto: ICryptoProvider\n\n /**\n * Whether to use IPv6 datacenters\n * (IPv6 will be preferred when choosing a DC by id)\n * (default: false)\n */\n useIpv6?: boolean\n\n /**\n * Primary DC to use for initial connection.\n * This does not mean this will be the only DC used,\n * nor that this DC will actually be primary, this only\n * determines the first DC the library will try to connect to.\n * Can be used to connect to other networks (like test DCs).\n *\n * When session already contains primary DC, this parameter is ignored.\n *\n * @default Production DC 2.\n */\n defaultDcs?: DcOptions\n\n /**\n * Whether to connect to test servers.\n *\n * If passed, {@link defaultDc} defaults to Test DC 2.\n *\n * **Must** be passed if using test servers, even if\n * you passed custom {@link defaultDc}\n */\n testMode?: boolean\n\n /**\n * Additional options for initConnection call.\n * `apiId` and `query` are not available and will be ignored.\n * Omitted values will be filled with defaults\n */\n initConnectionOptions?: Partial<Omit<tl.RawInitConnectionRequest, 'apiId' | 'query'>>\n\n /**\n * Transport factory to use in the client.\n *\n * @default platform-specific transport: WebSocket on the web, TCP in node\n */\n transport: TransportFactory\n\n /**\n * Reconnection strategy.\n *\n * @default simple reconnection strategy: first 0ms, then up to 5s (increasing by 1s)\n */\n reconnectionStrategy?: ReconnectionStrategy<PersistentConnectionParams>\n\n /**\n * Maximum duration of a flood_wait that will be waited automatically.\n * Flood waits above this threshold will throw a FloodWaitError.\n * Set to 0 to disable. Can be overridden with `throwFlood` parameter in call() params\n *\n * @default 10000\n */\n floodSleepThreshold?: number\n\n /**\n * Maximum number of retries when calling RPC methods.\n * Call is retried when InternalError or FloodWaitError is encountered.\n * Can be set to Infinity.\n *\n * @default 5\n */\n maxRetryCount?: number\n\n /**\n * If true, all API calls will be wrapped with `tl.invokeWithoutUpdates`,\n * effectively disabling the server-sent events for the clients.\n * May be useful in some cases.\n *\n * @default false\n */\n disableUpdates?: boolean\n\n /**\n * mtcute can send all unknown RPC errors to [danog](https://github.com/danog)'s\n * [error reporting service](https://rpc.pwrtelegram.xyz/).\n *\n * This is fully anonymous (except maybe IP) and is only used to improve the library\n * and developer experience for everyone working with MTProto. This is fully opt-in,\n * and if you're too paranoid, you can disable it by manually passing `enableErrorReporting: false` to the client.\n *\n * @default false\n */\n enableErrorReporting?: boolean\n\n /**\n * If true, RPC errors will have a stack trace of the initial `.call()`\n * or `.sendForResult()` call position, which drastically improves\n * debugging experience.<br>\n * If false, they will have a stack trace of mtcute internals.\n *\n * Internally this creates a stack capture before every RPC call\n * and stores it until the result is received. This might\n * use a lot more memory than normal, thus can be disabled here.\n *\n * @default true\n */\n niceStacks?: boolean\n\n /**\n * Extra parameters for {@link NetworkManager}\n */\n network?: NetworkManagerExtraParams\n\n /**\n * Logger instance for the client.\n * If not passed, a new one will be created.\n */\n logger?: Logger\n\n /**\n * Set logging level for the client.\n * Shorthand for `client.log.level = level`.\n *\n * See static members of {@link LogManager} for possible values.\n */\n logLevel?: number\n\n /**\n * **EXPERT USE ONLY!**\n *\n * Override TL layer used for the connection.\n *\n * **Does not** change the schema used.\n */\n overrideLayer?: number\n\n /**\n * **EXPERT USE ONLY**\n *\n * Override reader map used for the connection.\n */\n readerMap?: TlReaderMap\n\n /**\n * **EXPERT USE ONLY**\n *\n * Override writer map used for the connection.\n */\n writerMap?: TlWriterMap\n}\n\n/**\n * Basic MTProto client implementation, only doing the bare minimum\n * to make RPC calls and receive low-level updates, as well as providing\n * some APIs to manage that.\n */\nexport class MtClient extends EventEmitter {\n /**\n * Crypto provider taken from {@link MtClientOptions.crypto}\n */\n readonly crypto: ICryptoProvider\n\n /** Storage manager */\n readonly storage: StorageManager\n\n /**\n * \"Test mode\" taken from {@link MtClientOptions.testMode}\n */\n protected readonly _testMode: boolean\n\n /**\n * Primary DCs taken from {@link MtClientOptions.defaultDcs},\n * loaded from session or changed by other means (like redirecting).\n */\n _defaultDcs: DcOptions\n\n private _niceStacks: boolean\n /** TL layer used by the client */\n readonly _layer: number\n /** TL readers map used by the client */\n readonly _readerMap: TlReaderMap\n /** TL writers map used by the client */\n readonly _writerMap: TlWriterMap\n\n readonly _config = new ConfigManager(() => this.call({ _: 'help.getConfig' }))\n\n private _emitError?: (err: unknown) => void\n\n readonly log: Logger\n readonly network: NetworkManager\n\n constructor(readonly params: MtClientOptions) {\n super()\n\n this.log = params.logger ?? new LogManager()\n\n if (params.logLevel !== undefined) {\n this.log.mgr.level = params.logLevel\n }\n\n this.crypto = params.crypto\n this._testMode = Boolean(params.testMode)\n\n let dc = params.defaultDcs\n\n if (!dc) {\n if (params.testMode) {\n dc = params.useIpv6 ? defaultTestIpv6Dc : defaultTestDc\n } else {\n dc = params.useIpv6 ? defaultProductionIpv6Dc : defaultProductionDc\n }\n }\n\n this._defaultDcs = dc\n this._niceStacks = params.niceStacks ?? true\n\n this._layer = params.overrideLayer ?? tl.LAYER\n this._readerMap = params.readerMap ?? defaultReaderMap\n this._writerMap = params.writerMap ?? defaultWriterMap\n\n this.storage = new StorageManager({\n provider: params.storage,\n log: this.log,\n readerMap: this._readerMap,\n writerMap: this._writerMap,\n ...params.storageOptions,\n })\n\n this.network = new NetworkManager(\n {\n apiId: params.apiId,\n crypto: this.crypto,\n disableUpdates: params.disableUpdates ?? false,\n initConnectionOptions: params.initConnectionOptions,\n layer: this._layer,\n log: this.log,\n readerMap: this._readerMap,\n writerMap: this._writerMap,\n reconnectionStrategy: params.reconnectionStrategy,\n storage: this.storage,\n testMode: Boolean(params.testMode),\n transport: params.transport,\n emitError: this.emitError.bind(this),\n floodSleepThreshold: params.floodSleepThreshold ?? 10000,\n maxRetryCount: params.maxRetryCount ?? 5,\n isPremium: false,\n useIpv6: Boolean(params.useIpv6),\n enableErrorReporting: params.enableErrorReporting ?? false,\n onUsable: () => this.emit('usable'),\n onConnecting: () => this.emit('connecting'),\n onNetworkChanged: (connected) => this.emit('networkChanged', connected),\n onUpdate: (upd) => this.emit('update', upd),\n ...params.network,\n },\n this._config,\n )\n }\n\n emitError(err: unknown): void {\n if (this._emitError) {\n this._emitError(err)\n } else if (this._connect.finished()) {\n this.log.error('unhandled error:', err)\n }\n }\n\n private _prepare = asyncResettable(async () => {\n await this.crypto.initialize?.()\n await this.storage.load()\n\n const primaryDc = await this.storage.dcs.fetch()\n if (primaryDc !== null) this._defaultDcs = primaryDc\n })\n\n /**\n * **ADVANCED**\n *\n * Do all the preparations, but don't connect just yet.\n * Useful when you want to do some preparations before\n * connecting, like setting up session.\n *\n * Call {@link connect} to actually connect.\n */\n prepare() {\n return this._prepare.run()\n }\n\n private _connect = asyncResettable(async () => {\n await this._prepare.run()\n await this.network.connect(this._defaultDcs)\n })\n\n /**\n * Initialize the connection to the primary DC.\n *\n * You shouldn't usually call this method directly as it is called\n * implicitly the first time you call {@link call}.\n */\n async connect(): Promise<void> {\n return this._connect.run()\n }\n\n /**\n * Close all connections and finalize the client.\n */\n async close(): Promise<void> {\n this._config.destroy()\n await this.network.destroy()\n\n await this.storage.save()\n await this.storage.destroy?.()\n\n this._prepare.reset()\n this._connect.reset()\n }\n\n /**\n * Make an RPC call.\n *\n * The connection must have been {@link connect}-ed\n * before calling this method.\n *\n * This method is still quite low-level and you shouldn't use this\n * when using high-level API provided by `@mtcute/client`.\n *\n * @param message RPC method to call\n * @param params Additional call parameters\n */\n async call<T extends tl.RpcMethod>(\n message: MustEqual<T, tl.RpcMethod>,\n params?: RpcCallOptions,\n ): Promise<tl.RpcCallReturn[T['_']]> {\n const stack = this._niceStacks ? new Error().stack : undefined\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.network.call(message, params, stack)\n }\n\n /**\n * Register an error handler for the client\n *\n * @param handler Error handler.\n */\n onError(handler: (err: unknown) => void): void {\n this._emitError = handler\n }\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/network/client.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport EventEmitter from 'events'\n\nimport { tl } from '@mtcute/tl'\nimport { __tlReaderMap as defaultReaderMap } from '@mtcute/tl/binary/reader.js'\nimport { __tlWriterMap as defaultWriterMap } from '@mtcute/tl/binary/writer.js'\nimport { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { IMtStorageProvider } from '../storage/provider.js'\nimport { StorageManager, StorageManagerExtraOptions } from '../storage/storage.js'\nimport { MustEqual } from '../types/index.js'\nimport {\n asyncResettable,\n DcOptions,\n defaultProductionDc,\n defaultProductionIpv6Dc,\n defaultTestDc,\n defaultTestIpv6Dc,\n ICryptoProvider,\n Logger,\n LogManager,\n} from '../utils/index.js'\nimport { ConfigManager } from './config-manager.js'\nimport { NetworkManager, NetworkManagerExtraParams, RpcCallOptions } from './network-manager.js'\nimport { PersistentConnectionParams } from './persistent-connection.js'\nimport { ReconnectionStrategy } from './reconnection.js'\nimport { TransportFactory } from './transports/index.js'\n\n/** Options for {@link MtClient} */\nexport interface MtClientOptions {\n /**\n * API ID from my.telegram.org\n */\n apiId: number\n /**\n * API hash from my.telegram.org\n */\n apiHash: string\n\n /**\n * Storage to use for this client.\n */\n storage: IMtStorageProvider\n\n /** Additional options for the storage manager */\n storageOptions?: StorageManagerExtraOptions\n\n /**\n * Cryptography provider to allow delegating\n * crypto to native addon, worker, etc.\n */\n crypto: ICryptoProvider\n\n /**\n * Whether to use IPv6 datacenters\n * (IPv6 will be preferred when choosing a DC by id)\n * (default: false)\n */\n useIpv6?: boolean\n\n /**\n * Primary DC to use for initial connection.\n * This does not mean this will be the only DC used,\n * nor that this DC will actually be primary, this only\n * determines the first DC the library will try to connect to.\n * Can be used to connect to other networks (like test DCs).\n *\n * When session already contains primary DC, this parameter is ignored.\n *\n * @default Production DC 2.\n */\n defaultDcs?: DcOptions\n\n /**\n * Whether to connect to test servers.\n *\n * If passed, {@link defaultDc} defaults to Test DC 2.\n *\n * **Must** be passed if using test servers, even if\n * you passed custom {@link defaultDc}\n */\n testMode?: boolean\n\n /**\n * Additional options for initConnection call.\n * `apiId` and `query` are not available and will be ignored.\n * Omitted values will be filled with defaults\n */\n initConnectionOptions?: Partial<Omit<tl.RawInitConnectionRequest, 'apiId' | 'query'>>\n\n /**\n * Transport factory to use in the client.\n *\n * @default platform-specific transport: WebSocket on the web, TCP in node\n */\n transport: TransportFactory\n\n /**\n * Reconnection strategy.\n *\n * @default simple reconnection strategy: first 0ms, then up to 5s (increasing by 1s)\n */\n reconnectionStrategy?: ReconnectionStrategy<PersistentConnectionParams>\n\n /**\n * Maximum duration of a flood_wait that will be waited automatically.\n * Flood waits above this threshold will throw a FloodWaitError.\n * Set to 0 to disable. Can be overridden with `throwFlood` parameter in call() params\n *\n * @default 10000\n */\n floodSleepThreshold?: number\n\n /**\n * Maximum number of retries when calling RPC methods.\n * Call is retried when InternalError or FloodWaitError is encountered.\n * Can be set to Infinity.\n *\n * @default 5\n */\n maxRetryCount?: number\n\n /**\n * If true, all API calls will be wrapped with `tl.invokeWithoutUpdates`,\n * effectively disabling the server-sent events for the clients.\n * May be useful in some cases.\n *\n * @default false\n */\n disableUpdates?: boolean\n\n /**\n * mtcute can send all unknown RPC errors to [danog](https://github.com/danog)'s\n * [error reporting service](https://rpc.pwrtelegram.xyz/).\n *\n * This is fully anonymous (except maybe IP) and is only used to improve the library\n * and developer experience for everyone working with MTProto. This is fully opt-in,\n * and if you're too paranoid, you can disable it by manually passing `enableErrorReporting: false` to the client.\n *\n * @default false\n */\n enableErrorReporting?: boolean\n\n /**\n * If true, RPC errors will have a stack trace of the initial `.call()`\n * or `.sendForResult()` call position, which drastically improves\n * debugging experience.<br>\n * If false, they will have a stack trace of mtcute internals.\n *\n * Internally this creates a stack capture before every RPC call\n * and stores it until the result is received. This might\n * use a lot more memory than normal, thus can be disabled here.\n *\n * @default true\n */\n niceStacks?: boolean\n\n /**\n * Extra parameters for {@link NetworkManager}\n */\n network?: NetworkManagerExtraParams\n\n /**\n * Logger instance for the client.\n * If not passed, a new one will be created.\n */\n logger?: Logger\n\n /**\n * Set logging level for the client.\n * Shorthand for `client.log.level = level`.\n *\n * See static members of {@link LogManager} for possible values.\n */\n logLevel?: number\n\n /**\n * **EXPERT USE ONLY!**\n *\n * Override TL layer used for the connection.\n *\n * **Does not** change the schema used.\n */\n overrideLayer?: number\n\n /**\n * **EXPERT USE ONLY**\n *\n * Override reader map used for the connection.\n */\n readerMap?: TlReaderMap\n\n /**\n * **EXPERT USE ONLY**\n *\n * Override writer map used for the connection.\n */\n writerMap?: TlWriterMap\n}\n\n/**\n * Basic MTProto client implementation, only doing the bare minimum\n * to make RPC calls and receive low-level updates, as well as providing\n * some APIs to manage that.\n */\nexport class MtClient extends EventEmitter {\n /**\n * Crypto provider taken from {@link MtClientOptions.crypto}\n */\n readonly crypto: ICryptoProvider\n\n /** Storage manager */\n readonly storage: StorageManager\n\n /**\n * \"Test mode\" taken from {@link MtClientOptions.testMode}\n */\n protected readonly _testMode: boolean\n\n /**\n * Primary DCs taken from {@link MtClientOptions.defaultDcs},\n * loaded from session or changed by other means (like redirecting).\n */\n _defaultDcs: DcOptions\n\n private _niceStacks: boolean\n /** TL layer used by the client */\n readonly _layer: number\n /** TL readers map used by the client */\n readonly _readerMap: TlReaderMap\n /** TL writers map used by the client */\n readonly _writerMap: TlWriterMap\n\n readonly _config = new ConfigManager(() => this.call({ _: 'help.getConfig' }))\n\n private _emitError?: (err: unknown) => void\n\n readonly log: Logger\n readonly network: NetworkManager\n\n private _abortController: AbortController\n readonly stopSignal: AbortSignal\n\n constructor(readonly params: MtClientOptions) {\n super()\n\n this.log = params.logger ?? new LogManager()\n\n if (params.logLevel !== undefined) {\n this.log.mgr.level = params.logLevel\n }\n\n this.crypto = params.crypto\n this._testMode = Boolean(params.testMode)\n\n let dc = params.defaultDcs\n\n if (!dc) {\n if (params.testMode) {\n dc = params.useIpv6 ? defaultTestIpv6Dc : defaultTestDc\n } else {\n dc = params.useIpv6 ? defaultProductionIpv6Dc : defaultProductionDc\n }\n }\n\n this._defaultDcs = dc\n this._niceStacks = params.niceStacks ?? true\n\n this._layer = params.overrideLayer ?? tl.LAYER\n this._readerMap = params.readerMap ?? defaultReaderMap\n this._writerMap = params.writerMap ?? defaultWriterMap\n\n this._abortController = new AbortController()\n this.stopSignal = this._abortController.signal\n\n this.storage = new StorageManager({\n provider: params.storage,\n log: this.log,\n readerMap: this._readerMap,\n writerMap: this._writerMap,\n ...params.storageOptions,\n })\n\n this.network = new NetworkManager(\n {\n apiId: params.apiId,\n crypto: this.crypto,\n disableUpdates: params.disableUpdates ?? false,\n initConnectionOptions: params.initConnectionOptions,\n layer: this._layer,\n log: this.log,\n readerMap: this._readerMap,\n writerMap: this._writerMap,\n reconnectionStrategy: params.reconnectionStrategy,\n storage: this.storage,\n testMode: Boolean(params.testMode),\n transport: params.transport,\n emitError: this.emitError.bind(this),\n floodSleepThreshold: params.floodSleepThreshold ?? 10000,\n maxRetryCount: params.maxRetryCount ?? 5,\n isPremium: false,\n useIpv6: Boolean(params.useIpv6),\n enableErrorReporting: params.enableErrorReporting ?? false,\n onUsable: () => this.emit('usable'),\n onConnecting: () => this.emit('connecting'),\n onNetworkChanged: (connected) => this.emit('networkChanged', connected),\n onUpdate: (upd) => this.emit('update', upd),\n stopSignal: this.stopSignal,\n ...params.network,\n },\n this._config,\n )\n }\n\n emitError(err: unknown): void {\n if (this._emitError) {\n this._emitError(err)\n } else if (this._connect.finished()) {\n this.log.error('unhandled error:', err)\n }\n }\n\n private _prepare = asyncResettable(async () => {\n await this.crypto.initialize?.()\n await this.storage.load()\n\n const primaryDc = await this.storage.dcs.fetch()\n if (primaryDc !== null) this._defaultDcs = primaryDc\n })\n\n /**\n * **ADVANCED**\n *\n * Do all the preparations, but don't connect just yet.\n * Useful when you want to do some preparations before\n * connecting, like setting up session.\n *\n * Call {@link connect} to actually connect.\n */\n prepare() {\n return this._prepare.run()\n }\n\n private _connect = asyncResettable(async () => {\n await this._prepare.run()\n await this.network.connect(this._defaultDcs)\n })\n\n /**\n * Initialize the connection to the primary DC.\n *\n * You shouldn't usually call this method directly as it is called\n * implicitly the first time you call {@link call}.\n */\n async connect(): Promise<void> {\n return this._connect.run()\n }\n\n /**\n * Close all connections and finalize the client.\n */\n async close(): Promise<void> {\n this.log.debug('closing client')\n\n this._config.destroy()\n await this.network.destroy()\n\n await this.storage.save()\n await this.storage.destroy?.()\n\n this._prepare.reset()\n this._connect.reset()\n this._abortController.abort()\n\n this.log.debug('client closed successfully')\n }\n\n /**\n * Make an RPC call.\n *\n * The connection must have been {@link connect}-ed\n * before calling this method.\n *\n * This method is still quite low-level and you shouldn't use this\n * when using high-level API provided by `@mtcute/client`.\n *\n * @param message RPC method to call\n * @param params Additional call parameters\n */\n async call<T extends tl.RpcMethod>(\n message: MustEqual<T, tl.RpcMethod>,\n params?: RpcCallOptions,\n ): Promise<tl.RpcCallReturn[T['_']]> {\n const stack = this._niceStacks ? new Error().stack : undefined\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.network.call(message, params, stack)\n }\n\n /**\n * Register an error handler for the client\n *\n * @param handler Error handler.\n */\n onError(handler: (err: unknown) => void): void {\n this._emitError = handler\n }\n}\n"]}
@@ -101,6 +101,7 @@ export class MtprotoSession {
101
101
  if (!keepPending) {
102
102
  for (const info of this.pendingMessages.values()) {
103
103
  if (info._ === 'rpc') {
104
+ this.log.debug('rejecting pending rpc %s', info.rpc.method);
104
105
  info.rpc.promise.reject(new MtcuteError('Session is reset'));
105
106
  }
106
107
  }
@@ -112,6 +113,7 @@ export class MtprotoSession {
112
113
  while (this.queuedRpc.length) {
113
114
  const rpc = this.queuedRpc.popFront();
114
115
  if (rpc.sent === false) {
116
+ this.log.debug('rejecting pending rpc %s', rpc.method);
115
117
  rpc.promise.reject(new MtcuteError('Session is reset'));
116
118
  }
117
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mtproto-session.js","sourceRoot":"","sources":["../../../src/network/mtproto-session.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\n\nimport { mtp, tl } from '@mtcute/tl'\nimport { TlBinaryWriter, TlReaderMap, TlSerializationCounter, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { MtcuteError } from '../types/index.js'\nimport {\n compareLongs,\n ControllablePromise,\n Deque,\n getRandomInt,\n ICryptoProvider,\n Logger,\n LongMap,\n LruSet,\n randomLong,\n SortedArray,\n} from '../utils/index.js'\nimport { AuthKey } from './auth-key.js'\nimport { ServerSaltManager } from './server-salt.js'\n\nexport interface PendingRpc {\n method: string\n data: Uint8Array\n promise: ControllablePromise\n stack?: string\n gzipOverhead?: number\n\n chainId?: string | number\n invokeAfter?: Long\n\n sent?: boolean\n done?: boolean\n msgId?: Long\n seqNo?: number\n containerId?: Long\n acked?: boolean\n initConn?: boolean\n getState?: number\n cancelled?: boolean\n timeout?: NodeJS.Timeout\n}\n\nexport type PendingMessage =\n | {\n _: 'rpc'\n rpc: PendingRpc\n }\n | {\n _: 'container'\n msgIds: Long[]\n }\n | {\n _: 'state'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'resend'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'ping'\n pingId: Long\n containerId: Long\n }\n | {\n _: 'destroy_session'\n sessionId: Long\n containerId: Long\n }\n | {\n _: 'cancel'\n msgId: Long\n containerId: Long\n }\n | {\n _: 'future_salts'\n containerId: Long\n }\n | {\n _: 'bind'\n promise: ControllablePromise\n }\n\n/**\n * Class encapsulating a single MTProto session and storing\n * all the relevant state\n */\nexport class MtprotoSession {\n _sessionId = randomLong()\n\n _authKey: AuthKey\n _authKeyTemp: AuthKey\n _authKeyTempSecondary: AuthKey\n\n _timeOffset = 0\n _lastMessageId = Long.ZERO\n _seqNo = 0\n\n /// state ///\n // recent msg ids\n recentOutgoingMsgIds = new LruSet<Long>(1000, true)\n recentIncomingMsgIds = new LruSet<Long>(1000, true)\n\n // queues\n queuedRpc = new Deque<PendingRpc>()\n queuedAcks: Long[] = []\n queuedStateReq: Long[] = []\n queuedResendReq: Long[] = []\n queuedCancelReq: Long[] = []\n getStateSchedule = new SortedArray<PendingRpc>([], (a, b) => a.getState! - b.getState!)\n\n chains = new Map<string | number, Long>()\n chainsPendingFails = new Map<string | number, SortedArray<PendingRpc>>()\n\n // requests info\n pendingMessages = new LongMap<PendingMessage>()\n destroySessionIdToMsgId = new LongMap<Long>()\n\n lastPingRtt = NaN\n lastPingTime = 0\n lastPingMsgId = Long.ZERO\n lastSessionCreatedUid = Long.ZERO\n\n initConnectionCalled = false\n authorizationPending = false\n\n next429Timeout = 1000\n current429Timeout?: NodeJS.Timeout\n next429ResetTimeout?: NodeJS.Timeout\n\n constructor(\n readonly _crypto: ICryptoProvider,\n readonly log: Logger,\n readonly _readerMap: TlReaderMap,\n readonly _writerMap: TlWriterMap,\n readonly _salts: ServerSaltManager,\n ) {\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n this._authKey = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTemp = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTempSecondary = new AuthKey(_crypto, log, _readerMap)\n }\n\n get hasPendingMessages(): boolean {\n return Boolean(\n this.queuedRpc.length ||\n this.queuedAcks.length ||\n this.queuedStateReq.length ||\n this.queuedResendReq.length,\n )\n }\n\n /**\n * Reset session by resetting auth key(s) and session state\n */\n reset(withAuthKey = false): void {\n if (withAuthKey) {\n this.resetAuthKey()\n }\n\n clearTimeout(this.current429Timeout)\n this.resetState(withAuthKey)\n this.resetLastPing(true)\n }\n\n resetAuthKey(): void {\n this._authKey.reset()\n this._authKeyTemp.reset()\n this._authKeyTempSecondary.reset()\n }\n\n updateTimeOffset(offset: number) {\n this.log.debug('time offset updated: %d', offset)\n this._timeOffset = offset\n // lastMessageId was generated with (potentially) wrong time\n // reset it to avoid bigger issues - at worst, we'll get bad_msg_notification\n this._lastMessageId = Long.ZERO\n }\n\n /**\n * Reset session state and generate a new session ID.\n *\n * By default, also cancels any pending RPC requests.\n * If `keepPending` is set to `true`, pending requests will be kept\n */\n resetState(keepPending = false): void {\n this._lastMessageId = Long.ZERO\n this._seqNo = 0\n\n this._sessionId = randomLong()\n this.log.debug('session reset, new sid = %h', this._sessionId)\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n // reset session state\n\n if (!keepPending) {\n for (const info of this.pendingMessages.values()) {\n if (info._ === 'rpc') {\n info.rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n this.pendingMessages.clear()\n }\n\n this.recentOutgoingMsgIds.clear()\n this.recentIncomingMsgIds.clear()\n\n if (!keepPending) {\n while (this.queuedRpc.length) {\n const rpc = this.queuedRpc.popFront()!\n\n if (rpc.sent === false) {\n rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n }\n\n this.queuedAcks.length = 0\n this.queuedStateReq.length = 0\n this.queuedResendReq.length = 0\n this.queuedCancelReq.length = 0\n this.getStateSchedule.clear()\n this.chains.clear()\n this.chainsPendingFails.clear()\n }\n\n enqueueRpc(rpc: PendingRpc, force?: boolean): boolean {\n // already queued or cancelled\n if ((!force && !rpc.sent) || rpc.cancelled) return false\n\n rpc.sent = false\n rpc.containerId = undefined\n this.log.debug('enqueued %s for sending (msg_id = %s)', rpc.method, rpc.msgId || 'n/a')\n this.queuedRpc.pushBack(rpc)\n\n return true\n }\n\n getMessageId(): Long {\n const timeTicks = Date.now()\n const timeSec = Math.floor(timeTicks / 1000) - this._timeOffset\n const timeMSec = timeTicks % 1000\n const random = getRandomInt(0xffff)\n\n let messageId = new Long((timeMSec << 21) | (random << 3) | 4, timeSec)\n\n if (this._lastMessageId.ge(messageId)) {\n messageId = this._lastMessageId.add(4)\n }\n\n this._lastMessageId = messageId\n\n return messageId\n }\n\n getSeqNo(isContentRelated = true): number {\n let seqNo = this._seqNo\n\n if (isContentRelated) {\n seqNo += 1\n this._seqNo += 2\n }\n\n return seqNo\n }\n\n /** Encrypt a single MTProto message using session's keys */\n encryptMessage(message: Uint8Array): Uint8Array {\n const key = this._authKeyTemp.ready ? this._authKeyTemp : this._authKey\n\n return key.encryptMessage(message, this._salts.currentSalt, this._sessionId)\n }\n\n /** Decrypt a single MTProto message using session's keys */\n decryptMessage(data: Uint8Array, callback: Parameters<AuthKey['decryptMessage']>[2]): void {\n if (!this._authKey.ready) throw new MtcuteError('Keys are not set up!')\n\n const authKeyId = data.subarray(0, 8)\n\n let key: AuthKey\n\n if (this._authKey.match(authKeyId)) {\n key = this._authKey\n } else if (this._authKeyTemp.match(authKeyId)) {\n key = this._authKeyTemp\n } else if (this._authKeyTempSecondary.match(authKeyId)) {\n key = this._authKeyTempSecondary\n } else {\n this.log.warn(\n 'received message with unknown authKey = %h (expected %h or %h or %h)',\n authKeyId,\n this._authKey.id,\n this._authKeyTemp.id,\n this._authKeyTempSecondary.id,\n )\n\n return\n }\n\n return key.decryptMessage(data, this._sessionId, callback)\n }\n\n writeMessage(\n writer: TlBinaryWriter,\n content: tl.TlObject | mtp.TlObject | Uint8Array,\n isContentRelated = true,\n ): Long {\n const messageId = this.getMessageId()\n const seqNo = this.getSeqNo(isContentRelated)\n\n const length = ArrayBuffer.isView(content) ?\n content.length :\n TlSerializationCounter.countNeededBytes(writer.objectMap!, content)\n\n writer.long(messageId)\n writer.int(seqNo)\n writer.uint(length)\n if (ArrayBuffer.isView(content)) writer.raw(content)\n else writer.object(content as tl.TlObject)\n\n return messageId\n }\n\n onTransportFlood(callback: () => void) {\n if (this.current429Timeout) return // already waiting\n\n // all active queries must be resent after a timeout\n this.resetLastPing(true)\n\n const timeout = this.next429Timeout\n\n this.next429Timeout = Math.min(this.next429Timeout * 2, 32000)\n clearTimeout(this.current429Timeout)\n clearTimeout(this.next429ResetTimeout)\n\n this.current429Timeout = setTimeout(() => {\n this.current429Timeout = undefined\n callback()\n }, timeout)\n this.next429ResetTimeout = setTimeout(() => {\n this.next429ResetTimeout = undefined\n this.next429Timeout = 1000\n }, 60000)\n\n this.log.debug('transport flood, waiting for %d ms before proceeding', timeout)\n\n return Date.now() + timeout\n }\n\n resetLastPing(withTime = false): void {\n if (withTime) this.lastPingTime = 0\n\n if (!this.lastPingMsgId.isZero()) {\n this.pendingMessages.delete(this.lastPingMsgId)\n }\n\n this.lastPingMsgId = Long.ZERO\n }\n\n addToChain(chainId: string | number, msgId: Long): Long | undefined {\n const prevMsgId = this.chains.get(chainId)\n this.chains.set(chainId, msgId)\n\n this.log.debug('added message %l to chain %s (prev: %l)', msgId, chainId, prevMsgId)\n\n return prevMsgId\n }\n\n removeFromChain(chainId: string | number, msgId: Long): void {\n const lastMsgId = this.chains.get(chainId)\n\n if (!lastMsgId) {\n this.log.warn('tried to remove message %l from empty chain %s', msgId, chainId)\n\n return\n }\n\n if (lastMsgId.eq(msgId)) {\n // last message of the chain, remove it\n this.log.debug('chain %s: exhausted, last message %l', msgId, chainId)\n this.chains.delete(chainId)\n }\n\n // do nothing\n }\n\n getPendingChainedFails(chainId: string | number): SortedArray<PendingRpc> {\n let arr = this.chainsPendingFails.get(chainId)\n\n if (!arr) {\n arr = new SortedArray<PendingRpc>([], (a, b) => compareLongs(a.invokeAfter!, b.invokeAfter!))\n this.chainsPendingFails.set(chainId, arr)\n }\n\n return arr\n }\n}\n"]}
1
+ {"version":3,"file":"mtproto-session.js","sourceRoot":"","sources":["../../../src/network/mtproto-session.ts"],"names":[],"mappings":"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","sourcesContent":["import Long from 'long'\n\nimport { mtp, tl } from '@mtcute/tl'\nimport { TlBinaryWriter, TlReaderMap, TlSerializationCounter, TlWriterMap } from '@mtcute/tl-runtime'\n\nimport { MtcuteError } from '../types/index.js'\nimport {\n compareLongs,\n ControllablePromise,\n Deque,\n getRandomInt,\n ICryptoProvider,\n Logger,\n LongMap,\n LruSet,\n randomLong,\n SortedArray,\n} from '../utils/index.js'\nimport { AuthKey } from './auth-key.js'\nimport { ServerSaltManager } from './server-salt.js'\n\nexport interface PendingRpc {\n method: string\n data: Uint8Array\n promise: ControllablePromise\n stack?: string\n gzipOverhead?: number\n\n chainId?: string | number\n invokeAfter?: Long\n\n sent?: boolean\n done?: boolean\n msgId?: Long\n seqNo?: number\n containerId?: Long\n acked?: boolean\n initConn?: boolean\n getState?: number\n cancelled?: boolean\n timeout?: NodeJS.Timeout\n}\n\nexport type PendingMessage =\n | {\n _: 'rpc'\n rpc: PendingRpc\n }\n | {\n _: 'container'\n msgIds: Long[]\n }\n | {\n _: 'state'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'resend'\n msgIds: Long[]\n containerId: Long\n }\n | {\n _: 'ping'\n pingId: Long\n containerId: Long\n }\n | {\n _: 'destroy_session'\n sessionId: Long\n containerId: Long\n }\n | {\n _: 'cancel'\n msgId: Long\n containerId: Long\n }\n | {\n _: 'future_salts'\n containerId: Long\n }\n | {\n _: 'bind'\n promise: ControllablePromise\n }\n\n/**\n * Class encapsulating a single MTProto session and storing\n * all the relevant state\n */\nexport class MtprotoSession {\n _sessionId = randomLong()\n\n _authKey: AuthKey\n _authKeyTemp: AuthKey\n _authKeyTempSecondary: AuthKey\n\n _timeOffset = 0\n _lastMessageId = Long.ZERO\n _seqNo = 0\n\n /// state ///\n // recent msg ids\n recentOutgoingMsgIds = new LruSet<Long>(1000, true)\n recentIncomingMsgIds = new LruSet<Long>(1000, true)\n\n // queues\n queuedRpc = new Deque<PendingRpc>()\n queuedAcks: Long[] = []\n queuedStateReq: Long[] = []\n queuedResendReq: Long[] = []\n queuedCancelReq: Long[] = []\n getStateSchedule = new SortedArray<PendingRpc>([], (a, b) => a.getState! - b.getState!)\n\n chains = new Map<string | number, Long>()\n chainsPendingFails = new Map<string | number, SortedArray<PendingRpc>>()\n\n // requests info\n pendingMessages = new LongMap<PendingMessage>()\n destroySessionIdToMsgId = new LongMap<Long>()\n\n lastPingRtt = NaN\n lastPingTime = 0\n lastPingMsgId = Long.ZERO\n lastSessionCreatedUid = Long.ZERO\n\n initConnectionCalled = false\n authorizationPending = false\n\n next429Timeout = 1000\n current429Timeout?: NodeJS.Timeout\n next429ResetTimeout?: NodeJS.Timeout\n\n constructor(\n readonly _crypto: ICryptoProvider,\n readonly log: Logger,\n readonly _readerMap: TlReaderMap,\n readonly _writerMap: TlWriterMap,\n readonly _salts: ServerSaltManager,\n ) {\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n this._authKey = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTemp = new AuthKey(_crypto, log, _readerMap)\n this._authKeyTempSecondary = new AuthKey(_crypto, log, _readerMap)\n }\n\n get hasPendingMessages(): boolean {\n return Boolean(\n this.queuedRpc.length ||\n this.queuedAcks.length ||\n this.queuedStateReq.length ||\n this.queuedResendReq.length,\n )\n }\n\n /**\n * Reset session by resetting auth key(s) and session state\n */\n reset(withAuthKey = false): void {\n if (withAuthKey) {\n this.resetAuthKey()\n }\n\n clearTimeout(this.current429Timeout)\n this.resetState(withAuthKey)\n this.resetLastPing(true)\n }\n\n resetAuthKey(): void {\n this._authKey.reset()\n this._authKeyTemp.reset()\n this._authKeyTempSecondary.reset()\n }\n\n updateTimeOffset(offset: number) {\n this.log.debug('time offset updated: %d', offset)\n this._timeOffset = offset\n // lastMessageId was generated with (potentially) wrong time\n // reset it to avoid bigger issues - at worst, we'll get bad_msg_notification\n this._lastMessageId = Long.ZERO\n }\n\n /**\n * Reset session state and generate a new session ID.\n *\n * By default, also cancels any pending RPC requests.\n * If `keepPending` is set to `true`, pending requests will be kept\n */\n resetState(keepPending = false): void {\n this._lastMessageId = Long.ZERO\n this._seqNo = 0\n\n this._sessionId = randomLong()\n this.log.debug('session reset, new sid = %h', this._sessionId)\n this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `\n\n // reset session state\n\n if (!keepPending) {\n for (const info of this.pendingMessages.values()) {\n if (info._ === 'rpc') {\n this.log.debug('rejecting pending rpc %s', info.rpc.method)\n info.rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n this.pendingMessages.clear()\n }\n\n this.recentOutgoingMsgIds.clear()\n this.recentIncomingMsgIds.clear()\n\n if (!keepPending) {\n while (this.queuedRpc.length) {\n const rpc = this.queuedRpc.popFront()!\n\n if (rpc.sent === false) {\n this.log.debug('rejecting pending rpc %s', rpc.method)\n rpc.promise.reject(new MtcuteError('Session is reset'))\n }\n }\n }\n\n this.queuedAcks.length = 0\n this.queuedStateReq.length = 0\n this.queuedResendReq.length = 0\n this.queuedCancelReq.length = 0\n this.getStateSchedule.clear()\n this.chains.clear()\n this.chainsPendingFails.clear()\n }\n\n enqueueRpc(rpc: PendingRpc, force?: boolean): boolean {\n // already queued or cancelled\n if ((!force && !rpc.sent) || rpc.cancelled) return false\n\n rpc.sent = false\n rpc.containerId = undefined\n this.log.debug('enqueued %s for sending (msg_id = %s)', rpc.method, rpc.msgId || 'n/a')\n this.queuedRpc.pushBack(rpc)\n\n return true\n }\n\n getMessageId(): Long {\n const timeTicks = Date.now()\n const timeSec = Math.floor(timeTicks / 1000) - this._timeOffset\n const timeMSec = timeTicks % 1000\n const random = getRandomInt(0xffff)\n\n let messageId = new Long((timeMSec << 21) | (random << 3) | 4, timeSec)\n\n if (this._lastMessageId.ge(messageId)) {\n messageId = this._lastMessageId.add(4)\n }\n\n this._lastMessageId = messageId\n\n return messageId\n }\n\n getSeqNo(isContentRelated = true): number {\n let seqNo = this._seqNo\n\n if (isContentRelated) {\n seqNo += 1\n this._seqNo += 2\n }\n\n return seqNo\n }\n\n /** Encrypt a single MTProto message using session's keys */\n encryptMessage(message: Uint8Array): Uint8Array {\n const key = this._authKeyTemp.ready ? this._authKeyTemp : this._authKey\n\n return key.encryptMessage(message, this._salts.currentSalt, this._sessionId)\n }\n\n /** Decrypt a single MTProto message using session's keys */\n decryptMessage(data: Uint8Array, callback: Parameters<AuthKey['decryptMessage']>[2]): void {\n if (!this._authKey.ready) throw new MtcuteError('Keys are not set up!')\n\n const authKeyId = data.subarray(0, 8)\n\n let key: AuthKey\n\n if (this._authKey.match(authKeyId)) {\n key = this._authKey\n } else if (this._authKeyTemp.match(authKeyId)) {\n key = this._authKeyTemp\n } else if (this._authKeyTempSecondary.match(authKeyId)) {\n key = this._authKeyTempSecondary\n } else {\n this.log.warn(\n 'received message with unknown authKey = %h (expected %h or %h or %h)',\n authKeyId,\n this._authKey.id,\n this._authKeyTemp.id,\n this._authKeyTempSecondary.id,\n )\n\n return\n }\n\n return key.decryptMessage(data, this._sessionId, callback)\n }\n\n writeMessage(\n writer: TlBinaryWriter,\n content: tl.TlObject | mtp.TlObject | Uint8Array,\n isContentRelated = true,\n ): Long {\n const messageId = this.getMessageId()\n const seqNo = this.getSeqNo(isContentRelated)\n\n const length = ArrayBuffer.isView(content) ?\n content.length :\n TlSerializationCounter.countNeededBytes(writer.objectMap!, content)\n\n writer.long(messageId)\n writer.int(seqNo)\n writer.uint(length)\n if (ArrayBuffer.isView(content)) writer.raw(content)\n else writer.object(content as tl.TlObject)\n\n return messageId\n }\n\n onTransportFlood(callback: () => void) {\n if (this.current429Timeout) return // already waiting\n\n // all active queries must be resent after a timeout\n this.resetLastPing(true)\n\n const timeout = this.next429Timeout\n\n this.next429Timeout = Math.min(this.next429Timeout * 2, 32000)\n clearTimeout(this.current429Timeout)\n clearTimeout(this.next429ResetTimeout)\n\n this.current429Timeout = setTimeout(() => {\n this.current429Timeout = undefined\n callback()\n }, timeout)\n this.next429ResetTimeout = setTimeout(() => {\n this.next429ResetTimeout = undefined\n this.next429Timeout = 1000\n }, 60000)\n\n this.log.debug('transport flood, waiting for %d ms before proceeding', timeout)\n\n return Date.now() + timeout\n }\n\n resetLastPing(withTime = false): void {\n if (withTime) this.lastPingTime = 0\n\n if (!this.lastPingMsgId.isZero()) {\n this.pendingMessages.delete(this.lastPingMsgId)\n }\n\n this.lastPingMsgId = Long.ZERO\n }\n\n addToChain(chainId: string | number, msgId: Long): Long | undefined {\n const prevMsgId = this.chains.get(chainId)\n this.chains.set(chainId, msgId)\n\n this.log.debug('added message %l to chain %s (prev: %l)', msgId, chainId, prevMsgId)\n\n return prevMsgId\n }\n\n removeFromChain(chainId: string | number, msgId: Long): void {\n const lastMsgId = this.chains.get(chainId)\n\n if (!lastMsgId) {\n this.log.warn('tried to remove message %l from empty chain %s', msgId, chainId)\n\n return\n }\n\n if (lastMsgId.eq(msgId)) {\n // last message of the chain, remove it\n this.log.debug('chain %s: exhausted, last message %l', msgId, chainId)\n this.chains.delete(chainId)\n }\n\n // do nothing\n }\n\n getPendingChainedFails(chainId: string | number): SortedArray<PendingRpc> {\n let arr = this.chainsPendingFails.get(chainId)\n\n if (!arr) {\n arr = new SortedArray<PendingRpc>([], (a, b) => compareLongs(a.invokeAfter!, b.invokeAfter!))\n this.chainsPendingFails.set(chainId, arr)\n }\n\n return arr\n }\n}\n"]}
@@ -36,6 +36,7 @@ export interface NetworkManagerParams {
36
36
  onUsable: () => void;
37
37
  onConnecting: () => void;
38
38
  onNetworkChanged: (connected: boolean) => void;
39
+ stopSignal: AbortSignal;
39
40
  }
40
41
  export type ConnectionCountDelegate = (kind: ConnectionKind, dcId: number, isPremium: boolean) => number;
41
42
  /**
@@ -53,10 +54,15 @@ export interface NetworkManagerExtraParams {
53
54
  * The function should be pure to avoid unexpected behavior.
54
55
  *
55
56
  * Defaults to TDLib logic:
56
- * - main: handled internally, **cannot be changed here**
57
+ * - main: 0 (which stands for "handle internally, based on tmp_sessions value")
57
58
  * - upload: if premium or dc id is other than 2 or 4, then 8, otherwise 4
58
59
  * - download: if premium then 8, otherwise 2
59
60
  * - downloadSmall: 2
61
+ *
62
+ * Non-zero value for `main` is **for advanced users only**
63
+ * as it may lead to unexpected behavior, and is generally not recommended
64
+ * because of unnecessary extra load on both the server and the client as well as
65
+ * increased possibility of encountering AUTH_KEY_DUPLICATED errors.
60
66
  */
61
67
  connectionCount?: ConnectionCountDelegate;
62
68
  /**
@@ -161,7 +167,7 @@ export declare class DcConnectionManager {
161
167
  download: MultiSessionConnection;
162
168
  /** Download connection pool (for small files) */
163
169
  downloadSmall: MultiSessionConnection;
164
- private get _mainConnectionCount();
170
+ private get _mainCountOverride();
165
171
  constructor(
166
172
  /** Network manager instance */
167
173
  manager: NetworkManager,
@@ -175,6 +181,7 @@ export declare class DcConnectionManager {
175
181
  setIsPrimary(isPrimary: boolean): void;
176
182
  setIsPremium(isPremium: boolean): void;
177
183
  loadKeys(forcePfs?: boolean): Promise<boolean>;
184
+ setMainConnectionCount(count: number): void;
178
185
  destroy(): Promise<void>;
179
186
  }
180
187
  /**
@@ -1,7 +1,7 @@
1
1
  import { tl } from '@mtcute/tl';
2
2
  import { getPlatform } from '../platform.js';
3
3
  import { MtArgumentError, MtcuteError, MtTimeoutError, MtUnsupportedError } from '../types/index.js';
4
- import { createControllablePromise, sleep, } from '../utils/index.js';
4
+ import { createControllablePromise, sleepWithAbort, } from '../utils/index.js';
5
5
  import { assertTypeIs } from '../utils/type-assertions.js';
6
6
  import { MultiSessionConnection } from './multi-session-connection.js';
7
7
  import { defaultReconnectionStrategy } from './reconnection.js';
@@ -18,7 +18,7 @@ const CLIENT_ERRORS = {
18
18
  const defaultConnectionCountDelegate = (kind, dcId, isPremium) => {
19
19
  switch (kind) {
20
20
  case 'main':
21
- return 1;
21
+ return 0;
22
22
  case 'upload':
23
23
  return isPremium || (dcId !== 2 && dcId !== 4) ? 8 : 4;
24
24
  case 'download':
@@ -45,10 +45,8 @@ export class DcConnectionManager {
45
45
  download;
46
46
  /** Download connection pool (for small files) */
47
47
  downloadSmall;
48
- get _mainConnectionCount() {
49
- if (!this.isPrimary)
50
- return 1;
51
- return this.manager.config.getNow()?.tmpSessions ?? 1;
48
+ get _mainCountOverride() {
49
+ return this.manager.params.connectionCount?.('main', this.dcId, this.manager.params.isPremium) ?? 0;
52
50
  }
53
51
  constructor(
54
52
  /** Network manager instance */
@@ -89,7 +87,17 @@ export class DcConnectionManager {
89
87
  if (isPrimary) {
90
88
  mainParams.inactivityTimeout = undefined;
91
89
  }
92
- this.main = new MultiSessionConnection(mainParams, this._mainConnectionCount, this._log, 'MAIN');
90
+ let mainCount;
91
+ if (this.isPrimary) {
92
+ mainCount = this._mainCountOverride;
93
+ if (mainCount === 0) {
94
+ mainCount = this.manager.config.getNow()?.tmpSessions ?? 1;
95
+ }
96
+ }
97
+ else {
98
+ mainCount = 1;
99
+ }
100
+ this.main = new MultiSessionConnection(mainParams, mainCount, this._log, 'MAIN');
93
101
  this.upload = new MultiSessionConnection(baseConnectionParams(), this.manager._connectionCount('upload', this.dcId, this.manager.params.isPremium), this._log, 'UPLOAD');
94
102
  this.download = new MultiSessionConnection(baseConnectionParams(), this.manager._connectionCount('download', this.dcId, this.manager.params.isPremium), this._log, 'DOWNLOAD');
95
103
  this.downloadSmall = new MultiSessionConnection(baseConnectionParams(), this.manager._connectionCount('downloadSmall', this.dcId, this.manager.params.isPremium), this._log, 'DOWNLOAD_SMALL');
@@ -213,6 +221,11 @@ export class DcConnectionManager {
213
221
  }
214
222
  return true;
215
223
  }
224
+ setMainConnectionCount(count) {
225
+ if (this._mainCountOverride > 0)
226
+ return;
227
+ this.main.setCount(count);
228
+ }
216
229
  async destroy() {
217
230
  await this.main.destroy();
218
231
  await this.upload.destroy();
@@ -244,7 +257,7 @@ export class NetworkManager {
244
257
  _: 'initConnection',
245
258
  deviceModel,
246
259
  systemVersion: '1.0',
247
- appVersion: '0.13.3',
260
+ appVersion: '0.14.0',
248
261
  systemLangCode: 'en',
249
262
  langPack: '', // "langPacks are for official apps only"
250
263
  langCode: 'en',
@@ -393,7 +406,7 @@ export class NetworkManager {
393
406
  let user;
394
407
  if (auth._ === 'auth.authorization') {
395
408
  if (auth.tmpSessions) {
396
- this._primaryDc?.main.setCount(auth.tmpSessions);
409
+ this._primaryDc?.setMainConnectionCount(auth.tmpSessions);
397
410
  }
398
411
  user = auth.user;
399
412
  }
@@ -436,7 +449,7 @@ export class NetworkManager {
436
449
  }
437
450
  _onConfigChanged(config) {
438
451
  if (config.tmpSessions) {
439
- this._primaryDc?.main.setCount(config.tmpSessions);
452
+ this._primaryDc?.setMainConnectionCount(config.tmpSessions);
440
453
  }
441
454
  }
442
455
  async changePrimaryDc(newDc) {
@@ -465,7 +478,7 @@ export class NetworkManager {
465
478
  this._floodWaitedRequests.delete(message._);
466
479
  }
467
480
  else if (delta <= this.params.floodSleepThreshold) {
468
- await sleep(delta);
481
+ await sleepWithAbort(delta, this.params.stopSignal);
469
482
  this._floodWaitedRequests.delete(message._);
470
483
  }
471
484
  else {
@@ -506,7 +519,7 @@ export class NetworkManager {
506
519
  this._log.warn('Telegram is having internal issues: %d:%s (%s), retrying', e.code, e.text, e.message);
507
520
  if (e.text === 'WORKER_BUSY_TOO_LONG_RETRY') {
508
521
  // according to tdlib, "it is dangerous to resend query without timeout, so use 1"
509
- await sleep(1000);
522
+ await sleepWithAbort(1000, this.params.stopSignal);
510
523
  }
511
524
  continue;
512
525
  }
@@ -521,8 +534,8 @@ export class NetworkManager {
521
534
  e.seconds = 1;
522
535
  }
523
536
  if (e.seconds <= floodSleepThreshold) {
524
- this._log.info('Flood wait for %d seconds (because of %s)', e.seconds, message._);
525
- await sleep(e.seconds * 1000);
537
+ this._log.warn('%s resulted in a flood wait, will retry in %d seconds', message._, e.seconds);
538
+ await sleepWithAbort(e.seconds * 1000, this.params.stopSignal);
526
539
  continue;
527
540
  }
528
541
  }