@mtcute/core 0.2.3 → 0.4.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 (127) hide show
  1. package/cjs/base-client.d.ts +33 -166
  2. package/cjs/base-client.js +69 -45
  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 +35 -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 +193 -54
  24. package/cjs/network/session-connection.js.map +1 -1
  25. package/cjs/storage/abstract.d.ts +13 -2
  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-file.d.ts +1 -2
  34. package/cjs/storage/json-file.js +4 -12
  35. package/cjs/storage/json-file.js.map +1 -1
  36. package/cjs/storage/json.js +1 -0
  37. package/cjs/storage/json.js.map +1 -1
  38. package/cjs/storage/memory.d.ts +5 -2
  39. package/cjs/storage/memory.js +16 -2
  40. package/cjs/storage/memory.js.map +1 -1
  41. package/cjs/storage/memory.test.js +2 -1
  42. package/cjs/storage/memory.test.js.map +1 -1
  43. package/cjs/utils/index.d.ts +1 -0
  44. package/cjs/utils/index.js +1 -0
  45. package/cjs/utils/index.js.map +1 -1
  46. package/cjs/utils/logger.js +8 -2
  47. package/cjs/utils/logger.js.map +1 -1
  48. package/cjs/utils/logger.test.js +12 -0
  49. package/cjs/utils/logger.test.js.map +1 -1
  50. package/cjs/utils/long-utils.d.ts +5 -0
  51. package/cjs/utils/long-utils.js +13 -1
  52. package/cjs/utils/long-utils.js.map +1 -1
  53. package/cjs/utils/platform/exit-hook.d.ts +1 -0
  54. package/cjs/utils/platform/exit-hook.js +45 -0
  55. package/cjs/utils/platform/exit-hook.js.map +1 -0
  56. package/cjs/utils/platform/exit-hook.web.d.ts +1 -0
  57. package/cjs/utils/platform/exit-hook.web.js +21 -0
  58. package/cjs/utils/platform/exit-hook.web.js.map +1 -0
  59. package/cjs/utils/sorted-array.js +1 -0
  60. package/cjs/utils/sorted-array.js.map +1 -1
  61. package/cjs/utils/type-assertions.d.ts +1 -0
  62. package/cjs/utils/type-assertions.js +7 -1
  63. package/cjs/utils/type-assertions.js.map +1 -1
  64. package/esm/base-client.d.ts +33 -166
  65. package/esm/base-client.js +69 -45
  66. package/esm/base-client.js.map +1 -1
  67. package/esm/base-client.types.d.ts +153 -0
  68. package/esm/base-client.types.js +2 -0
  69. package/esm/base-client.types.js.map +1 -0
  70. package/esm/index.d.ts +1 -0
  71. package/esm/index.js +1 -0
  72. package/esm/index.js.map +1 -1
  73. package/esm/network/mtproto-session.d.ts +10 -2
  74. package/esm/network/mtproto-session.js +36 -4
  75. package/esm/network/mtproto-session.js.map +1 -1
  76. package/esm/network/multi-session-connection.d.ts +1 -1
  77. package/esm/network/multi-session-connection.js +4 -3
  78. package/esm/network/multi-session-connection.js.map +1 -1
  79. package/esm/network/network-manager.d.ts +23 -0
  80. package/esm/network/network-manager.js +29 -9
  81. package/esm/network/network-manager.js.map +1 -1
  82. package/esm/network/server-salt.d.ts +12 -0
  83. package/esm/network/server-salt.js +38 -0
  84. package/esm/network/server-salt.js.map +1 -0
  85. package/esm/network/session-connection.d.ts +6 -1
  86. package/esm/network/session-connection.js +193 -54
  87. package/esm/network/session-connection.js.map +1 -1
  88. package/esm/storage/abstract.d.ts +13 -2
  89. package/esm/storage/abstract.js.map +1 -1
  90. package/esm/storage/idb.d.ts +3 -1
  91. package/esm/storage/idb.js +17 -0
  92. package/esm/storage/idb.js.map +1 -1
  93. package/esm/storage/index.d.ts +1 -0
  94. package/esm/storage/index.js +1 -0
  95. package/esm/storage/index.js.map +1 -1
  96. package/esm/storage/json-file.d.ts +1 -2
  97. package/esm/storage/json-file.js +4 -12
  98. package/esm/storage/json-file.js.map +1 -1
  99. package/esm/storage/json.js +1 -0
  100. package/esm/storage/json.js.map +1 -1
  101. package/esm/storage/memory.d.ts +5 -2
  102. package/esm/storage/memory.js +16 -2
  103. package/esm/storage/memory.js.map +1 -1
  104. package/esm/storage/memory.test.js +2 -1
  105. package/esm/storage/memory.test.js.map +1 -1
  106. package/esm/utils/index.d.ts +1 -0
  107. package/esm/utils/index.js +1 -0
  108. package/esm/utils/index.js.map +1 -1
  109. package/esm/utils/logger.js +8 -2
  110. package/esm/utils/logger.js.map +1 -1
  111. package/esm/utils/logger.test.js +12 -0
  112. package/esm/utils/logger.test.js.map +1 -1
  113. package/esm/utils/long-utils.d.ts +5 -0
  114. package/esm/utils/long-utils.js +11 -0
  115. package/esm/utils/long-utils.js.map +1 -1
  116. package/esm/utils/platform/exit-hook.d.ts +1 -0
  117. package/esm/utils/platform/exit-hook.js +41 -0
  118. package/esm/utils/platform/exit-hook.js.map +1 -0
  119. package/esm/utils/platform/exit-hook.web.d.ts +1 -0
  120. package/esm/utils/platform/exit-hook.web.js +17 -0
  121. package/esm/utils/platform/exit-hook.web.js.map +1 -0
  122. package/esm/utils/sorted-array.js +1 -0
  123. package/esm/utils/sorted-array.js.map +1 -1
  124. package/esm/utils/type-assertions.d.ts +1 -0
  125. package/esm/utils/type-assertions.js +5 -0
  126. package/esm/utils/type-assertions.js.map +1 -1
  127. package/package.json +6 -4
@@ -1 +1 @@
1
- {"version":3,"file":"type-assertions.js","sourceRoot":"","sources":["../../../src/utils/type-assertions.ts"],"names":[],"mappings":";;;AAEA,kDAAyD;AAEzD,qEAAqE;AAErE,SAAgB,SAAS,CAAI,CAA8B;IACvD,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAA;AACxC,CAAC;AAFD,8BAEC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,aAAa,CAAqC,CAAI;IAClE,OAAO,UAAiB,CAA8B;QAClD,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9C,CAAC,CAAA;AACL,CAAC;AAJD,sCAIC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,aAAa,CAAoD,CAAI,EAAE,CAAI;IACvF,OAAO,UAAc,CAA4B;QAC7C,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC,CAAA;AACL,CAAC;AAJD,sCAIC;AAED,SAAgB,YAAY,CACxB,OAAe,EACf,GAAM,EACN,QAAW;IAEX,IAAI,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE;QACpB,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;KAC3D;AACL,CAAC;AARD,oCAQC;AAED,SAAgB,eAAe,CAC3B,OAAe,EACf,GAAM,EACN,WAAc;IAEd,IAAI,GAAG,CAAC,CAAC,KAAK,WAAW,EAAE;QACvB,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;KACvE;AACL,CAAC;AARD,0CAQC;AAED,SAAgB,eAAe,CAC3B,OAAe,EACf,GAAM,EACN,QAAW;IAEX,IAAI,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE;QACpB,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;KAC3D;AACL,CAAC;AARD,0CAQC","sourcesContent":["import { mtp, tl } from '@mtcute/tl'\n\nimport { MtTypeAssertionError } from '../types/errors.js'\n\n// mostly taken from https://github.com/robertmassaioli/ts-is-present\n\nexport function isPresent<T>(t: T | undefined | null | void): t is T {\n return t !== undefined && t !== null\n}\n\n/**\n * Returns a function that can be used to filter down objects\n * to the ones that have a defined non-null value under the key `k`.\n *\n * @example\n * ```ts\n * const filesWithUrl = files.filter(file => file.url);\n * files[0].url // In this case, TS might still treat this as undefined/null\n *\n * const filesWithUrl = files.filter(hasPresentKey(\"url\"));\n * files[0].url // TS will know that this is present\n * ```\n */\nexport function hasPresentKey<K extends string | number | symbol>(k: K) {\n return function <T, V> (a: T & { [k in K]?: V | null }): a is T & { [k in K]: V } {\n return a[k] !== undefined && a[k] !== null\n }\n}\n\n/**\n * Returns a function that can be used to filter down objects\n * to the ones that have a specific value V under a key `k`.\n *\n * @example\n * ```ts\n * type File = { type: \"image\", imageUrl: string } | { type: \"pdf\", pdfUrl: string };\n * const files: File[] = [];\n *\n * const imageFiles = files.filter(file => file.type === \"image\");\n * files[0].type // In this case, TS will still treat it as `\"image\" | \"pdf\"`\n *\n * const filesWithUrl = files.filter(hasValueKey(\"type\", \"image\" as const));\n * files[0].type // TS will now know that this is \"image\"\n * files[0].imageUrl // TS will know this is present, because already it excluded the other union members.\n * ```\n */\nexport function hasValueAtKey<const K extends string | number | symbol, const V>(k: K, v: V) {\n return function <T> (a: T & { [k in K]: unknown }): a is T & { [k in K]: V } {\n return a[k] === v\n }\n}\n\nexport function assertTypeIs<T extends tl.TlObject, K extends T['_']>(\n context: string,\n obj: T,\n expected: K,\n): asserts obj is tl.FindByName<T, K> {\n if (obj._ !== expected) {\n throw new MtTypeAssertionError(context, expected, obj._)\n }\n}\n\nexport function assertTypeIsNot<T extends tl.TlObject, K extends T['_']>(\n context: string,\n obj: T,\n expectedNot: K,\n): asserts obj is Exclude<T, tl.FindByName<T, K>> {\n if (obj._ === expectedNot) {\n throw new MtTypeAssertionError(context, 'not ' + expectedNot, obj._)\n }\n}\n\nexport function mtpAssertTypeIs<T extends mtp.TlObject, K extends T['_']>(\n context: string,\n obj: T,\n expected: K,\n): asserts obj is mtp.FindByName<T, K> {\n if (obj._ !== expected) {\n throw new MtTypeAssertionError(context, expected, obj._)\n }\n}\n"]}
1
+ {"version":3,"file":"type-assertions.js","sourceRoot":"","sources":["../../../src/utils/type-assertions.ts"],"names":[],"mappings":";;;AAEA,kDAAyD;AAEzD,qEAAqE;AAErE,SAAgB,SAAS,CAAI,CAA8B;IACvD,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAA;AACxC,CAAC;AAFD,8BAEC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,aAAa,CAAqC,CAAI;IAClE,OAAO,UAAiB,CAA8B;QAClD,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9C,CAAC,CAAA;AACL,CAAC;AAJD,sCAIC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,aAAa,CAAoD,CAAI,EAAE,CAAI;IACvF,OAAO,UAAc,CAA4B;QAC7C,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC,CAAA;AACL,CAAC;AAJD,sCAIC;AAED,SAAgB,YAAY,CACxB,OAAe,EACf,GAAM,EACN,QAAW;IAEX,IAAI,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE;QACpB,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;KAC3D;AACL,CAAC;AARD,oCAQC;AAED,SAAgB,eAAe,CAC3B,OAAe,EACf,GAAM,EACN,WAAc;IAEd,IAAI,GAAG,CAAC,CAAC,KAAK,WAAW,EAAE;QACvB,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;KACvE;AACL,CAAC;AARD,0CAQC;AAED,SAAgB,eAAe,CAC3B,OAAe,EACf,GAAM,EACN,QAAW;IAEX,IAAI,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE;QACpB,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;KAC3D;AACL,CAAC;AARD,0CAQC;AAED,SAAgB,UAAU,CAAC,OAAe,EAAE,IAAa;IACrD,IAAI,CAAC,IAAI,EAAE;QACP,MAAM,IAAI,gCAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;KAC3D;AACL,CAAC;AAJD,gCAIC","sourcesContent":["import { mtp, tl } from '@mtcute/tl'\n\nimport { MtTypeAssertionError } from '../types/errors.js'\n\n// mostly taken from https://github.com/robertmassaioli/ts-is-present\n\nexport function isPresent<T>(t: T | undefined | null | void): t is T {\n return t !== undefined && t !== null\n}\n\n/**\n * Returns a function that can be used to filter down objects\n * to the ones that have a defined non-null value under the key `k`.\n *\n * @example\n * ```ts\n * const filesWithUrl = files.filter(file => file.url);\n * files[0].url // In this case, TS might still treat this as undefined/null\n *\n * const filesWithUrl = files.filter(hasPresentKey(\"url\"));\n * files[0].url // TS will know that this is present\n * ```\n */\nexport function hasPresentKey<K extends string | number | symbol>(k: K) {\n return function <T, V> (a: T & { [k in K]?: V | null }): a is T & { [k in K]: V } {\n return a[k] !== undefined && a[k] !== null\n }\n}\n\n/**\n * Returns a function that can be used to filter down objects\n * to the ones that have a specific value V under a key `k`.\n *\n * @example\n * ```ts\n * type File = { type: \"image\", imageUrl: string } | { type: \"pdf\", pdfUrl: string };\n * const files: File[] = [];\n *\n * const imageFiles = files.filter(file => file.type === \"image\");\n * files[0].type // In this case, TS will still treat it as `\"image\" | \"pdf\"`\n *\n * const filesWithUrl = files.filter(hasValueKey(\"type\", \"image\" as const));\n * files[0].type // TS will now know that this is \"image\"\n * files[0].imageUrl // TS will know this is present, because already it excluded the other union members.\n * ```\n */\nexport function hasValueAtKey<const K extends string | number | symbol, const V>(k: K, v: V) {\n return function <T> (a: T & { [k in K]: unknown }): a is T & { [k in K]: V } {\n return a[k] === v\n }\n}\n\nexport function assertTypeIs<T extends tl.TlObject, K extends T['_']>(\n context: string,\n obj: T,\n expected: K,\n): asserts obj is tl.FindByName<T, K> {\n if (obj._ !== expected) {\n throw new MtTypeAssertionError(context, expected, obj._)\n }\n}\n\nexport function assertTypeIsNot<T extends tl.TlObject, K extends T['_']>(\n context: string,\n obj: T,\n expectedNot: K,\n): asserts obj is Exclude<T, tl.FindByName<T, K>> {\n if (obj._ === expectedNot) {\n throw new MtTypeAssertionError(context, 'not ' + expectedNot, obj._)\n }\n}\n\nexport function mtpAssertTypeIs<T extends mtp.TlObject, K extends T['_']>(\n context: string,\n obj: T,\n expected: K,\n): asserts obj is mtp.FindByName<T, K> {\n if (obj._ !== expected) {\n throw new MtTypeAssertionError(context, expected, obj._)\n }\n}\n\nexport function assertTrue(context: string, cond: boolean): asserts cond {\n if (!cond) {\n throw new MtTypeAssertionError(context, 'true', 'false')\n }\n}\n"]}
@@ -2,165 +2,19 @@
2
2
  import EventEmitter from 'events';
3
3
  import { tl } from '@mtcute/tl';
4
4
  import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime';
5
+ import { BaseTelegramClientOptions } from './base-client.types.js';
5
6
  import { ConfigManager } from './network/config-manager.js';
6
- import { ReconnectionStrategy, SessionConnection, TransportFactory } from './network/index.js';
7
- import { NetworkManager, NetworkManagerExtraParams, RpcCallOptions } from './network/network-manager.js';
8
- import { PersistentConnectionParams } from './network/persistent-connection.js';
7
+ import { SessionConnection, TransportFactory } from './network/index.js';
8
+ import { NetworkManager, RpcCallOptions } from './network/network-manager.js';
9
9
  import { ITelegramStorage } from './storage/index.js';
10
10
  import { MustEqual } from './types/index.js';
11
- import { CryptoProviderFactory, ICryptoProvider, LogManager } from './utils/index.js';
12
- /** Options for {@link BaseTelegramClient} */
13
- export interface BaseTelegramClientOptions {
14
- /**
15
- * API ID from my.telegram.org
16
- */
17
- apiId: number | string;
18
- /**
19
- * API hash from my.telegram.org
20
- */
21
- apiHash: string;
22
- /**
23
- * Storage to use for this client.
24
- */
25
- storage: ITelegramStorage;
26
- /**
27
- * Cryptography provider factory to allow delegating
28
- * crypto to native addon, worker, etc.
29
- */
30
- crypto?: CryptoProviderFactory;
31
- /**
32
- * Whether to use IPv6 datacenters
33
- * (IPv6 will be preferred when choosing a DC by id)
34
- * (default: false)
35
- */
36
- useIpv6?: boolean;
37
- /**
38
- * Primary DC to use for initial connection.
39
- * This does not mean this will be the only DC used,
40
- * nor that this DC will actually be primary, this only
41
- * determines the first DC the library will try to connect to.
42
- * Can be used to connect to other networks (like test DCs).
43
- *
44
- * When session already contains primary DC, this parameter is ignored.
45
- *
46
- * @default Production DC 2.
47
- */
48
- defaultDcs?: ITelegramStorage.DcOptions;
49
- /**
50
- * Whether to connect to test servers.
51
- *
52
- * If passed, {@link defaultDc} defaults to Test DC 2.
53
- *
54
- * **Must** be passed if using test servers, even if
55
- * you passed custom {@link defaultDc}
56
- */
57
- testMode?: boolean;
58
- /**
59
- * Additional options for initConnection call.
60
- * `apiId` and `query` are not available and will be ignored.
61
- * Omitted values will be filled with defaults
62
- */
63
- initConnectionOptions?: Partial<Omit<tl.RawInitConnectionRequest, 'apiId' | 'query'>>;
64
- /**
65
- * Transport factory to use in the client.
66
- *
67
- * @default platform-specific transport: WebSocket on the web, TCP in node
68
- */
69
- transport?: TransportFactory;
70
- /**
71
- * Reconnection strategy.
72
- *
73
- * @default simple reconnection strategy: first 0ms, then up to 5s (increasing by 1s)
74
- */
75
- reconnectionStrategy?: ReconnectionStrategy<PersistentConnectionParams>;
76
- /**
77
- * Maximum duration of a flood_wait that will be waited automatically.
78
- * Flood waits above this threshold will throw a FloodWaitError.
79
- * Set to 0 to disable. Can be overridden with `throwFlood` parameter in call() params
80
- *
81
- * @default 10000
82
- */
83
- floodSleepThreshold?: number;
84
- /**
85
- * Maximum number of retries when calling RPC methods.
86
- * Call is retried when InternalError or FloodWaitError is encountered.
87
- * Can be set to Infinity.
88
- *
89
- * @default 5
90
- */
91
- maxRetryCount?: number;
92
- /**
93
- * If true, every single API call will be wrapped with `tl.invokeWithoutUpdates`,
94
- * effectively disabling the server-sent events for the clients.
95
- * May be useful in some cases.
96
- *
97
- * Note that this only wraps calls made with `.call()` within the primary
98
- * connection. Additional connections and direct `.sendForResult()` calls
99
- * must be wrapped manually.
100
- *
101
- * @default false
102
- */
103
- disableUpdates?: boolean;
104
- /**
105
- * mtcute can send all unknown RPC errors to [danog](https://github.com/danog)'s
106
- * [error reporting service](https://rpc.pwrtelegram.xyz/).
107
- *
108
- * This is fully anonymous (except maybe IP) and is only used to improve the library
109
- * and developer experience for everyone working with MTProto. This is fully opt-in,
110
- * and if you're too paranoid, you can disable it by manually passing `enableErrorReporting: false` to the client.
111
- *
112
- * @default false
113
- */
114
- enableErrorReporting?: boolean;
115
- /**
116
- * If true, RPC errors will have a stack trace of the initial `.call()`
117
- * or `.sendForResult()` call position, which drastically improves
118
- * debugging experience.<br>
119
- * If false, they will have a stack trace of mtcute internals.
120
- *
121
- * Internally this creates a stack capture before every RPC call
122
- * and stores it until the result is received. This might
123
- * use a lot more memory than normal, thus can be disabled here.
124
- *
125
- * @default true
126
- */
127
- niceStacks?: boolean;
128
- /**
129
- * Extra parameters for {@link NetworkManager}
130
- */
131
- network?: NetworkManagerExtraParams;
132
- /**
133
- * Set logging level for the client.
134
- *
135
- * See static members of {@link LogManager} for possible values.
136
- */
137
- logLevel?: number;
138
- /**
139
- * **EXPERT USE ONLY!**
140
- *
141
- * Override TL layer used for the connection.
142
- *
143
- * **Does not** change the schema used.
144
- */
145
- overrideLayer?: number;
146
- /**
147
- * **EXPERT USE ONLY**
148
- *
149
- * Override reader map used for the connection.
150
- */
151
- readerMap?: TlReaderMap;
152
- /**
153
- * **EXPERT USE ONLY**
154
- *
155
- * Override writer map used for the connection.
156
- */
157
- writerMap?: TlWriterMap;
158
- }
11
+ import { ICryptoProvider, LogManager, StringSessionData } from './utils/index.js';
159
12
  /**
160
13
  * Basic Telegram client that only implements the bare minimum
161
14
  * to make RPC calls and receive low-level updates.
162
15
  */
163
16
  export declare class BaseTelegramClient extends EventEmitter {
17
+ readonly params: BaseTelegramClientOptions;
164
18
  /**
165
19
  * Crypto provider taken from {@link BaseTelegramClientOptions.crypto}
166
20
  */
@@ -169,14 +23,6 @@ export declare class BaseTelegramClient extends EventEmitter {
169
23
  * Telegram storage taken from {@link BaseTelegramClientOptions.storage}
170
24
  */
171
25
  readonly storage: ITelegramStorage;
172
- /**
173
- * API hash taken from {@link BaseTelegramClientOptions.apiHash}
174
- */
175
- protected readonly _apiHash: string;
176
- /**
177
- * "Use IPv6" taken from {@link BaseTelegramClientOptions.useIpv6}
178
- */
179
- protected readonly _useIpv6: boolean;
180
26
  /**
181
27
  * "Test mode" taken from {@link BaseTelegramClientOptions.testMode}
182
28
  */
@@ -197,12 +43,12 @@ export declare class BaseTelegramClient extends EventEmitter {
197
43
  protected _lastUpdateTime: number;
198
44
  readonly _config: ConfigManager;
199
45
  private _connected;
200
- private _onError?;
46
+ _emitError: (err: unknown, connection?: SessionConnection) => void;
201
47
  private _importFrom?;
202
48
  private _importForce?;
203
49
  readonly log: LogManager;
204
50
  readonly network: NetworkManager;
205
- constructor(opts: BaseTelegramClientOptions);
51
+ constructor(params: BaseTelegramClientOptions);
206
52
  protected _keepAliveAction(): void;
207
53
  protected _loadStorage(): Promise<void>;
208
54
  _beforeStorageSave: (() => Promise<void>)[];
@@ -234,6 +80,26 @@ export declare class BaseTelegramClient extends EventEmitter {
234
80
  * @param params Additional call parameters
235
81
  */
236
82
  call<T extends tl.RpcMethod>(message: MustEqual<T, tl.RpcMethod>, params?: RpcCallOptions): Promise<tl.RpcCallReturn[T['_']]>;
83
+ /**
84
+ * Create a Proxy that will call all methods with given call parameters
85
+ * (see {@link RpcCallOptions}})
86
+ *
87
+ * This is useful when you don't call `call()` directly, but rather
88
+ * use high-level API provided by `@mtcute/client`, for example:
89
+ *
90
+ * ```ts
91
+ * const client = new TelegramClient(...)
92
+ *
93
+ * const someone = await client
94
+ * .withCallParams({ timeout: 500 })
95
+ * .getUsers(...)
96
+ * ```
97
+ */
98
+ withCallParams(params: RpcCallOptions): this;
99
+ /**
100
+ * Shorthand for `withCallParams({ abortSignal })`
101
+ */
102
+ withAbortSignal(signal: AbortSignal): this;
237
103
  /**
238
104
  * Change transport for the client.
239
105
  *
@@ -256,8 +122,9 @@ export declare class BaseTelegramClient extends EventEmitter {
256
122
  */
257
123
  onError(handler: (err: unknown, connection?: SessionConnection) => void): void;
258
124
  notifyLoggedIn(auth: tl.auth.RawAuthorization): void;
259
- _emitError(err: unknown, connection?: SessionConnection): void;
260
125
  /**
126
+ * **ADVANCED**
127
+ *
261
128
  * Adds all peers from a given object to entity cache in storage.
262
129
  */
263
130
  _cachePeersFrom(obj: object): Promise<boolean>;
@@ -280,15 +147,15 @@ export declare class BaseTelegramClient extends EventEmitter {
280
147
  /**
281
148
  * Request the session to be imported from the given session string.
282
149
  *
283
- * Note that the string will not be parsed and imported right away,
284
- * instead, it will be imported when `connect()` is called
150
+ * Note that the session will not be imported right away,
151
+ * instead, it will be imported once `connect()` is called
285
152
  *
286
153
  * Also note that the session will only be imported in case
287
154
  * the storage is missing authorization (i.e. does not contain
288
- * auth key for the primary DC), otherwise it will be ignored (unless `force).
155
+ * auth key for the primary DC), otherwise it will be ignored (unless `force`).
289
156
  *
290
157
  * @param session Session string to import
291
158
  * @param force Whether to overwrite existing session
292
159
  */
293
- importSession(session: string, force?: boolean): void;
160
+ importSession(session: string | StringSessionData, force?: boolean): void;
294
161
  }
@@ -12,63 +12,59 @@ import { createControllablePromise, defaultCryptoProviderFactory, defaultProduct
12
12
  * to make RPC calls and receive low-level updates.
13
13
  */
14
14
  export class BaseTelegramClient extends EventEmitter {
15
- constructor(opts) {
15
+ constructor(params) {
16
16
  super();
17
+ this.params = params;
17
18
  /** Unix timestamp when the last update was received */
18
19
  this._lastUpdateTime = 0;
19
20
  this._config = new ConfigManager(() => this.call({ _: 'help.getConfig' }));
20
21
  // not really connected, but rather "connect() was called"
21
22
  this._connected = false;
23
+ this._emitError = console.error.bind(console);
22
24
  this.log = new LogManager('client');
23
25
  this._beforeStorageSave = [];
24
- const apiId = typeof opts.apiId === 'string' ? parseInt(opts.apiId) : opts.apiId;
25
- if (isNaN(apiId)) {
26
- throw new Error('apiId must be a number or a numeric string!');
26
+ if (params.logLevel !== undefined) {
27
+ this.log.level = params.logLevel;
27
28
  }
28
- if (opts.logLevel !== undefined) {
29
- this.log.level = opts.logLevel;
30
- }
31
- this.crypto = (opts.crypto ?? defaultCryptoProviderFactory)();
32
- this.storage = opts.storage;
33
- this._apiHash = opts.apiHash;
34
- this._useIpv6 = Boolean(opts.useIpv6);
35
- this._testMode = Boolean(opts.testMode);
36
- let dc = opts.defaultDcs;
29
+ this.crypto = (params.crypto ?? defaultCryptoProviderFactory)();
30
+ this.storage = params.storage;
31
+ this._testMode = Boolean(params.testMode);
32
+ let dc = params.defaultDcs;
37
33
  if (!dc) {
38
- if (this._testMode) {
39
- dc = this._useIpv6 ? defaultTestIpv6Dc : defaultTestDc;
34
+ if (params.testMode) {
35
+ dc = params.useIpv6 ? defaultTestIpv6Dc : defaultTestDc;
40
36
  }
41
37
  else {
42
- dc = this._useIpv6 ? defaultProductionIpv6Dc : defaultProductionDc;
38
+ dc = params.useIpv6 ? defaultProductionIpv6Dc : defaultProductionDc;
43
39
  }
44
40
  }
45
41
  this._defaultDcs = dc;
46
- this._niceStacks = opts.niceStacks ?? true;
47
- this._layer = opts.overrideLayer ?? tl.LAYER;
48
- this._readerMap = opts.readerMap ?? defaultReaderMap;
49
- this._writerMap = opts.writerMap ?? defaultWriterMap;
42
+ this._niceStacks = params.niceStacks ?? true;
43
+ this._layer = params.overrideLayer ?? tl.LAYER;
44
+ this._readerMap = params.readerMap ?? defaultReaderMap;
45
+ this._writerMap = params.writerMap ?? defaultWriterMap;
50
46
  this.network = new NetworkManager({
51
- apiId,
47
+ apiId: params.apiId,
52
48
  crypto: this.crypto,
53
- disableUpdates: opts.disableUpdates ?? false,
54
- initConnectionOptions: opts.initConnectionOptions,
49
+ disableUpdates: params.disableUpdates ?? false,
50
+ initConnectionOptions: params.initConnectionOptions,
55
51
  layer: this._layer,
56
52
  log: this.log,
57
53
  readerMap: this._readerMap,
58
54
  writerMap: this._writerMap,
59
- reconnectionStrategy: opts.reconnectionStrategy,
55
+ reconnectionStrategy: params.reconnectionStrategy,
60
56
  storage: this.storage,
61
- testMode: this._testMode,
62
- transport: opts.transport,
57
+ testMode: Boolean(params.testMode),
58
+ transport: params.transport,
63
59
  _emitError: this._emitError.bind(this),
64
- floodSleepThreshold: opts.floodSleepThreshold ?? 10000,
65
- maxRetryCount: opts.maxRetryCount ?? 5,
60
+ floodSleepThreshold: params.floodSleepThreshold ?? 10000,
61
+ maxRetryCount: params.maxRetryCount ?? 5,
66
62
  isPremium: false,
67
- useIpv6: Boolean(opts.useIpv6),
63
+ useIpv6: Boolean(params.useIpv6),
68
64
  keepAliveAction: this._keepAliveAction.bind(this),
69
- enableErrorReporting: opts.enableErrorReporting ?? false,
65
+ enableErrorReporting: params.enableErrorReporting ?? false,
70
66
  onUsable: () => this.emit('usable'),
71
- ...(opts.network ?? {}),
67
+ ...(params.network ?? {}),
72
68
  }, this._config);
73
69
  this.storage.setup?.(this.log, this._readerMap, this._writerMap);
74
70
  }
@@ -110,7 +106,7 @@ export class BaseTelegramClient extends EventEmitter {
110
106
  this._defaultDcs = primaryDc;
111
107
  const defaultDcAuthKey = await this.storage.getAuthKeyFor(this._defaultDcs.main.id);
112
108
  if ((this._importForce || !defaultDcAuthKey) && this._importFrom) {
113
- const data = readStringSession(this._readerMap, this._importFrom);
109
+ const data = this._importFrom;
114
110
  if (data.testMode !== this._testMode) {
115
111
  throw new Error('This session string is not for the current backend. ' +
116
112
  `Session is ${data.testMode ? 'test' : 'prod'}, but the client is ${this._testMode ? 'test' : 'prod'}`);
@@ -169,6 +165,40 @@ export class BaseTelegramClient extends EventEmitter {
169
165
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
170
166
  return res;
171
167
  }
168
+ /**
169
+ * Create a Proxy that will call all methods with given call parameters
170
+ * (see {@link RpcCallOptions}})
171
+ *
172
+ * This is useful when you don't call `call()` directly, but rather
173
+ * use high-level API provided by `@mtcute/client`, for example:
174
+ *
175
+ * ```ts
176
+ * const client = new TelegramClient(...)
177
+ *
178
+ * const someone = await client
179
+ * .withCallParams({ timeout: 500 })
180
+ * .getUsers(...)
181
+ * ```
182
+ */
183
+ withCallParams(params) {
184
+ return new Proxy(this, {
185
+ get(target, prop, receiver) {
186
+ if (prop === 'call') {
187
+ return (message, paramsCustom) => target.call(message, {
188
+ ...params,
189
+ ...paramsCustom,
190
+ });
191
+ }
192
+ return Reflect.get(target, prop, receiver);
193
+ },
194
+ });
195
+ }
196
+ /**
197
+ * Shorthand for `withCallParams({ abortSignal })`
198
+ */
199
+ withAbortSignal(signal) {
200
+ return this.withCallParams({ abortSignal: signal });
201
+ }
172
202
  /**
173
203
  * Change transport for the client.
174
204
  *
@@ -192,21 +222,15 @@ export class BaseTelegramClient extends EventEmitter {
192
222
  * this was connection-related error.
193
223
  */
194
224
  onError(handler) {
195
- this._onError = handler;
225
+ this._emitError = handler;
196
226
  }
197
227
  notifyLoggedIn(auth) {
198
228
  this.network.notifyLoggedIn(auth);
199
229
  this.emit('logged_in', auth);
200
230
  }
201
- _emitError(err, connection) {
202
- if (this._onError) {
203
- this._onError(err, connection);
204
- }
205
- else {
206
- console.error(err);
207
- }
208
- }
209
231
  /**
232
+ * **ADVANCED**
233
+ *
210
234
  * Adds all peers from a given object to entity cache in storage.
211
235
  */
212
236
  async _cachePeersFrom(obj) {
@@ -296,18 +320,18 @@ export class BaseTelegramClient extends EventEmitter {
296
320
  /**
297
321
  * Request the session to be imported from the given session string.
298
322
  *
299
- * Note that the string will not be parsed and imported right away,
300
- * instead, it will be imported when `connect()` is called
323
+ * Note that the session will not be imported right away,
324
+ * instead, it will be imported once `connect()` is called
301
325
  *
302
326
  * Also note that the session will only be imported in case
303
327
  * the storage is missing authorization (i.e. does not contain
304
- * auth key for the primary DC), otherwise it will be ignored (unless `force).
328
+ * auth key for the primary DC), otherwise it will be ignored (unless `force`).
305
329
  *
306
330
  * @param session Session string to import
307
331
  * @param force Whether to overwrite existing session
308
332
  */
309
333
  importSession(session, force = false) {
310
- this._importFrom = session;
334
+ this._importFrom = typeof session === 'string' ? readStringSession(this._readerMap, session) : session;
311
335
  this._importForce = force;
312
336
  }
313
337
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base-client.js","sourceRoot":"","sources":["../../src/base-client.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport EventEmitter from 'events'\nimport Long from 'long'\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 { ConfigManager } from './network/config-manager.js'\nimport { ReconnectionStrategy, SessionConnection, TransportFactory } from './network/index.js'\nimport { NetworkManager, NetworkManagerExtraParams, RpcCallOptions } from './network/network-manager.js'\nimport { PersistentConnectionParams } from './network/persistent-connection.js'\nimport { ITelegramStorage } from './storage/index.js'\nimport { MustEqual } from './types/index.js'\nimport {\n ControllablePromise,\n createControllablePromise,\n CryptoProviderFactory,\n defaultCryptoProviderFactory,\n defaultProductionDc,\n defaultProductionIpv6Dc,\n defaultTestDc,\n defaultTestIpv6Dc,\n getAllPeersFrom,\n ICryptoProvider,\n LogManager,\n readStringSession,\n toggleChannelIdMark,\n writeStringSession,\n} from './utils/index.js'\n\n/** Options for {@link BaseTelegramClient} */\nexport interface BaseTelegramClientOptions {\n /**\n * API ID from my.telegram.org\n */\n apiId: number | string\n /**\n * API hash from my.telegram.org\n */\n apiHash: string\n\n /**\n * Storage to use for this client.\n */\n storage: ITelegramStorage\n\n /**\n * Cryptography provider factory to allow delegating\n * crypto to native addon, worker, etc.\n */\n crypto?: CryptoProviderFactory\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?: ITelegramStorage.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, every single API call 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 * Note that this only wraps calls made with `.call()` within the primary\n * connection. Additional connections and direct `.sendForResult()` calls\n * must be wrapped manually.\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 * Set logging level for the client.\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 Telegram client that only implements the bare minimum\n * to make RPC calls and receive low-level updates.\n */\nexport class BaseTelegramClient extends EventEmitter {\n /**\n * Crypto provider taken from {@link BaseTelegramClientOptions.crypto}\n */\n readonly crypto: ICryptoProvider\n\n /**\n * Telegram storage taken from {@link BaseTelegramClientOptions.storage}\n */\n readonly storage: ITelegramStorage\n\n /**\n * API hash taken from {@link BaseTelegramClientOptions.apiHash}\n */\n protected readonly _apiHash: string\n\n /**\n * \"Use IPv6\" taken from {@link BaseTelegramClientOptions.useIpv6}\n */\n protected readonly _useIpv6: boolean\n\n /**\n * \"Test mode\" taken from {@link BaseTelegramClientOptions.testMode}\n */\n protected readonly _testMode: boolean\n\n /**\n * Primary DCs taken from {@link BaseTelegramClientOptions.defaultDcs},\n * loaded from session or changed by other means (like redirecting).\n */\n protected _defaultDcs: ITelegramStorage.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 /** Unix timestamp when the last update was received */\n protected _lastUpdateTime = 0\n\n readonly _config = new ConfigManager(() => this.call({ _: 'help.getConfig' }))\n\n // not really connected, but rather \"connect() was called\"\n private _connected: ControllablePromise<void> | boolean = false\n\n private _onError?: (err: unknown, connection?: SessionConnection) => void\n\n private _importFrom?: string\n private _importForce?: boolean\n\n readonly log = new LogManager('client')\n readonly network: NetworkManager\n\n constructor(opts: BaseTelegramClientOptions) {\n super()\n\n const apiId = typeof opts.apiId === 'string' ? parseInt(opts.apiId) : opts.apiId\n\n if (isNaN(apiId)) {\n throw new Error('apiId must be a number or a numeric string!')\n }\n\n if (opts.logLevel !== undefined) {\n this.log.level = opts.logLevel\n }\n\n this.crypto = (opts.crypto ?? defaultCryptoProviderFactory)()\n\n this.storage = opts.storage\n this._apiHash = opts.apiHash\n this._useIpv6 = Boolean(opts.useIpv6)\n this._testMode = Boolean(opts.testMode)\n\n let dc = opts.defaultDcs\n\n if (!dc) {\n if (this._testMode) {\n dc = this._useIpv6 ? defaultTestIpv6Dc : defaultTestDc\n } else {\n dc = this._useIpv6 ? defaultProductionIpv6Dc : defaultProductionDc\n }\n }\n\n this._defaultDcs = dc\n this._niceStacks = opts.niceStacks ?? true\n\n this._layer = opts.overrideLayer ?? tl.LAYER\n this._readerMap = opts.readerMap ?? defaultReaderMap\n this._writerMap = opts.writerMap ?? defaultWriterMap\n\n this.network = new NetworkManager(\n {\n apiId,\n crypto: this.crypto,\n disableUpdates: opts.disableUpdates ?? false,\n initConnectionOptions: opts.initConnectionOptions,\n layer: this._layer,\n log: this.log,\n readerMap: this._readerMap,\n writerMap: this._writerMap,\n reconnectionStrategy: opts.reconnectionStrategy,\n storage: this.storage,\n testMode: this._testMode,\n transport: opts.transport,\n _emitError: this._emitError.bind(this),\n floodSleepThreshold: opts.floodSleepThreshold ?? 10000,\n maxRetryCount: opts.maxRetryCount ?? 5,\n isPremium: false,\n useIpv6: Boolean(opts.useIpv6),\n keepAliveAction: this._keepAliveAction.bind(this),\n enableErrorReporting: opts.enableErrorReporting ?? false,\n onUsable: () => this.emit('usable'),\n ...(opts.network ?? {}),\n },\n this._config,\n )\n\n this.storage.setup?.(this.log, this._readerMap, this._writerMap)\n }\n\n protected _keepAliveAction(): void {\n this.emit('keep_alive')\n }\n\n protected async _loadStorage(): Promise<void> {\n await this.storage.load?.()\n }\n\n _beforeStorageSave: (() => Promise<void>)[] = []\n\n beforeStorageSave(cb: () => Promise<void>): void {\n this._beforeStorageSave.push(cb)\n }\n\n offBeforeStorageSave(cb: () => Promise<void>): void {\n this._beforeStorageSave = this._beforeStorageSave.filter((x) => x !== cb)\n }\n\n async saveStorage(): Promise<void> {\n for (const cb of this._beforeStorageSave) {\n await cb()\n }\n await this.storage.save?.()\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 if (this._connected) {\n // avoid double-connect\n await this._connected\n\n return\n }\n\n const promise = (this._connected = createControllablePromise())\n\n await this.crypto.initialize?.()\n await this._loadStorage()\n const primaryDc = await this.storage.getDefaultDcs()\n if (primaryDc !== null) this._defaultDcs = primaryDc\n\n const defaultDcAuthKey = await this.storage.getAuthKeyFor(this._defaultDcs.main.id)\n\n if ((this._importForce || !defaultDcAuthKey) && this._importFrom) {\n const data = readStringSession(this._readerMap, this._importFrom)\n\n if (data.testMode !== this._testMode) {\n throw new Error(\n 'This session string is not for the current backend. ' +\n `Session is ${data.testMode ? 'test' : 'prod'}, but the client is ${\n this._testMode ? 'test' : 'prod'\n }`,\n )\n }\n\n this._defaultDcs = data.primaryDcs\n await this.storage.setDefaultDcs(data.primaryDcs)\n\n if (data.self) {\n await this.storage.setSelf(data.self)\n }\n\n // await this.primaryConnection.setupKeys(data.authKey)\n await this.storage.setAuthKeyFor(data.primaryDcs.main.id, data.authKey)\n\n await this.saveStorage()\n }\n\n this.emit('before_connect')\n\n this.network\n .connect(this._defaultDcs)\n .then(() => {\n promise.resolve()\n this._connected = true\n })\n .catch((err: Error) => this._emitError(err))\n }\n\n /**\n * Close all connections and finalize the client.\n */\n async close(): Promise<void> {\n this.emit('before_close')\n\n this._config.destroy()\n this.network.destroy()\n\n await this.saveStorage()\n await this.storage.destroy?.()\n\n this.emit('closed')\n }\n\n /**\n * Make an RPC call to the primary DC.\n * This method handles DC migration, flood waits and retries automatically.\n *\n * If you want more low-level control, use\n * `primaryConnection.sendForResult()` (which is what this method wraps)\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 if (this._connected !== true) {\n await this.connect()\n }\n\n const stack = this._niceStacks ? new Error().stack : undefined\n\n const res = await this.network.call(message, params, stack)\n\n if (await this._cachePeersFrom(res)) {\n await this.saveStorage()\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return res\n }\n\n /**\n * Change transport for the client.\n *\n * Can be used, for example, to change proxy at runtime\n *\n * This effectively calls `changeTransport()` on\n * `primaryConnection` and all additional connections.\n *\n * @param factory New transport factory\n */\n changeTransport(factory: TransportFactory): void {\n this.network.changeTransport(factory)\n }\n\n /**\n * Register an error handler for the client\n *\n * @param handler\n * Error handler. Called with one or two parameters.\n * The first one is always the error, and the second is\n * the connection in which the error has occurred, in case\n * this was connection-related error.\n */\n onError(handler: (err: unknown, connection?: SessionConnection) => void): void {\n this._onError = handler\n }\n\n notifyLoggedIn(auth: tl.auth.RawAuthorization): void {\n this.network.notifyLoggedIn(auth)\n this.emit('logged_in', auth)\n }\n\n _emitError(err: unknown, connection?: SessionConnection): void {\n if (this._onError) {\n this._onError(err, connection)\n } else {\n console.error(err)\n }\n }\n\n /**\n * Adds all peers from a given object to entity cache in storage.\n */\n async _cachePeersFrom(obj: object): Promise<boolean> {\n const parsedPeers: ITelegramStorage.PeerInfo[] = []\n\n let count = 0\n\n for (const peer of getAllPeersFrom(obj as tl.TlObject)) {\n if ((peer as any).min) {\n // no point in caching min peers as we can't use them\n continue\n }\n\n count += 1\n\n switch (peer._) {\n case 'user':\n if (!peer.accessHash) {\n this.log.warn('received user without access hash: %j', peer)\n continue\n }\n\n parsedPeers.push({\n id: peer.id,\n accessHash: peer.accessHash,\n username: peer.username?.toLowerCase(),\n phone: peer.phone,\n type: 'user',\n full: peer,\n })\n break\n case 'chat':\n case 'chatForbidden':\n parsedPeers.push({\n id: -peer.id,\n accessHash: Long.ZERO,\n type: 'chat',\n full: peer,\n })\n break\n case 'channel':\n case 'channelForbidden':\n if (!peer.accessHash) {\n this.log.warn('received user without access hash: %j', peer)\n continue\n }\n parsedPeers.push({\n id: toggleChannelIdMark(peer.id),\n accessHash: peer.accessHash,\n username: peer._ === 'channel' ? peer.username?.toLowerCase() : undefined,\n type: 'channel',\n full: peer,\n })\n break\n }\n }\n\n if (count > 0) {\n await this.storage.updatePeers(parsedPeers)\n this.log.debug('cached %d peers', count)\n\n return true\n }\n\n return false\n }\n\n /**\n * Export current session to a single *LONG* string, containing\n * all the needed information.\n *\n * > **Warning!** Anyone with this string will be able\n * > to authorize as you and do anything. Treat this\n * > as your password, and never give it away!\n * >\n * > In case you have accidentally leaked this string,\n * > make sure to revoke this session in account settings:\n * > \"Privacy & Security\" > \"Active sessions\" >\n * > find the one containing `mtcute` > Revoke,\n * > or, in case this is a bot, revoke bot token\n * > with [@BotFather](//t.me/botfather)\n */\n async exportSession(): Promise<string> {\n const primaryDcs = (await this.storage.getDefaultDcs()) ?? this._defaultDcs\n\n const authKey = await this.storage.getAuthKeyFor(primaryDcs.main.id)\n if (!authKey) throw new Error('Auth key is not ready yet')\n\n return writeStringSession(this._writerMap, {\n version: 2,\n self: await this.storage.getSelf(),\n testMode: this._testMode,\n primaryDcs,\n authKey,\n })\n }\n\n /**\n * Request the session to be imported from the given session string.\n *\n * Note that the string will not be parsed and imported right away,\n * instead, it will be imported when `connect()` is called\n *\n * Also note that the session will only be imported in case\n * the storage is missing authorization (i.e. does not contain\n * auth key for the primary DC), otherwise it will be ignored (unless `force).\n *\n * @param session Session string to import\n * @param force Whether to overwrite existing session\n */\n importSession(session: string, force = false): void {\n this._importFrom = session\n this._importForce = force\n }\n}\n"]}
1
+ {"version":3,"file":"base-client.js","sourceRoot":"","sources":["../../src/base-client.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport EventEmitter from 'events'\nimport Long from 'long'\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 { BaseTelegramClientOptions } from './base-client.types.js'\nimport { ConfigManager } from './network/config-manager.js'\nimport { SessionConnection, TransportFactory } from './network/index.js'\nimport { NetworkManager, RpcCallOptions } from './network/network-manager.js'\nimport { ITelegramStorage } from './storage/index.js'\nimport { MustEqual } from './types/index.js'\nimport {\n ControllablePromise,\n createControllablePromise,\n defaultCryptoProviderFactory,\n defaultProductionDc,\n defaultProductionIpv6Dc,\n defaultTestDc,\n defaultTestIpv6Dc,\n getAllPeersFrom,\n ICryptoProvider,\n LogManager,\n readStringSession,\n StringSessionData,\n toggleChannelIdMark,\n writeStringSession,\n} from './utils/index.js'\n\n/**\n * Basic Telegram client that only implements the bare minimum\n * to make RPC calls and receive low-level updates.\n */\nexport class BaseTelegramClient extends EventEmitter {\n /**\n * Crypto provider taken from {@link BaseTelegramClientOptions.crypto}\n */\n readonly crypto: ICryptoProvider\n\n /**\n * Telegram storage taken from {@link BaseTelegramClientOptions.storage}\n */\n readonly storage: ITelegramStorage\n\n /**\n * \"Test mode\" taken from {@link BaseTelegramClientOptions.testMode}\n */\n protected readonly _testMode: boolean\n\n /**\n * Primary DCs taken from {@link BaseTelegramClientOptions.defaultDcs},\n * loaded from session or changed by other means (like redirecting).\n */\n protected _defaultDcs: ITelegramStorage.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 /** Unix timestamp when the last update was received */\n protected _lastUpdateTime = 0\n\n readonly _config = new ConfigManager(() => this.call({ _: 'help.getConfig' }))\n\n // not really connected, but rather \"connect() was called\"\n private _connected: ControllablePromise<void> | boolean = false\n\n _emitError: (err: unknown, connection?: SessionConnection) => void = console.error.bind(console)\n\n private _importFrom?: StringSessionData\n private _importForce?: boolean\n\n readonly log = new LogManager('client')\n readonly network: NetworkManager\n\n constructor(readonly params: BaseTelegramClientOptions) {\n super()\n\n if (params.logLevel !== undefined) {\n this.log.level = params.logLevel\n }\n\n this.crypto = (params.crypto ?? defaultCryptoProviderFactory)()\n this.storage = params.storage\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.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 keepAliveAction: this._keepAliveAction.bind(this),\n enableErrorReporting: params.enableErrorReporting ?? false,\n onUsable: () => this.emit('usable'),\n ...(params.network ?? {}),\n },\n this._config,\n )\n\n this.storage.setup?.(this.log, this._readerMap, this._writerMap)\n }\n\n protected _keepAliveAction(): void {\n this.emit('keep_alive')\n }\n\n protected async _loadStorage(): Promise<void> {\n await this.storage.load?.()\n }\n\n _beforeStorageSave: (() => Promise<void>)[] = []\n\n beforeStorageSave(cb: () => Promise<void>): void {\n this._beforeStorageSave.push(cb)\n }\n\n offBeforeStorageSave(cb: () => Promise<void>): void {\n this._beforeStorageSave = this._beforeStorageSave.filter((x) => x !== cb)\n }\n\n async saveStorage(): Promise<void> {\n for (const cb of this._beforeStorageSave) {\n await cb()\n }\n await this.storage.save?.()\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 if (this._connected) {\n // avoid double-connect\n await this._connected\n\n return\n }\n\n const promise = (this._connected = createControllablePromise())\n\n await this.crypto.initialize?.()\n await this._loadStorage()\n const primaryDc = await this.storage.getDefaultDcs()\n if (primaryDc !== null) this._defaultDcs = primaryDc\n\n const defaultDcAuthKey = await this.storage.getAuthKeyFor(this._defaultDcs.main.id)\n\n if ((this._importForce || !defaultDcAuthKey) && this._importFrom) {\n const data = this._importFrom\n\n if (data.testMode !== this._testMode) {\n throw new Error(\n 'This session string is not for the current backend. ' +\n `Session is ${data.testMode ? 'test' : 'prod'}, but the client is ${\n this._testMode ? 'test' : 'prod'\n }`,\n )\n }\n\n this._defaultDcs = data.primaryDcs\n await this.storage.setDefaultDcs(data.primaryDcs)\n\n if (data.self) {\n await this.storage.setSelf(data.self)\n }\n\n // await this.primaryConnection.setupKeys(data.authKey)\n await this.storage.setAuthKeyFor(data.primaryDcs.main.id, data.authKey)\n\n await this.saveStorage()\n }\n\n this.emit('before_connect')\n\n this.network\n .connect(this._defaultDcs)\n .then(() => {\n promise.resolve()\n this._connected = true\n })\n .catch((err: Error) => this._emitError(err))\n }\n\n /**\n * Close all connections and finalize the client.\n */\n async close(): Promise<void> {\n this.emit('before_close')\n\n this._config.destroy()\n this.network.destroy()\n\n await this.saveStorage()\n await this.storage.destroy?.()\n\n this.emit('closed')\n }\n\n /**\n * Make an RPC call to the primary DC.\n * This method handles DC migration, flood waits and retries automatically.\n *\n * If you want more low-level control, use\n * `primaryConnection.sendForResult()` (which is what this method wraps)\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 if (this._connected !== true) {\n await this.connect()\n }\n\n const stack = this._niceStacks ? new Error().stack : undefined\n\n const res = await this.network.call(message, params, stack)\n\n if (await this._cachePeersFrom(res)) {\n await this.saveStorage()\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return res\n }\n\n /**\n * Create a Proxy that will call all methods with given call parameters\n * (see {@link RpcCallOptions}})\n *\n * This is useful when you don't call `call()` directly, but rather\n * use high-level API provided by `@mtcute/client`, for example:\n *\n * ```ts\n * const client = new TelegramClient(...)\n *\n * const someone = await client\n * .withCallParams({ timeout: 500 })\n * .getUsers(...)\n * ```\n */\n withCallParams(params: RpcCallOptions): this {\n return new Proxy(this, {\n get(target, prop, receiver) {\n if (prop === 'call') {\n return (message: tl.RpcMethod, paramsCustom?: RpcCallOptions) =>\n target.call(message, {\n ...params,\n ...paramsCustom,\n })\n }\n\n return Reflect.get(target, prop, receiver)\n },\n })\n }\n\n /**\n * Shorthand for `withCallParams({ abortSignal })`\n */\n withAbortSignal(signal: AbortSignal): this {\n return this.withCallParams({ abortSignal: signal })\n }\n\n /**\n * Change transport for the client.\n *\n * Can be used, for example, to change proxy at runtime\n *\n * This effectively calls `changeTransport()` on\n * `primaryConnection` and all additional connections.\n *\n * @param factory New transport factory\n */\n changeTransport(factory: TransportFactory): void {\n this.network.changeTransport(factory)\n }\n\n /**\n * Register an error handler for the client\n *\n * @param handler\n * Error handler. Called with one or two parameters.\n * The first one is always the error, and the second is\n * the connection in which the error has occurred, in case\n * this was connection-related error.\n */\n onError(handler: (err: unknown, connection?: SessionConnection) => void): void {\n this._emitError = handler\n }\n\n notifyLoggedIn(auth: tl.auth.RawAuthorization): void {\n this.network.notifyLoggedIn(auth)\n this.emit('logged_in', auth)\n }\n\n /**\n * **ADVANCED**\n *\n * Adds all peers from a given object to entity cache in storage.\n */\n async _cachePeersFrom(obj: object): Promise<boolean> {\n const parsedPeers: ITelegramStorage.PeerInfo[] = []\n\n let count = 0\n\n for (const peer of getAllPeersFrom(obj as tl.TlObject)) {\n if ((peer as any).min) {\n // no point in caching min peers as we can't use them\n continue\n }\n\n count += 1\n\n switch (peer._) {\n case 'user':\n if (!peer.accessHash) {\n this.log.warn('received user without access hash: %j', peer)\n continue\n }\n\n parsedPeers.push({\n id: peer.id,\n accessHash: peer.accessHash,\n username: peer.username?.toLowerCase(),\n phone: peer.phone,\n type: 'user',\n full: peer,\n })\n break\n case 'chat':\n case 'chatForbidden':\n parsedPeers.push({\n id: -peer.id,\n accessHash: Long.ZERO,\n type: 'chat',\n full: peer,\n })\n break\n case 'channel':\n case 'channelForbidden':\n if (!peer.accessHash) {\n this.log.warn('received user without access hash: %j', peer)\n continue\n }\n parsedPeers.push({\n id: toggleChannelIdMark(peer.id),\n accessHash: peer.accessHash,\n username: peer._ === 'channel' ? peer.username?.toLowerCase() : undefined,\n type: 'channel',\n full: peer,\n })\n break\n }\n }\n\n if (count > 0) {\n await this.storage.updatePeers(parsedPeers)\n this.log.debug('cached %d peers', count)\n\n return true\n }\n\n return false\n }\n\n /**\n * Export current session to a single *LONG* string, containing\n * all the needed information.\n *\n * > **Warning!** Anyone with this string will be able\n * > to authorize as you and do anything. Treat this\n * > as your password, and never give it away!\n * >\n * > In case you have accidentally leaked this string,\n * > make sure to revoke this session in account settings:\n * > \"Privacy & Security\" > \"Active sessions\" >\n * > find the one containing `mtcute` > Revoke,\n * > or, in case this is a bot, revoke bot token\n * > with [@BotFather](//t.me/botfather)\n */\n async exportSession(): Promise<string> {\n const primaryDcs = (await this.storage.getDefaultDcs()) ?? this._defaultDcs\n\n const authKey = await this.storage.getAuthKeyFor(primaryDcs.main.id)\n if (!authKey) throw new Error('Auth key is not ready yet')\n\n return writeStringSession(this._writerMap, {\n version: 2,\n self: await this.storage.getSelf(),\n testMode: this._testMode,\n primaryDcs,\n authKey,\n })\n }\n\n /**\n * Request the session to be imported from the given session string.\n *\n * Note that the session will not be imported right away,\n * instead, it will be imported once `connect()` is called\n *\n * Also note that the session will only be imported in case\n * the storage is missing authorization (i.e. does not contain\n * auth key for the primary DC), otherwise it will be ignored (unless `force`).\n *\n * @param session Session string to import\n * @param force Whether to overwrite existing session\n */\n importSession(session: string | StringSessionData, force = false): void {\n this._importFrom = typeof session === 'string' ? readStringSession(this._readerMap, session) : session\n this._importForce = force\n }\n}\n"]}