@mtkruto/node 0.0.822 → 0.0.824
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/client/client.d.ts +12 -6
- package/esm/client/client.js +193 -59
- package/esm/client/client_abstract.d.ts +2 -1
- package/esm/client/client_abstract.js +1 -0
- package/esm/constants.d.ts +4 -0
- package/esm/constants.js +4 -0
- package/esm/mod.d.ts +4 -3
- package/esm/mod.js +4 -3
- package/esm/storage/storage.d.ts +23 -0
- package/esm/storage/storage.js +98 -0
- package/esm/storage/storage_local_storage.d.ts +9 -0
- package/esm/storage/storage_local_storage.js +36 -0
- package/esm/storage/storage_memory.d.ts +8 -0
- package/esm/storage/storage_memory.js +25 -0
- package/esm/storage/storage_session_storage.d.ts +9 -0
- package/esm/storage/storage_session_storage.js +36 -0
- package/package.json +1 -1
- package/script/client/client.d.ts +12 -6
- package/script/client/client.js +191 -57
- package/script/client/client_abstract.d.ts +2 -1
- package/script/client/client_abstract.js +1 -0
- package/script/constants.d.ts +4 -0
- package/script/constants.js +5 -1
- package/script/mod.d.ts +4 -3
- package/script/mod.js +4 -3
- package/script/storage/storage.d.ts +23 -0
- package/script/storage/storage.js +102 -0
- package/script/storage/storage_local_storage.d.ts +9 -0
- package/script/storage/storage_local_storage.js +40 -0
- package/script/storage/storage_memory.d.ts +8 -0
- package/script/storage/storage_memory.js +29 -0
- package/script/storage/storage_session_storage.d.ts +9 -0
- package/script/storage/storage_session_storage.js +40 -0
- package/esm/session/session.d.ts +0 -12
- package/esm/session/session.js +0 -36
- package/esm/session/session_local_storage.d.ts +0 -7
- package/esm/session/session_local_storage.js +0 -26
- package/esm/session/session_memory.d.ts +0 -5
- package/esm/session/session_memory.js +0 -5
- package/script/session/session.d.ts +0 -12
- package/script/session/session.js +0 -40
- package/script/session/session_local_storage.d.ts +0 -7
- package/script/session/session_local_storage.js +0 -30
- package/script/session/session_memory.d.ts +0 -5
- package/script/session/session_memory.js +0 -9
package/esm/client/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { MaybePromise } from "../types.js";
|
|
|
2
2
|
import * as types from "../tl/2_types.js";
|
|
3
3
|
import * as functions from "../tl/3_functions.js";
|
|
4
4
|
import { ClientAbstract } from "./client_abstract.js";
|
|
5
|
-
import {
|
|
5
|
+
import { Storage } from "../storage/storage.js";
|
|
6
6
|
import { DC, TransportProvider } from "../transport/transport_provider.js";
|
|
7
7
|
export declare const restartAuth: unique symbol;
|
|
8
8
|
export interface AuthorizeUserParams<S = string> {
|
|
@@ -42,9 +42,10 @@ export interface ClientParams {
|
|
|
42
42
|
systemVersion?: string;
|
|
43
43
|
}
|
|
44
44
|
export declare class Client extends ClientAbstract {
|
|
45
|
-
readonly
|
|
45
|
+
readonly storage: Storage;
|
|
46
46
|
readonly apiId: number;
|
|
47
47
|
readonly apiHash: string;
|
|
48
|
+
private auth;
|
|
48
49
|
private sessionId;
|
|
49
50
|
private state;
|
|
50
51
|
private promises;
|
|
@@ -59,20 +60,21 @@ export declare class Client extends ClientAbstract {
|
|
|
59
60
|
/**
|
|
60
61
|
* Constructs the client.
|
|
61
62
|
*
|
|
62
|
-
* @param
|
|
63
|
+
* @param storage The storage provider to use. Defaults to memory storage.
|
|
63
64
|
* @param apiId App's API ID from [my.telegram.org](https://my.telegram.org/apps). Defaults to 0 (unset).
|
|
64
65
|
* @param apiHash App's API hash from [my.telegram.org/apps](https://my.telegram.org/apps). Default to empty string (unset).
|
|
65
66
|
* @param params Other parameters.
|
|
66
67
|
*/
|
|
67
|
-
constructor(
|
|
68
|
-
private
|
|
68
|
+
constructor(storage?: Storage, apiId?: number, apiHash?: string, params?: ClientParams);
|
|
69
|
+
private storageInited;
|
|
69
70
|
/**
|
|
70
71
|
* Sets the DC and resets the auth key stored in the session provider
|
|
71
72
|
* if the stored DC was not the same as the `dc` parameter.
|
|
72
73
|
*
|
|
73
74
|
* @param dc The DC to change to.
|
|
74
75
|
*/
|
|
75
|
-
setDc(dc: DC): void
|
|
76
|
+
setDc(dc: DC): Promise<void>;
|
|
77
|
+
private setAuth;
|
|
76
78
|
/**
|
|
77
79
|
* Loads the session if `setDc` was not called, initializes and connnects
|
|
78
80
|
* a `ClientPlain` to generate auth key if there was none, and connects the client.
|
|
@@ -111,4 +113,8 @@ export declare class Client extends ClientAbstract {
|
|
|
111
113
|
* Alias for `invoke` with its second parameter being `true`.
|
|
112
114
|
*/
|
|
113
115
|
send<T extends (functions.Function<unknown> | types.Type) = functions.Function<unknown>>(function_: T): Promise<void>;
|
|
116
|
+
private processChats;
|
|
117
|
+
private processUsers;
|
|
118
|
+
private processUpdates;
|
|
119
|
+
getInputPeer(id: string | number): Promise<types.InputPeerChat | types.InputPeerUser | types.InputPeerChannel>;
|
|
114
120
|
}
|
package/esm/client/client.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { gunzip } from "../deps.js";
|
|
2
|
-
import { ackThreshold, DEFAULT_APP_VERSION, DEFAULT_DEVICE_MODEL, DEFAULT_LANG_CODE, DEFAULT_LANG_PACK, DEFAULT_SYSTEM_LANG_CODE, DEFAULT_SYSTEM_VERSION, LAYER } from "../constants.js";
|
|
3
|
-
import { getRandomBigInt } from "../utilities/0_bigint.js";
|
|
2
|
+
import { ackThreshold, DEFAULT_APP_VERSION, DEFAULT_DEVICE_MODEL, DEFAULT_INITIAL_DC, DEFAULT_LANG_CODE, DEFAULT_LANG_PACK, DEFAULT_SYSTEM_LANG_CODE, DEFAULT_SYSTEM_VERSION, LAYER, MAX_CHANNEL_ID, MAX_CHAT_ID, USERNAME_TTL, ZERO_CHANNEL_ID } from "../constants.js";
|
|
3
|
+
import { bigIntFromBuffer, getRandomBigInt } from "../utilities/0_bigint.js";
|
|
4
4
|
import { decryptMessage, encryptMessage, getMessageId } from "../utilities/1_message.js";
|
|
5
5
|
import { checkPassword } from "../utilities/1_password.js";
|
|
6
|
+
import { as } from "../tl/1_tl_object.js";
|
|
6
7
|
import * as types from "../tl/2_types.js";
|
|
7
8
|
import * as functions from "../tl/3_functions.js";
|
|
8
9
|
import { TLReader } from "../tl/3_tl_reader.js";
|
|
@@ -11,24 +12,25 @@ import { Message } from "../tl/5_message.js";
|
|
|
11
12
|
import { MessageContainer } from "../tl/6_message_container.js";
|
|
12
13
|
import { ClientAbstract } from "./client_abstract.js";
|
|
13
14
|
import { ClientPlain } from "./client_plain.js";
|
|
14
|
-
import {
|
|
15
|
+
import { StorageMemory } from "../storage/storage_memory.js";
|
|
16
|
+
import { sha1 } from "../utilities/0_hash.js";
|
|
15
17
|
export const restartAuth = Symbol();
|
|
16
18
|
export class Client extends ClientAbstract {
|
|
17
19
|
/**
|
|
18
20
|
* Constructs the client.
|
|
19
21
|
*
|
|
20
|
-
* @param
|
|
22
|
+
* @param storage The storage provider to use. Defaults to memory storage.
|
|
21
23
|
* @param apiId App's API ID from [my.telegram.org](https://my.telegram.org/apps). Defaults to 0 (unset).
|
|
22
24
|
* @param apiHash App's API hash from [my.telegram.org/apps](https://my.telegram.org/apps). Default to empty string (unset).
|
|
23
25
|
* @param params Other parameters.
|
|
24
26
|
*/
|
|
25
|
-
constructor(
|
|
27
|
+
constructor(storage = new StorageMemory(), apiId = 0, apiHash = "", params) {
|
|
26
28
|
super(params?.transportProvider);
|
|
27
|
-
Object.defineProperty(this, "
|
|
29
|
+
Object.defineProperty(this, "storage", {
|
|
28
30
|
enumerable: true,
|
|
29
31
|
configurable: true,
|
|
30
32
|
writable: true,
|
|
31
|
-
value:
|
|
33
|
+
value: storage
|
|
32
34
|
});
|
|
33
35
|
Object.defineProperty(this, "apiId", {
|
|
34
36
|
enumerable: true,
|
|
@@ -42,6 +44,12 @@ export class Client extends ClientAbstract {
|
|
|
42
44
|
writable: true,
|
|
43
45
|
value: apiHash
|
|
44
46
|
});
|
|
47
|
+
Object.defineProperty(this, "auth", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
writable: true,
|
|
51
|
+
value: null
|
|
52
|
+
});
|
|
45
53
|
Object.defineProperty(this, "sessionId", {
|
|
46
54
|
enumerable: true,
|
|
47
55
|
configurable: true,
|
|
@@ -108,11 +116,11 @@ export class Client extends ClientAbstract {
|
|
|
108
116
|
writable: true,
|
|
109
117
|
value: void 0
|
|
110
118
|
});
|
|
111
|
-
Object.defineProperty(this, "
|
|
119
|
+
Object.defineProperty(this, "storageInited", {
|
|
112
120
|
enumerable: true,
|
|
113
121
|
configurable: true,
|
|
114
122
|
writable: true,
|
|
115
|
-
value:
|
|
123
|
+
value: false
|
|
116
124
|
});
|
|
117
125
|
this.appVersion = params?.appVersion ?? DEFAULT_APP_VERSION;
|
|
118
126
|
this.deviceModel = params?.deviceModel ?? DEFAULT_DEVICE_MODEL;
|
|
@@ -127,42 +135,57 @@ export class Client extends ClientAbstract {
|
|
|
127
135
|
*
|
|
128
136
|
* @param dc The DC to change to.
|
|
129
137
|
*/
|
|
130
|
-
setDc(dc) {
|
|
131
|
-
if (this.
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
async setDc(dc) {
|
|
139
|
+
if (!this.storageInited) {
|
|
140
|
+
await this.storage.init();
|
|
141
|
+
this.storageInited = true;
|
|
142
|
+
}
|
|
143
|
+
if (await this.storage.getDc() != dc) {
|
|
144
|
+
await this.storage.setDc(dc);
|
|
145
|
+
await this.storage.setAuthKey(null);
|
|
137
146
|
}
|
|
138
147
|
super.setDc(dc);
|
|
139
148
|
}
|
|
149
|
+
async setAuth(key) {
|
|
150
|
+
const hash = await sha1(key);
|
|
151
|
+
const id = bigIntFromBuffer(hash.slice(-8), true, false);
|
|
152
|
+
this.auth = { key, id };
|
|
153
|
+
}
|
|
140
154
|
/**
|
|
141
155
|
* Loads the session if `setDc` was not called, initializes and connnects
|
|
142
156
|
* a `ClientPlain` to generate auth key if there was none, and connects the client.
|
|
143
157
|
* Before establishing the connection, the session is saved.
|
|
144
158
|
*/
|
|
145
159
|
async connect() {
|
|
146
|
-
if (this.
|
|
147
|
-
await this.
|
|
148
|
-
this.
|
|
160
|
+
if (!this.storageInited) {
|
|
161
|
+
await this.storage.init();
|
|
162
|
+
this.storageInited = true;
|
|
149
163
|
}
|
|
150
|
-
|
|
164
|
+
const authKey = await this.storage.getAuthKey();
|
|
165
|
+
if (authKey == null) {
|
|
151
166
|
const plain = new ClientPlain(this.transportProvider);
|
|
152
|
-
|
|
153
|
-
|
|
167
|
+
const dc = await this.storage.getDc();
|
|
168
|
+
if (dc != null) {
|
|
169
|
+
plain.setDc(dc);
|
|
154
170
|
}
|
|
155
171
|
await plain.connect();
|
|
156
172
|
const { authKey, salt } = await plain.createAuthKey();
|
|
157
173
|
await plain.disconnect();
|
|
174
|
+
await this.storage.setAuthKey(authKey);
|
|
175
|
+
await this.setAuth(authKey);
|
|
158
176
|
this.state.salt = salt;
|
|
159
|
-
this.session.authKey = authKey;
|
|
160
177
|
}
|
|
161
|
-
|
|
162
|
-
this.
|
|
178
|
+
else {
|
|
179
|
+
await this.setAuth(authKey);
|
|
180
|
+
}
|
|
181
|
+
const dc = await this.storage.getDc();
|
|
182
|
+
if (dc != null) {
|
|
183
|
+
await this.setDc(dc);
|
|
163
184
|
}
|
|
164
|
-
await this.session.save();
|
|
165
185
|
await super.connect();
|
|
186
|
+
if (dc == null) {
|
|
187
|
+
await this.storage.setDc(DEFAULT_INITIAL_DC);
|
|
188
|
+
}
|
|
166
189
|
// logger().debug("Client connected");
|
|
167
190
|
this.receiveLoop();
|
|
168
191
|
this.pingLoop();
|
|
@@ -204,6 +227,36 @@ export class Client extends ClientAbstract {
|
|
|
204
227
|
systemLangCode: this.systemLangCode,
|
|
205
228
|
systemVersion: this.systemVersion,
|
|
206
229
|
}));
|
|
230
|
+
const handlePassword = async (err) => {
|
|
231
|
+
params = params;
|
|
232
|
+
if (err instanceof types.RPCError && err.errorMessage == "SESSION_PASSWORD_NEEDED") {
|
|
233
|
+
while (true) {
|
|
234
|
+
const ap = await this.invoke(new functions.AccountGetPassword());
|
|
235
|
+
if (ap.currentAlgo instanceof types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) {
|
|
236
|
+
try {
|
|
237
|
+
const password = typeof params.password === "string" ? params.password : await params.password();
|
|
238
|
+
const input = await checkPassword(password, ap);
|
|
239
|
+
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
if (err instanceof types.RPCError && err.errorMessage == "PASSWORD_HASH_INVALID") {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
throw err;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
throw new Error(`Handling ${ap.currentAlgo?.constructor.name} not implemented`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
};
|
|
207
260
|
try {
|
|
208
261
|
await this.invoke(new functions.UpdatesGetState());
|
|
209
262
|
return;
|
|
@@ -261,33 +314,7 @@ export class Client extends ClientAbstract {
|
|
|
261
314
|
}
|
|
262
315
|
}
|
|
263
316
|
catch (err) {
|
|
264
|
-
|
|
265
|
-
while (true) {
|
|
266
|
-
const ap = await this.invoke(new functions.AccountGetPassword());
|
|
267
|
-
if (ap.currentAlgo instanceof types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) {
|
|
268
|
-
try {
|
|
269
|
-
const password = typeof params.password === "string" ? params.password : await params.password();
|
|
270
|
-
const input = await checkPassword(password, ap);
|
|
271
|
-
await this.invoke(new functions.AuthCheckPassword({ password: input }));
|
|
272
|
-
break;
|
|
273
|
-
}
|
|
274
|
-
catch (err) {
|
|
275
|
-
if (err instanceof types.RPCError && err.errorMessage == "PASSWORD_HASH_INVALID") {
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
279
|
-
throw err;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
throw new Error(`Handling ${ap.currentAlgo?.constructor.name} not implemented`);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
throw err;
|
|
290
|
-
}
|
|
317
|
+
await handlePassword(err);
|
|
291
318
|
}
|
|
292
319
|
}
|
|
293
320
|
catch (err) {
|
|
@@ -320,7 +347,7 @@ export class Client extends ClientAbstract {
|
|
|
320
347
|
await this.authorize(params);
|
|
321
348
|
}
|
|
322
349
|
else {
|
|
323
|
-
|
|
350
|
+
await handlePassword(err);
|
|
324
351
|
}
|
|
325
352
|
}
|
|
326
353
|
else {
|
|
@@ -329,7 +356,7 @@ export class Client extends ClientAbstract {
|
|
|
329
356
|
}
|
|
330
357
|
}
|
|
331
358
|
async receiveLoop() {
|
|
332
|
-
if (!this.
|
|
359
|
+
if (!this.auth) {
|
|
333
360
|
throw new Error("Not connected");
|
|
334
361
|
}
|
|
335
362
|
while (this.connected) {
|
|
@@ -351,7 +378,7 @@ export class Client extends ClientAbstract {
|
|
|
351
378
|
}
|
|
352
379
|
let decrypted;
|
|
353
380
|
try {
|
|
354
|
-
decrypted = await decryptMessage(buffer, this.
|
|
381
|
+
decrypted = await decryptMessage(buffer, this.auth.key, this.auth.id, this.sessionId);
|
|
355
382
|
}
|
|
356
383
|
catch (_err) {
|
|
357
384
|
// logger().error(`Failed to decrypt message: ${err}`);
|
|
@@ -365,7 +392,7 @@ export class Client extends ClientAbstract {
|
|
|
365
392
|
}
|
|
366
393
|
// logger().debug(`Received ${body.constructor.name}`);
|
|
367
394
|
if (body instanceof types.Updates) {
|
|
368
|
-
this.
|
|
395
|
+
this.processUpdates(body);
|
|
369
396
|
}
|
|
370
397
|
else if (message.body instanceof RPCResult) {
|
|
371
398
|
let result = message.body.result;
|
|
@@ -416,7 +443,7 @@ export class Client extends ClientAbstract {
|
|
|
416
443
|
}
|
|
417
444
|
}
|
|
418
445
|
async invoke(function_, noWait) {
|
|
419
|
-
if (!this.
|
|
446
|
+
if (!this.auth) {
|
|
420
447
|
throw new Error("Not connected");
|
|
421
448
|
}
|
|
422
449
|
let seqNo = this.state.seqNo * 2;
|
|
@@ -425,7 +452,7 @@ export class Client extends ClientAbstract {
|
|
|
425
452
|
this.state.seqNo++;
|
|
426
453
|
}
|
|
427
454
|
const message = new Message(getMessageId(), seqNo, function_);
|
|
428
|
-
await this.transport.send(await encryptMessage(message, this.
|
|
455
|
+
await this.transport.send(await encryptMessage(message, this.auth.key, this.auth.id, this.state.salt, this.sessionId));
|
|
429
456
|
// logger().debug(`Invoked ${function_.constructor.name}`);
|
|
430
457
|
if (noWait) {
|
|
431
458
|
return;
|
|
@@ -446,4 +473,111 @@ export class Client extends ClientAbstract {
|
|
|
446
473
|
send(function_) {
|
|
447
474
|
return this.invoke(function_, true);
|
|
448
475
|
}
|
|
476
|
+
async processChats(chats) {
|
|
477
|
+
for (const chat of chats) {
|
|
478
|
+
if (chat instanceof types.Channel && chat.accessHash) {
|
|
479
|
+
await this.storage.setChannelAccessHash(chat.id, chat.accessHash);
|
|
480
|
+
if (chat.username) {
|
|
481
|
+
await this.storage.updateUsernames("channel", chat.id, [chat.username]);
|
|
482
|
+
}
|
|
483
|
+
if (chat.usernames) {
|
|
484
|
+
await this.storage.updateUsernames("channel", chat.id, chat.usernames.map((v) => v[as](types.Username)).map((v) => v.username));
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
async processUsers(users) {
|
|
490
|
+
for (const user of users) {
|
|
491
|
+
if (user instanceof types.User && user.accessHash) {
|
|
492
|
+
await this.storage.setUserAccessHash(user.id, user.accessHash);
|
|
493
|
+
if (user.username) {
|
|
494
|
+
await this.storage.updateUsernames("user", user.id, [user.username]);
|
|
495
|
+
}
|
|
496
|
+
if (user.usernames) {
|
|
497
|
+
await this.storage.updateUsernames("user", user.id, user.usernames.map((v) => v[as](types.Username)).map((v) => v.username));
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
async processUpdates(updates) {
|
|
503
|
+
try {
|
|
504
|
+
await this.processChats(updates.chats);
|
|
505
|
+
await this.processUsers(updates.users);
|
|
506
|
+
for (const update of updates.updates) {
|
|
507
|
+
if (update instanceof types.UpdateUserName) {
|
|
508
|
+
await this.storage.updateUsernames("user", update.userId, update.usernames.map((v) => v[as](types.Username)).map((v) => v.username));
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
await this.updatesHandler?.(this, updates);
|
|
512
|
+
}
|
|
513
|
+
catch (err) {
|
|
514
|
+
console.error("Error processing updates:", err);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
async getInputPeer(id) {
|
|
518
|
+
if (typeof id === "string") {
|
|
519
|
+
if (!id.startsWith("@")) {
|
|
520
|
+
throw new Error("Expected username to start with @");
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
id = id.slice(1);
|
|
524
|
+
if (!id) {
|
|
525
|
+
throw new Error("Empty username");
|
|
526
|
+
}
|
|
527
|
+
let userId = 0n;
|
|
528
|
+
let channelId = 0n;
|
|
529
|
+
const maybeUsername = await this.storage.getUsername(id);
|
|
530
|
+
if (maybeUsername != null && Date.now() - maybeUsername[2].getTime() < USERNAME_TTL) {
|
|
531
|
+
const [type, id] = maybeUsername;
|
|
532
|
+
if (type == "user") {
|
|
533
|
+
userId = id;
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
channelId = id;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
const resolved = await this.invoke(new functions.ContactsResolveUsername({ username: id }));
|
|
541
|
+
await this.processChats(resolved.chats);
|
|
542
|
+
await this.processUsers(resolved.users);
|
|
543
|
+
if (resolved.peer instanceof types.PeerUser) {
|
|
544
|
+
userId = resolved.peer.userId;
|
|
545
|
+
}
|
|
546
|
+
else if (resolved.peer instanceof types.PeerChannel) {
|
|
547
|
+
channelId = resolved.peer.channelId;
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
throw new Error("Unreachable");
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (userId) {
|
|
554
|
+
const accessHash = await this.storage.getUserAccessHash(userId);
|
|
555
|
+
return new types.InputPeerUser({ userId, accessHash: accessHash ?? 0n });
|
|
556
|
+
}
|
|
557
|
+
else if (channelId) {
|
|
558
|
+
const accessHash = await this.storage.getChannelAccessHash(channelId);
|
|
559
|
+
return new types.InputPeerChannel({ channelId, accessHash: accessHash ?? 0n });
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
throw new Error("Unreachable");
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else if (id > 0) {
|
|
567
|
+
const id_ = BigInt(id);
|
|
568
|
+
const accessHash = await this.storage.getUserAccessHash(id_);
|
|
569
|
+
return new types.InputPeerUser({ userId: id_, accessHash: accessHash ?? 0n });
|
|
570
|
+
}
|
|
571
|
+
else if (-MAX_CHAT_ID <= id) {
|
|
572
|
+
return new types.InputPeerChat({ chatId: BigInt(Math.abs(id)) });
|
|
573
|
+
}
|
|
574
|
+
else if (ZERO_CHANNEL_ID - MAX_CHANNEL_ID <= id && id != ZERO_CHANNEL_ID) {
|
|
575
|
+
const id_ = BigInt(Math.abs(id - ZERO_CHANNEL_ID));
|
|
576
|
+
const accessHash = await this.storage.getChannelAccessHash(id_);
|
|
577
|
+
return new types.InputPeerChannel({ channelId: id_, accessHash: accessHash ?? 0n });
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
throw new Error("ID format unknown or not implemented");
|
|
581
|
+
}
|
|
582
|
+
}
|
|
449
583
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Connection } from "../connection/connection.js";
|
|
2
2
|
import { Transport } from "../transport/transport.js";
|
|
3
3
|
import { DC } from "../transport/transport_provider.js";
|
|
4
|
+
import { MaybePromise } from "../types.js";
|
|
4
5
|
export declare abstract class ClientAbstract {
|
|
5
6
|
protected transportProvider: import("../transport/transport_provider.js").TransportProvider;
|
|
6
7
|
protected connection: Connection;
|
|
@@ -9,7 +10,7 @@ export declare abstract class ClientAbstract {
|
|
|
9
10
|
protected connected: boolean;
|
|
10
11
|
constructor(transportProvider?: import("../transport/transport_provider.js").TransportProvider);
|
|
11
12
|
get dcId(): number;
|
|
12
|
-
setDc(dc: DC): void
|
|
13
|
+
setDc(dc: DC): MaybePromise<void>;
|
|
13
14
|
connect(): Promise<void>;
|
|
14
15
|
reconnect(dc?: DC): Promise<void>;
|
|
15
16
|
disconnect(): Promise<void>;
|
|
@@ -41,6 +41,7 @@ export class ClientAbstract {
|
|
|
41
41
|
get dcId() {
|
|
42
42
|
return this._dcId;
|
|
43
43
|
}
|
|
44
|
+
// MaybePromise since `Client` has to deal with `Storage.set()`
|
|
44
45
|
setDc(dc) {
|
|
45
46
|
const { connection, transport, dcId } = this.transportProvider({ dc, cdn: false });
|
|
46
47
|
this.connection = connection;
|
package/esm/constants.d.ts
CHANGED
|
@@ -10,3 +10,7 @@ export declare const DEFAULT_LANG_CODE = "en";
|
|
|
10
10
|
export declare const DEFAULT_LANG_PACK = "";
|
|
11
11
|
export declare const DEFAULT_SYSTEM_LANG_CODE = "en";
|
|
12
12
|
export declare const DEFAULT_SYSTEM_VERSION = "1.0";
|
|
13
|
+
export declare const USERNAME_TTL = 86400;
|
|
14
|
+
export declare const MAX_CHAT_ID = 999999999999;
|
|
15
|
+
export declare const MAX_CHANNEL_ID = 997852516352;
|
|
16
|
+
export declare const ZERO_CHANNEL_ID = -1000000000000;
|
package/esm/constants.js
CHANGED
|
@@ -68,3 +68,7 @@ export const DEFAULT_LANG_CODE = "en";
|
|
|
68
68
|
export const DEFAULT_LANG_PACK = "";
|
|
69
69
|
export const DEFAULT_SYSTEM_LANG_CODE = "en";
|
|
70
70
|
export const DEFAULT_SYSTEM_VERSION = "1.0";
|
|
71
|
+
export const USERNAME_TTL = 86400;
|
|
72
|
+
export const MAX_CHAT_ID = 999999999999;
|
|
73
|
+
export const MAX_CHANNEL_ID = 997852516352;
|
|
74
|
+
export const ZERO_CHANNEL_ID = -1000000000000;
|
package/esm/mod.d.ts
CHANGED
|
@@ -12,9 +12,10 @@ export * from "./tl/5_message.js";
|
|
|
12
12
|
export * from "./tl/6_message_container.js";
|
|
13
13
|
export * from "./client/client_plain.js";
|
|
14
14
|
export * from "./client/client.js";
|
|
15
|
-
export * from "./
|
|
16
|
-
export * from "./
|
|
17
|
-
export * from "./
|
|
15
|
+
export * from "./storage/storage.js";
|
|
16
|
+
export * from "./storage/storage_memory.js";
|
|
17
|
+
export * from "./storage/storage_local_storage.js";
|
|
18
|
+
export * from "./storage/storage_session_storage.js";
|
|
18
19
|
export * from "./transport/transport_abridged.js";
|
|
19
20
|
export * from "./transport/transport_intermediate.js";
|
|
20
21
|
export * from "./transport/transport.js";
|
package/esm/mod.js
CHANGED
|
@@ -9,9 +9,10 @@ export * from "./tl/5_message.js";
|
|
|
9
9
|
export * from "./tl/6_message_container.js";
|
|
10
10
|
export * from "./client/client_plain.js";
|
|
11
11
|
export * from "./client/client.js";
|
|
12
|
-
export * from "./
|
|
13
|
-
export * from "./
|
|
14
|
-
export * from "./
|
|
12
|
+
export * from "./storage/storage.js";
|
|
13
|
+
export * from "./storage/storage_memory.js";
|
|
14
|
+
export * from "./storage/storage_local_storage.js";
|
|
15
|
+
export * from "./storage/storage_session_storage.js";
|
|
15
16
|
export * from "./transport/transport_abridged.js";
|
|
16
17
|
export * from "./transport/transport_intermediate.js";
|
|
17
18
|
export * from "./transport/transport.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MaybePromise } from "../types.js";
|
|
2
|
+
import { DC } from "../transport/transport_provider.js";
|
|
3
|
+
export declare abstract class Storage {
|
|
4
|
+
private _authKeyId;
|
|
5
|
+
abstract init(): MaybePromise<void>;
|
|
6
|
+
abstract set(key: string, value: string | null): MaybePromise<void>;
|
|
7
|
+
abstract get(key: string): MaybePromise<string | null>;
|
|
8
|
+
setDc(dc: DC | null): MaybePromise<void>;
|
|
9
|
+
getDc(): Promise<DC | null>;
|
|
10
|
+
private resetAuthKeyId;
|
|
11
|
+
getAuthKey(): Promise<Uint8Array | null>;
|
|
12
|
+
setAuthKey(authKey: Uint8Array | null): Promise<void>;
|
|
13
|
+
get authKeyId(): bigint | null;
|
|
14
|
+
private readonly channelAccessHash__;
|
|
15
|
+
setChannelAccessHash(id: bigint, accessHash: bigint): MaybePromise<void>;
|
|
16
|
+
getChannelAccessHash(id: bigint): Promise<bigint | null>;
|
|
17
|
+
private readonly userAccessHash__;
|
|
18
|
+
setUserAccessHash(id: bigint, accessHash: bigint): MaybePromise<void>;
|
|
19
|
+
getUserAccessHash(id: bigint): Promise<bigint | null>;
|
|
20
|
+
private readonly username__;
|
|
21
|
+
updateUsernames(type: "user" | "channel", id: bigint, usernames: string[]): Promise<void>;
|
|
22
|
+
getUsername(username: string): Promise<readonly ["user" | "channel", bigint, Date] | null>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { sha1 } from "../utilities/0_hash.js";
|
|
2
|
+
import { bigIntFromBuffer } from "../utilities/0_bigint.js";
|
|
3
|
+
export class Storage {
|
|
4
|
+
constructor() {
|
|
5
|
+
Object.defineProperty(this, "_authKeyId", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
writable: true,
|
|
9
|
+
value: null
|
|
10
|
+
});
|
|
11
|
+
Object.defineProperty(this, "channelAccessHash__", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: "channelAccessHash__"
|
|
16
|
+
});
|
|
17
|
+
Object.defineProperty(this, "userAccessHash__", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: "userAccessHash__"
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "username__", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: "username__"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
setDc(dc) {
|
|
31
|
+
return this.set("dc", dc);
|
|
32
|
+
}
|
|
33
|
+
async getDc() {
|
|
34
|
+
return await this.get("dc");
|
|
35
|
+
}
|
|
36
|
+
async resetAuthKeyId(authKey) {
|
|
37
|
+
if (authKey != null) {
|
|
38
|
+
this._authKeyId = await sha1(authKey).then((hash) => bigIntFromBuffer(hash.slice(-8), true, false));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this._authKeyId = null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async getAuthKey() {
|
|
45
|
+
const authKey_ = await this.get("authKey");
|
|
46
|
+
const authKey = authKey_ == null ? null : new Uint8Array(authKey_.split(/([0-9a-f]{2})/).filter((v) => v).map((v) => parseInt(v, 16)));
|
|
47
|
+
await this.resetAuthKeyId(authKey);
|
|
48
|
+
return authKey;
|
|
49
|
+
}
|
|
50
|
+
async setAuthKey(authKey) {
|
|
51
|
+
await this.set("authKey", authKey == null ? null : Array.from(authKey).map((v) => v.toString(16)).map((v) => v.padStart(2, "0")).join(""));
|
|
52
|
+
await this.resetAuthKeyId(authKey);
|
|
53
|
+
}
|
|
54
|
+
get authKeyId() {
|
|
55
|
+
return this._authKeyId;
|
|
56
|
+
}
|
|
57
|
+
setChannelAccessHash(id, accessHash) {
|
|
58
|
+
return this.set(`${this.channelAccessHash__}${id}`, String(accessHash));
|
|
59
|
+
}
|
|
60
|
+
async getChannelAccessHash(id) {
|
|
61
|
+
const accessHash = await this.get(`${this.channelAccessHash__}${id}`);
|
|
62
|
+
if (accessHash != null) {
|
|
63
|
+
return BigInt(accessHash);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
setUserAccessHash(id, accessHash) {
|
|
70
|
+
return this.set(`${this.userAccessHash__}${id}`, String(accessHash));
|
|
71
|
+
}
|
|
72
|
+
async getUserAccessHash(id) {
|
|
73
|
+
const accessHash = await this.get(`${this.userAccessHash__}${id}`);
|
|
74
|
+
if (accessHash != null) {
|
|
75
|
+
return BigInt(accessHash);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async updateUsernames(type, id, usernames) {
|
|
82
|
+
for (let username of usernames) {
|
|
83
|
+
username = username.toLowerCase();
|
|
84
|
+
await this.set(`${this.username__}${username}`, JSON.stringify([type, String(id), new Date()]));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async getUsername(username) {
|
|
88
|
+
username = username.toLowerCase();
|
|
89
|
+
const username_ = await this.get(`${this.username__}${username}`);
|
|
90
|
+
if (username_ != null) {
|
|
91
|
+
const [type, id, updatedAt] = JSON.parse(username_);
|
|
92
|
+
return [type, BigInt(id), new Date(updatedAt)];
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MaybePromise } from "../types.js";
|
|
2
|
+
import { Storage } from "./storage.js";
|
|
3
|
+
export declare class StorageLocalStorage extends Storage implements Storage {
|
|
4
|
+
private readonly prefix;
|
|
5
|
+
constructor(prefix: string);
|
|
6
|
+
init(): void;
|
|
7
|
+
get(key: string): string | null;
|
|
8
|
+
set(key: string, value: string | null): MaybePromise<void>;
|
|
9
|
+
}
|