teleproto 1.214.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 (222) hide show
  1. package/CryptoFile.d.ts +2 -0
  2. package/CryptoFile.js +37 -0
  3. package/Helpers.d.ts +150 -0
  4. package/Helpers.js +477 -0
  5. package/LICENSE +23 -0
  6. package/Password.d.ts +14 -0
  7. package/Password.js +270 -0
  8. package/README.md +98 -0
  9. package/Utils.d.ts +227 -0
  10. package/Utils.js +1247 -0
  11. package/Version.d.ts +1 -0
  12. package/Version.js +4 -0
  13. package/client/2fa.d.ts +48 -0
  14. package/client/2fa.js +108 -0
  15. package/client/TelegramClient.d.ts +1043 -0
  16. package/client/TelegramClient.js +1181 -0
  17. package/client/account.d.ts +0 -0
  18. package/client/account.js +1 -0
  19. package/client/auth.d.ts +92 -0
  20. package/client/auth.js +388 -0
  21. package/client/bots.d.ts +6 -0
  22. package/client/bots.js +23 -0
  23. package/client/buttons.d.ts +4 -0
  24. package/client/buttons.js +86 -0
  25. package/client/chats.d.ts +45 -0
  26. package/client/chats.js +350 -0
  27. package/client/dialogs.d.ts +52 -0
  28. package/client/dialogs.js +174 -0
  29. package/client/downloads.d.ts +156 -0
  30. package/client/downloads.js +614 -0
  31. package/client/fs.d.ts +1 -0
  32. package/client/fs.js +17 -0
  33. package/client/index.d.ts +15 -0
  34. package/client/index.js +64 -0
  35. package/client/messageParse.d.ts +17 -0
  36. package/client/messageParse.js +191 -0
  37. package/client/messages.d.ts +263 -0
  38. package/client/messages.js +813 -0
  39. package/client/os.d.ts +2 -0
  40. package/client/os.js +37 -0
  41. package/client/path.d.ts +2 -0
  42. package/client/path.js +7 -0
  43. package/client/telegramBaseClient.d.ts +237 -0
  44. package/client/telegramBaseClient.js +368 -0
  45. package/client/updates.d.ts +33 -0
  46. package/client/updates.js +260 -0
  47. package/client/uploads.d.ts +136 -0
  48. package/client/uploads.js +514 -0
  49. package/client/users.d.ts +29 -0
  50. package/client/users.js +490 -0
  51. package/crypto/AuthKey.d.ts +19 -0
  52. package/crypto/AuthKey.js +76 -0
  53. package/crypto/CTR.d.ts +5 -0
  54. package/crypto/CTR.js +16 -0
  55. package/crypto/Factorizator.d.ts +19 -0
  56. package/crypto/Factorizator.js +74 -0
  57. package/crypto/IGE.d.ts +11 -0
  58. package/crypto/IGE.js +115 -0
  59. package/crypto/RSA.d.ts +14 -0
  60. package/crypto/RSA.js +70 -0
  61. package/crypto/converters.d.ts +19 -0
  62. package/crypto/converters.js +52 -0
  63. package/crypto/crypto.d.ts +19 -0
  64. package/crypto/crypto.js +58 -0
  65. package/crypto/words.d.ts +6 -0
  66. package/crypto/words.js +47 -0
  67. package/define.d.ts +77 -0
  68. package/entityCache.d.ts +7 -0
  69. package/entityCache.js +79 -0
  70. package/errors/Common.d.ts +71 -0
  71. package/errors/Common.js +122 -0
  72. package/errors/RPCBaseErrors.d.ts +84 -0
  73. package/errors/RPCBaseErrors.js +134 -0
  74. package/errors/RPCErrorList.d.ts +37 -0
  75. package/errors/RPCErrorList.js +117 -0
  76. package/errors/index.d.ts +11 -0
  77. package/errors/index.js +32 -0
  78. package/events/Album.d.ts +36 -0
  79. package/events/Album.js +104 -0
  80. package/events/CallbackQuery.d.ts +73 -0
  81. package/events/CallbackQuery.js +193 -0
  82. package/events/DeletedMessage.d.ts +45 -0
  83. package/events/DeletedMessage.js +63 -0
  84. package/events/EditedMessage.d.ts +30 -0
  85. package/events/EditedMessage.js +41 -0
  86. package/events/NewMessage.d.ts +89 -0
  87. package/events/NewMessage.js +182 -0
  88. package/events/Raw.d.ts +29 -0
  89. package/events/Raw.js +43 -0
  90. package/events/common.d.ts +66 -0
  91. package/events/common.js +141 -0
  92. package/events/index.d.ts +2 -0
  93. package/events/index.js +8 -0
  94. package/extensions/AsyncQueue.d.ts +10 -0
  95. package/extensions/AsyncQueue.js +32 -0
  96. package/extensions/BinaryReader.d.ts +99 -0
  97. package/extensions/BinaryReader.js +242 -0
  98. package/extensions/BinaryWriter.d.ts +6 -0
  99. package/extensions/BinaryWriter.js +15 -0
  100. package/extensions/Deferred.d.ts +8 -0
  101. package/extensions/Deferred.js +16 -0
  102. package/extensions/Logger.d.ts +54 -0
  103. package/extensions/Logger.js +128 -0
  104. package/extensions/MessagePacker.d.ts +21 -0
  105. package/extensions/MessagePacker.js +154 -0
  106. package/extensions/PendingState.d.ts +12 -0
  107. package/extensions/PendingState.js +29 -0
  108. package/extensions/PromisedNetSockets.d.ts +24 -0
  109. package/extensions/PromisedNetSockets.js +192 -0
  110. package/extensions/PromisedWebSockets.d.ts +18 -0
  111. package/extensions/PromisedWebSockets.js +124 -0
  112. package/extensions/html.d.ts +5 -0
  113. package/extensions/html.js +228 -0
  114. package/extensions/index.d.ts +7 -0
  115. package/extensions/index.js +17 -0
  116. package/extensions/markdown.d.ts +5 -0
  117. package/extensions/markdown.js +76 -0
  118. package/extensions/markdownv2.d.ts +5 -0
  119. package/extensions/markdownv2.js +51 -0
  120. package/extensions/net.d.ts +1 -0
  121. package/extensions/net.js +17 -0
  122. package/extensions/socks.d.ts +1 -0
  123. package/extensions/socks.js +17 -0
  124. package/index.d.ts +14 -0
  125. package/index.js +62 -0
  126. package/inspect.d.ts +1 -0
  127. package/inspect.js +5 -0
  128. package/network/Authenticator.d.ts +12 -0
  129. package/network/Authenticator.js +192 -0
  130. package/network/MTProtoPlainSender.d.ts +19 -0
  131. package/network/MTProtoPlainSender.js +74 -0
  132. package/network/MTProtoSender.d.ts +290 -0
  133. package/network/MTProtoSender.js +873 -0
  134. package/network/MTProtoState.d.ts +102 -0
  135. package/network/MTProtoState.js +267 -0
  136. package/network/RequestState.d.ts +18 -0
  137. package/network/RequestState.js +35 -0
  138. package/network/connection/Connection.d.ts +69 -0
  139. package/network/connection/Connection.js +162 -0
  140. package/network/connection/TCPAbridged.d.ts +19 -0
  141. package/network/connection/TCPAbridged.js +58 -0
  142. package/network/connection/TCPFull.d.ts +16 -0
  143. package/network/connection/TCPFull.js +61 -0
  144. package/network/connection/TCPMTProxy.d.ts +49 -0
  145. package/network/connection/TCPMTProxy.js +121 -0
  146. package/network/connection/TCPObfuscated.d.ts +18 -0
  147. package/network/connection/TCPObfuscated.js +78 -0
  148. package/network/connection/index.d.ts +4 -0
  149. package/network/connection/index.js +11 -0
  150. package/network/index.d.ts +11 -0
  151. package/network/index.js +23 -0
  152. package/package.json +50 -0
  153. package/requestIter.d.ts +24 -0
  154. package/requestIter.js +109 -0
  155. package/sessions/Abstract.d.ts +103 -0
  156. package/sessions/Abstract.js +6 -0
  157. package/sessions/Memory.d.ts +38 -0
  158. package/sessions/Memory.js +272 -0
  159. package/sessions/StoreSession.d.ts +14 -0
  160. package/sessions/StoreSession.js +77 -0
  161. package/sessions/StringSession.d.ts +32 -0
  162. package/sessions/StringSession.js +116 -0
  163. package/sessions/index.d.ts +4 -0
  164. package/sessions/index.js +11 -0
  165. package/sessions/localStorage.d.ts +1 -0
  166. package/sessions/localStorage.js +4 -0
  167. package/tl/AllTLObjects.d.ts +3 -0
  168. package/tl/AllTLObjects.js +17 -0
  169. package/tl/MTProtoRequest.d.ts +18 -0
  170. package/tl/MTProtoRequest.js +38 -0
  171. package/tl/api.d.ts +32488 -0
  172. package/tl/api.js +507 -0
  173. package/tl/apiTl.d.ts +2 -0
  174. package/tl/apiTl.js +2209 -0
  175. package/tl/core/GZIPPacked.d.ts +15 -0
  176. package/tl/core/GZIPPacked.js +51 -0
  177. package/tl/core/MessageContainer.d.ts +12 -0
  178. package/tl/core/MessageContainer.js +42 -0
  179. package/tl/core/RPCResult.d.ts +14 -0
  180. package/tl/core/RPCResult.js +32 -0
  181. package/tl/core/TLMessage.d.ts +10 -0
  182. package/tl/core/TLMessage.js +14 -0
  183. package/tl/core/index.d.ts +6 -0
  184. package/tl/core/index.js +16 -0
  185. package/tl/custom/button.d.ts +24 -0
  186. package/tl/custom/button.js +78 -0
  187. package/tl/custom/chatGetter.d.ts +29 -0
  188. package/tl/custom/chatGetter.js +116 -0
  189. package/tl/custom/dialog.d.ts +30 -0
  190. package/tl/custom/dialog.js +40 -0
  191. package/tl/custom/draft.d.ts +21 -0
  192. package/tl/custom/draft.js +48 -0
  193. package/tl/custom/file.d.ts +21 -0
  194. package/tl/custom/file.js +68 -0
  195. package/tl/custom/forward.d.ts +15 -0
  196. package/tl/custom/forward.js +47 -0
  197. package/tl/custom/index.d.ts +1 -0
  198. package/tl/custom/index.js +5 -0
  199. package/tl/custom/inlineResult.d.ts +32 -0
  200. package/tl/custom/inlineResult.js +87 -0
  201. package/tl/custom/inlineResults.d.ts +20 -0
  202. package/tl/custom/inlineResults.js +26 -0
  203. package/tl/custom/message.d.ts +427 -0
  204. package/tl/custom/message.js +716 -0
  205. package/tl/custom/messageButton.d.ts +54 -0
  206. package/tl/custom/messageButton.js +152 -0
  207. package/tl/custom/senderGetter.d.ts +28 -0
  208. package/tl/custom/senderGetter.js +55 -0
  209. package/tl/generateModule.d.ts +1 -0
  210. package/tl/generateModule.js +17 -0
  211. package/tl/generationHelpers.d.ts +11 -0
  212. package/tl/generationHelpers.js +289 -0
  213. package/tl/index.d.ts +3 -0
  214. package/tl/index.js +10 -0
  215. package/tl/patched/index.d.ts +2 -0
  216. package/tl/patched/index.js +76 -0
  217. package/tl/schemaTl.d.ts +2 -0
  218. package/tl/schemaTl.js +64 -0
  219. package/tl/types-generator/generate.d.ts +1 -0
  220. package/tl/types-generator/generate.js +84 -0
  221. package/tl/types-generator/template.d.ts +6 -0
  222. package/tl/types-generator/template.js +257 -0
@@ -0,0 +1,102 @@
1
+ import bigInt from "big-integer";
2
+ import type { AuthKey } from "../crypto/AuthKey";
3
+ import { TLMessage } from "../tl/core";
4
+ import type { BinaryWriter } from "../extensions";
5
+ export declare class MTProtoState {
6
+ private readonly authKey?;
7
+ private _log;
8
+ timeOffset: number;
9
+ salt: bigInt.BigInteger;
10
+ private id;
11
+ _sequence: number;
12
+ private _lastMsgId;
13
+ private msgIds;
14
+ private securityChecks;
15
+ /**
16
+ *
17
+ `telethon.network.mtprotosender.MTProtoSender` needs to hold a state
18
+ in order to be able to encrypt and decrypt incoming/outgoing messages,
19
+ as well as generating the message IDs. Instances of this class hold
20
+ together all the required information.
21
+
22
+ It doesn't make sense to use `telethon.sessions.abstract.Session` for
23
+ the sender because the sender should *not* be concerned about storing
24
+ this information to disk, as one may create as many senders as they
25
+ desire to any other data center, or some CDN. Using the same session
26
+ for all these is not a good idea as each need their own authkey, and
27
+ the concept of "copying" sessions with the unnecessary entities or
28
+ updates state for these connections doesn't make sense.
29
+
30
+ While it would be possible to have a `MTProtoPlainState` that does no
31
+ encryption so that it was usable through the `MTProtoLayer` and thus
32
+ avoid the need for a `MTProtoPlainSender`, the `MTProtoLayer` is more
33
+ focused to efficiency and this state is also more advanced (since it
34
+ supports gzipping and invoking after other message IDs). There are too
35
+ many methods that would be needed to make it convenient to use for the
36
+ authentication process, at which point the `MTProtoPlainSender` is better
37
+ * @param authKey
38
+ * @param loggers
39
+ * @param securityChecks
40
+ */
41
+ constructor(authKey?: AuthKey, loggers?: any, securityChecks?: boolean);
42
+ /**
43
+ * Resets the state
44
+ */
45
+ reset(): void;
46
+ /**
47
+ * Updates the message ID to a new one,
48
+ * used when the time offset changed.
49
+ * @param message
50
+ */
51
+ updateMessageId(message: any): void;
52
+ /**
53
+ * Calculate the key based on Telegram guidelines, specifying whether it's the client or not
54
+ * @param authKey
55
+ * @param msgKey
56
+ * @param client
57
+ * @returns {{iv: Buffer, key: Buffer}}
58
+ */
59
+ _calcKey(authKey: Buffer, msgKey: Buffer, client: boolean): Promise<{
60
+ key: Buffer<ArrayBuffer>;
61
+ iv: Buffer<ArrayBuffer>;
62
+ }>;
63
+ /**
64
+ * Writes a message containing the given data into buffer.
65
+ * Returns the message id.
66
+ * @param buffer
67
+ * @param data
68
+ * @param contentRelated
69
+ * @param afterId
70
+ */
71
+ writeDataAsMessage(buffer: BinaryWriter, data: Buffer, contentRelated: boolean, afterId?: bigInt.BigInteger): Promise<bigInt.BigInteger>;
72
+ /**
73
+ * Encrypts the given message data using the current authorization key
74
+ * following MTProto 2.0 guidelines core.telegram.org/mtproto/description.
75
+ * @param data
76
+ */
77
+ encryptMessageData(data: Buffer): Promise<Buffer<ArrayBuffer>>;
78
+ /**
79
+ * Inverse of `encrypt_message_data` for incoming server messages.
80
+ * @param body
81
+ */
82
+ decryptMessageData(body: Buffer): Promise<TLMessage>;
83
+ /**
84
+ * Generates a new unique message ID based on the current
85
+ * time (in ms) since epoch, applying a known time offset.
86
+ * @private
87
+ */
88
+ _getNewMsgId(): bigInt.BigInteger;
89
+ /**
90
+ * Updates the time offset to the correct
91
+ * one given a known valid message ID.
92
+ * @param correctMsgId {BigInteger}
93
+ */
94
+ updateTimeOffset(correctMsgId: bigInt.BigInteger): number;
95
+ /**
96
+ * Generates the next sequence number depending on whether
97
+ * it should be for a content-related query or not.
98
+ * @param contentRelated
99
+ * @private
100
+ */
101
+ _getSeqNo(contentRelated: boolean): number;
102
+ }
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MTProtoState = void 0;
7
+ const big_integer_1 = __importDefault(require("big-integer"));
8
+ const __1 = require("..");
9
+ const tl_1 = require("../tl");
10
+ const Helpers_1 = require("../Helpers");
11
+ const core_1 = require("../tl/core");
12
+ const extensions_1 = require("../extensions");
13
+ const IGE_1 = require("../crypto/IGE");
14
+ const errors_1 = require("../errors");
15
+ class MTProtoState {
16
+ /**
17
+ *
18
+ `telethon.network.mtprotosender.MTProtoSender` needs to hold a state
19
+ in order to be able to encrypt and decrypt incoming/outgoing messages,
20
+ as well as generating the message IDs. Instances of this class hold
21
+ together all the required information.
22
+
23
+ It doesn't make sense to use `telethon.sessions.abstract.Session` for
24
+ the sender because the sender should *not* be concerned about storing
25
+ this information to disk, as one may create as many senders as they
26
+ desire to any other data center, or some CDN. Using the same session
27
+ for all these is not a good idea as each need their own authkey, and
28
+ the concept of "copying" sessions with the unnecessary entities or
29
+ updates state for these connections doesn't make sense.
30
+
31
+ While it would be possible to have a `MTProtoPlainState` that does no
32
+ encryption so that it was usable through the `MTProtoLayer` and thus
33
+ avoid the need for a `MTProtoPlainSender`, the `MTProtoLayer` is more
34
+ focused to efficiency and this state is also more advanced (since it
35
+ supports gzipping and invoking after other message IDs). There are too
36
+ many methods that would be needed to make it convenient to use for the
37
+ authentication process, at which point the `MTProtoPlainSender` is better
38
+ * @param authKey
39
+ * @param loggers
40
+ * @param securityChecks
41
+ */
42
+ constructor(authKey, loggers, securityChecks = true) {
43
+ this.authKey = authKey;
44
+ this._log = loggers;
45
+ this.timeOffset = 0;
46
+ this.salt = big_integer_1.default.zero;
47
+ this._sequence = 0;
48
+ this.id = this._lastMsgId = big_integer_1.default.zero;
49
+ this.msgIds = [];
50
+ this.securityChecks = securityChecks;
51
+ this.reset();
52
+ }
53
+ /**
54
+ * Resets the state
55
+ */
56
+ reset() {
57
+ // Session IDs can be random on every connection
58
+ this.id = __1.helpers.generateRandomLong(true);
59
+ this._sequence = 0;
60
+ this._lastMsgId = big_integer_1.default.zero;
61
+ this.msgIds = [];
62
+ }
63
+ /**
64
+ * Updates the message ID to a new one,
65
+ * used when the time offset changed.
66
+ * @param message
67
+ */
68
+ updateMessageId(message) {
69
+ message.msgId = this._getNewMsgId();
70
+ }
71
+ /**
72
+ * Calculate the key based on Telegram guidelines, specifying whether it's the client or not
73
+ * @param authKey
74
+ * @param msgKey
75
+ * @param client
76
+ * @returns {{iv: Buffer, key: Buffer}}
77
+ */
78
+ async _calcKey(authKey, msgKey, client) {
79
+ const x = client ? 0 : 8;
80
+ const [sha256a, sha256b] = await Promise.all([
81
+ (0, Helpers_1.sha256)(Buffer.concat([msgKey, authKey.slice(x, x + 36)])),
82
+ (0, Helpers_1.sha256)(Buffer.concat([authKey.slice(x + 40, x + 76), msgKey])),
83
+ ]);
84
+ const key = Buffer.concat([
85
+ sha256a.slice(0, 8),
86
+ sha256b.slice(8, 24),
87
+ sha256a.slice(24, 32),
88
+ ]);
89
+ const iv = Buffer.concat([
90
+ sha256b.slice(0, 8),
91
+ sha256a.slice(8, 24),
92
+ sha256b.slice(24, 32),
93
+ ]);
94
+ return { key, iv };
95
+ }
96
+ /**
97
+ * Writes a message containing the given data into buffer.
98
+ * Returns the message id.
99
+ * @param buffer
100
+ * @param data
101
+ * @param contentRelated
102
+ * @param afterId
103
+ */
104
+ async writeDataAsMessage(buffer, data, contentRelated, afterId) {
105
+ const msgId = this._getNewMsgId();
106
+ const seqNo = this._getSeqNo(contentRelated);
107
+ let body;
108
+ if (!afterId) {
109
+ body = await core_1.GZIPPacked.gzipIfSmaller(contentRelated, data);
110
+ }
111
+ else {
112
+ body = await core_1.GZIPPacked.gzipIfSmaller(contentRelated, new tl_1.Api.InvokeAfterMsg({
113
+ msgId: afterId,
114
+ query: {
115
+ getBytes() {
116
+ return data;
117
+ },
118
+ },
119
+ }).getBytes());
120
+ }
121
+ const s = Buffer.alloc(4);
122
+ s.writeInt32LE(seqNo, 0);
123
+ const b = Buffer.alloc(4);
124
+ b.writeInt32LE(body.length, 0);
125
+ const m = (0, Helpers_1.toSignedLittleBuffer)(msgId, 8);
126
+ buffer.write(Buffer.concat([m, s, b]));
127
+ buffer.write(body);
128
+ return msgId;
129
+ }
130
+ /**
131
+ * Encrypts the given message data using the current authorization key
132
+ * following MTProto 2.0 guidelines core.telegram.org/mtproto/description.
133
+ * @param data
134
+ */
135
+ async encryptMessageData(data) {
136
+ if (!this.authKey) {
137
+ throw new Error("Auth key unset");
138
+ }
139
+ await this.authKey.waitForKey();
140
+ const authKey = this.authKey.getKey();
141
+ if (!authKey) {
142
+ throw new Error("Auth key unset");
143
+ }
144
+ if (!this.salt || !this.id || !authKey || !this.authKey.keyId) {
145
+ throw new Error("Unset params");
146
+ }
147
+ const s = (0, Helpers_1.toSignedLittleBuffer)(this.salt, 8);
148
+ const i = (0, Helpers_1.toSignedLittleBuffer)(this.id, 8);
149
+ data = Buffer.concat([Buffer.concat([s, i]), data]);
150
+ const padding = __1.helpers.generateRandomBytes(__1.helpers.mod(-(data.length + 12), 16) + 12);
151
+ // Being substr(what, offset, length); x = 0 for client
152
+ // "msg_key_large = SHA256(substr(auth_key, 88+x, 32) + pt + padding)"
153
+ const msgKeyLarge = await (0, Helpers_1.sha256)(Buffer.concat([authKey.slice(88, 88 + 32), data, padding]));
154
+ // "msg_key = substr (msg_key_large, 8, 16)"
155
+ const msgKey = msgKeyLarge.slice(8, 24);
156
+ const { iv, key } = await this._calcKey(authKey, msgKey, true);
157
+ const keyId = __1.helpers.readBufferFromBigInt(this.authKey.keyId, 8);
158
+ return Buffer.concat([
159
+ keyId,
160
+ msgKey,
161
+ new IGE_1.IGE(key, iv).encryptIge(Buffer.concat([data, padding])),
162
+ ]);
163
+ }
164
+ /**
165
+ * Inverse of `encrypt_message_data` for incoming server messages.
166
+ * @param body
167
+ */
168
+ async decryptMessageData(body) {
169
+ if (!this.authKey) {
170
+ throw new Error("Auth key unset");
171
+ }
172
+ if (body.length < 8) {
173
+ throw new errors_1.InvalidBufferError(body);
174
+ }
175
+ // TODO Check salt,sessionId, and sequenceNumber
176
+ const keyId = __1.helpers.readBigIntFromBuffer(body.slice(0, 8));
177
+ if (!this.authKey.keyId || keyId.neq(this.authKey.keyId)) {
178
+ throw new errors_1.SecurityError("Server replied with an invalid auth key");
179
+ }
180
+ const authKey = this.authKey.getKey();
181
+ if (!authKey) {
182
+ throw new errors_1.SecurityError("Unset AuthKey");
183
+ }
184
+ const msgKey = body.slice(8, 24);
185
+ const { iv, key } = await this._calcKey(authKey, msgKey, false);
186
+ body = new IGE_1.IGE(key, iv).decryptIge(body.slice(24));
187
+ // https://core.telegram.org/mtproto/security_guidelines
188
+ // Sections "checking sha256 hash" and "message length"
189
+ const ourKey = await (0, Helpers_1.sha256)(Buffer.concat([authKey.slice(96, 96 + 32), body]));
190
+ if (!msgKey.equals(ourKey.slice(8, 24))) {
191
+ throw new errors_1.SecurityError("Received msg_key doesn't match with expected one");
192
+ }
193
+ const reader = new extensions_1.BinaryReader(body);
194
+ reader.readLong(); // removeSalt
195
+ const serverId = reader.readLong();
196
+ if (serverId.neq(this.id)) {
197
+ // throw new SecurityError('Server replied with a wrong session ID');
198
+ }
199
+ const remoteMsgId = reader.readLong();
200
+ if (this.msgIds.includes(remoteMsgId.toString()) &&
201
+ this.securityChecks) {
202
+ throw new errors_1.SecurityError("Duplicate msgIds");
203
+ }
204
+ if (this.msgIds.length > 500) {
205
+ this.msgIds.shift();
206
+ }
207
+ this.msgIds.push(remoteMsgId.toString());
208
+ const remoteSequence = reader.readInt();
209
+ reader.readInt(); // msgLen for the inner object, padding ignored
210
+ // We could read msg_len bytes and use those in a new reader to read
211
+ // the next TLObject without including the padding, but since the
212
+ // reader isn't used for anything else after this, it's unnecessary.
213
+ const obj = reader.tgReadObject();
214
+ return new core_1.TLMessage(remoteMsgId, remoteSequence, obj);
215
+ }
216
+ /**
217
+ * Generates a new unique message ID based on the current
218
+ * time (in ms) since epoch, applying a known time offset.
219
+ * @private
220
+ */
221
+ _getNewMsgId() {
222
+ const now = new Date().getTime() / 1000 + this.timeOffset;
223
+ const nanoseconds = Math.floor((now - Math.floor(now)) * 1e9);
224
+ let newMsgId = (0, big_integer_1.default)(Math.floor(now))
225
+ .shiftLeft((0, big_integer_1.default)(32))
226
+ .or((0, big_integer_1.default)(nanoseconds).shiftLeft((0, big_integer_1.default)(2)));
227
+ if (this._lastMsgId.greaterOrEquals(newMsgId)) {
228
+ newMsgId = this._lastMsgId.add((0, big_integer_1.default)(4));
229
+ }
230
+ this._lastMsgId = newMsgId;
231
+ return newMsgId;
232
+ }
233
+ /**
234
+ * Updates the time offset to the correct
235
+ * one given a known valid message ID.
236
+ * @param correctMsgId {BigInteger}
237
+ */
238
+ updateTimeOffset(correctMsgId) {
239
+ const bad = this._getNewMsgId();
240
+ const old = this.timeOffset;
241
+ const now = Math.floor(new Date().getTime() / 1000);
242
+ const correct = correctMsgId.shiftRight((0, big_integer_1.default)(32)).toJSNumber();
243
+ this.timeOffset = correct - now;
244
+ if (this.timeOffset !== old) {
245
+ this._lastMsgId = big_integer_1.default.zero;
246
+ this._log.debug(`Updated time offset (old offset ${old}, bad ${bad}, good ${correctMsgId}, new ${this.timeOffset})`);
247
+ }
248
+ return this.timeOffset;
249
+ }
250
+ /**
251
+ * Generates the next sequence number depending on whether
252
+ * it should be for a content-related query or not.
253
+ * @param contentRelated
254
+ * @private
255
+ */
256
+ _getSeqNo(contentRelated) {
257
+ if (contentRelated) {
258
+ const result = this._sequence * 2 + 1;
259
+ this._sequence += 1;
260
+ return result;
261
+ }
262
+ else {
263
+ return this._sequence * 2;
264
+ }
265
+ }
266
+ }
267
+ exports.MTProtoState = MTProtoState;
@@ -0,0 +1,18 @@
1
+ import bigInt from "big-integer";
2
+ import Deferred from "../extensions/Deferred";
3
+ import { Api } from "../tl";
4
+ export declare class RequestState {
5
+ containerId?: bigInt.BigInteger;
6
+ msgId?: bigInt.BigInteger;
7
+ request: any;
8
+ data: Buffer;
9
+ after: any;
10
+ result: undefined;
11
+ finished: Deferred;
12
+ promise: Promise<unknown> | undefined;
13
+ resolve: (value?: any) => void;
14
+ reject: (reason?: any) => void;
15
+ constructor(request: Api.AnyRequest | Api.MsgsAck | Api.MsgsStateInfo);
16
+ isReady(): any;
17
+ resetPromise(): void;
18
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RequestState = void 0;
7
+ const Deferred_1 = __importDefault(require("../extensions/Deferred"));
8
+ class RequestState {
9
+ constructor(request) {
10
+ this.containerId = undefined;
11
+ this.msgId = undefined;
12
+ this.request = request;
13
+ this.data = request.getBytes();
14
+ this.after = undefined;
15
+ this.result = undefined;
16
+ this.finished = new Deferred_1.default();
17
+ this.resetPromise();
18
+ }
19
+ isReady() {
20
+ if (!this.after) {
21
+ return true;
22
+ }
23
+ return this.after.finished.promise;
24
+ }
25
+ resetPromise() {
26
+ var _a;
27
+ // Prevent stuck await
28
+ (_a = this.reject) === null || _a === void 0 ? void 0 : _a.call(this);
29
+ this.promise = new Promise((resolve, reject) => {
30
+ this.resolve = resolve;
31
+ this.reject = reject;
32
+ });
33
+ }
34
+ }
35
+ exports.RequestState = RequestState;
@@ -0,0 +1,69 @@
1
+ import { Logger, PromisedNetSockets, PromisedWebSockets } from "../../extensions";
2
+ import { AsyncQueue } from "../../extensions";
3
+ import { AbridgedPacketCodec } from "./TCPAbridged";
4
+ import { FullPacketCodec } from "./TCPFull";
5
+ import { ProxyInterface } from "./TCPMTProxy";
6
+ interface ConnectionInterfaceParams {
7
+ ip: string;
8
+ port: number;
9
+ dcId: number;
10
+ loggers: Logger;
11
+ proxy?: ProxyInterface;
12
+ socket: typeof PromisedNetSockets | typeof PromisedWebSockets;
13
+ testServers: boolean;
14
+ }
15
+ /**
16
+ * The `Connection` class is a wrapper around ``asyncio.open_connection``.
17
+ *
18
+ * Subclasses will implement different transport modes as atomic operations,
19
+ * which this class eases doing since the exposed interface simply puts and
20
+ * gets complete data payloads to and from queues.
21
+ *
22
+ * The only error that will raise from send and receive methods is
23
+ * ``ConnectionError``, which will raise when attempting to send if
24
+ * the client is disconnected (includes remote disconnections).
25
+ */
26
+ declare class Connection {
27
+ PacketCodecClass?: typeof AbridgedPacketCodec | typeof FullPacketCodec;
28
+ readonly _ip: string;
29
+ readonly _port: number;
30
+ _dcId: number;
31
+ _log: Logger;
32
+ _proxy?: ProxyInterface;
33
+ _connected: boolean;
34
+ private _sendTask?;
35
+ private _recvTask?;
36
+ protected _codec: any;
37
+ protected _obfuscation: any;
38
+ _sendArray: AsyncQueue;
39
+ _recvArray: AsyncQueue;
40
+ private _abortController;
41
+ socket: PromisedNetSockets | PromisedWebSockets;
42
+ _testServers: boolean;
43
+ constructor({ ip, port, dcId, loggers, proxy, socket, testServers, }: ConnectionInterfaceParams);
44
+ _connect(): Promise<void>;
45
+ connect(): Promise<void>;
46
+ disconnect(): Promise<void>;
47
+ send(data: Buffer): Promise<void>;
48
+ recv(): Promise<any>;
49
+ _sendLoop(): Promise<void>;
50
+ isConnected(): boolean;
51
+ _recvLoop(): Promise<void>;
52
+ _initConn(): Promise<void>;
53
+ _send(data: Buffer): Promise<void>;
54
+ _recv(): Promise<any>;
55
+ toString(): string;
56
+ }
57
+ declare class ObfuscatedConnection extends Connection {
58
+ ObfuscatedIO: any;
59
+ _initConn(): Promise<void>;
60
+ _send(data: Buffer): Promise<void>;
61
+ _recv(): Promise<any>;
62
+ }
63
+ declare class PacketCodec {
64
+ private _conn;
65
+ constructor(connection: Buffer);
66
+ encodePacket(data: Buffer): void;
67
+ readPacket(reader: PromisedNetSockets | PromisedWebSockets): Promise<Buffer>;
68
+ }
69
+ export { Connection, PacketCodec, ObfuscatedConnection };
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObfuscatedConnection = exports.PacketCodec = exports.Connection = void 0;
4
+ const extensions_1 = require("../../extensions");
5
+ /**
6
+ * The `Connection` class is a wrapper around ``asyncio.open_connection``.
7
+ *
8
+ * Subclasses will implement different transport modes as atomic operations,
9
+ * which this class eases doing since the exposed interface simply puts and
10
+ * gets complete data payloads to and from queues.
11
+ *
12
+ * The only error that will raise from send and receive methods is
13
+ * ``ConnectionError``, which will raise when attempting to send if
14
+ * the client is disconnected (includes remote disconnections).
15
+ */
16
+ class Connection {
17
+ constructor({ ip, port, dcId, loggers, proxy, socket, testServers, }) {
18
+ this._ip = ip;
19
+ this._port = port;
20
+ this._dcId = dcId;
21
+ this._log = loggers;
22
+ this._proxy = proxy;
23
+ this._connected = false;
24
+ this._sendTask = undefined;
25
+ this._recvTask = undefined;
26
+ this._codec = undefined;
27
+ this._obfuscation = undefined; // TcpObfuscated and MTProxy
28
+ this._sendArray = new extensions_1.AsyncQueue();
29
+ this._recvArray = new extensions_1.AsyncQueue();
30
+ this._abortController = new AbortController();
31
+ this.socket = new socket(proxy);
32
+ this._testServers = testServers;
33
+ }
34
+ async _connect() {
35
+ this._log.debug("Connecting");
36
+ this._codec = new this.PacketCodecClass(this);
37
+ await this.socket.connect(this._port, this._ip, this._testServers);
38
+ this._log.debug("Finished connecting");
39
+ // await this.socket.connect({host: this._ip, port: this._port});
40
+ await this._initConn();
41
+ }
42
+ async connect() {
43
+ // Reset abort controller to have a fresh signal
44
+ this._abortController = new AbortController();
45
+ await this._connect();
46
+ this._connected = true;
47
+ if (!this._sendTask) {
48
+ this._sendTask = this._sendLoop();
49
+ }
50
+ this._recvTask = this._recvLoop();
51
+ }
52
+ async disconnect() {
53
+ if (!this._connected) {
54
+ return;
55
+ }
56
+ this._connected = false;
57
+ // Signal abort to any pending operations
58
+ this._abortController.abort();
59
+ void this._recvArray.push(undefined);
60
+ await this.socket.close();
61
+ }
62
+ async send(data) {
63
+ if (!this._connected) {
64
+ throw new Error("Not connected");
65
+ }
66
+ await this._sendArray.push(data);
67
+ }
68
+ async recv() {
69
+ while (this._connected) {
70
+ const result = await this._recvArray.pop();
71
+ // null = sentinel value = keep trying
72
+ if (result) {
73
+ return result;
74
+ }
75
+ }
76
+ throw new Error("Not connected");
77
+ }
78
+ async _sendLoop() {
79
+ try {
80
+ while (this._connected) {
81
+ const data = await this._sendArray.pop();
82
+ if (!data) {
83
+ this._sendTask = undefined;
84
+ return;
85
+ }
86
+ await this._send(data);
87
+ }
88
+ }
89
+ catch (e) {
90
+ this._log.info("The server closed the connection while sending");
91
+ }
92
+ }
93
+ isConnected() {
94
+ return this._connected;
95
+ }
96
+ async _recvLoop() {
97
+ let data;
98
+ while (this._connected) {
99
+ try {
100
+ data = await this._recv();
101
+ if (!data) {
102
+ throw new Error("no data received");
103
+ }
104
+ }
105
+ catch (e) {
106
+ this._log.info("connection closed");
107
+ // await this._recvArray.push()
108
+ this.disconnect();
109
+ return;
110
+ }
111
+ await this._recvArray.push(data);
112
+ }
113
+ }
114
+ async _initConn() {
115
+ if (this._codec.tag) {
116
+ await this.socket.write(this._codec.tag);
117
+ }
118
+ }
119
+ async _send(data) {
120
+ const encodedPacket = this._codec.encodePacket(data);
121
+ this.socket.write(encodedPacket);
122
+ }
123
+ async _recv() {
124
+ return await this._codec.readPacket(this.socket);
125
+ }
126
+ toString() {
127
+ return `${this._ip}:${this._port}/${this.constructor.name.replace("Connection", "")}`;
128
+ }
129
+ }
130
+ exports.Connection = Connection;
131
+ class ObfuscatedConnection extends Connection {
132
+ constructor() {
133
+ super(...arguments);
134
+ this.ObfuscatedIO = undefined;
135
+ }
136
+ async _initConn() {
137
+ this._obfuscation = new this.ObfuscatedIO(this);
138
+ await this._obfuscation.initHeader();
139
+ this.socket.write(this._obfuscation.header);
140
+ }
141
+ async _send(data) {
142
+ this._obfuscation.write(this._codec.encodePacket(data));
143
+ }
144
+ async _recv() {
145
+ return await this._codec.readPacket(this._obfuscation);
146
+ }
147
+ }
148
+ exports.ObfuscatedConnection = ObfuscatedConnection;
149
+ class PacketCodec {
150
+ constructor(connection) {
151
+ this._conn = connection;
152
+ }
153
+ encodePacket(data) {
154
+ throw new Error("Not Implemented");
155
+ // Override
156
+ }
157
+ async readPacket(reader) {
158
+ // override
159
+ throw new Error("Not Implemented");
160
+ }
161
+ }
162
+ exports.PacketCodec = PacketCodec;
@@ -0,0 +1,19 @@
1
+ import { Connection, PacketCodec } from "./Connection";
2
+ import type { PromisedNetSockets, PromisedWebSockets } from "../../extensions";
3
+ export declare class AbridgedPacketCodec extends PacketCodec {
4
+ static tag: Buffer<ArrayBuffer>;
5
+ static obfuscateTag: Buffer<ArrayBuffer>;
6
+ private tag;
7
+ obfuscateTag: Buffer;
8
+ constructor(props: any);
9
+ encodePacket(data: Buffer): Buffer<ArrayBuffer>;
10
+ readPacket(reader: PromisedNetSockets | PromisedWebSockets): Promise<Buffer>;
11
+ }
12
+ /**
13
+ * This is the mode with the lowest overhead, as it will
14
+ * only require 1 byte if the packet length is less than
15
+ * 508 bytes (127 << 2, which is very common).
16
+ */
17
+ export declare class ConnectionTCPAbridged extends Connection {
18
+ PacketCodecClass: typeof AbridgedPacketCodec;
19
+ }