@mtcute/core 0.22.3 → 0.23.1
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/client.cjs +1 -1
- package/client.js +1 -1
- package/highlevel/base.cjs +1 -0
- package/highlevel/base.js +1 -0
- package/highlevel/client.d.cts +7 -3
- package/highlevel/client.d.ts +7 -3
- package/highlevel/methods/auth/send-code.cjs +8 -2
- package/highlevel/methods/auth/send-code.d.cts +4 -2
- package/highlevel/methods/auth/send-code.d.ts +4 -2
- package/highlevel/methods/auth/send-code.js +8 -2
- package/highlevel/methods/auth/start.cjs +6 -1
- package/highlevel/methods/auth/start.d.cts +1 -1
- package/highlevel/methods/auth/start.d.ts +1 -1
- package/highlevel/methods/auth/start.js +6 -1
- package/highlevel/methods/chats/open-chat.cjs +1 -1
- package/highlevel/methods/chats/open-chat.js +1 -1
- package/highlevel/methods/dialogs/find-dialogs.cjs +3 -1
- package/highlevel/methods/dialogs/find-dialogs.js +3 -1
- package/highlevel/methods/dialogs/get-peer-dialogs.cjs +49 -11
- package/highlevel/methods/dialogs/get-peer-dialogs.d.cts +1 -1
- package/highlevel/methods/dialogs/get-peer-dialogs.d.ts +1 -1
- package/highlevel/methods/dialogs/get-peer-dialogs.js +49 -11
- package/highlevel/methods/files/normalize-input-file.d.cts +1 -0
- package/highlevel/methods/files/normalize-input-file.d.ts +1 -0
- package/highlevel/methods/files/normalize-input-media.cjs +13 -6
- package/highlevel/methods/files/normalize-input-media.d.cts +1 -0
- package/highlevel/methods/files/normalize-input-media.d.ts +1 -0
- package/highlevel/methods/files/normalize-input-media.js +13 -6
- package/highlevel/methods/files/upload-file.cjs +6 -3
- package/highlevel/methods/files/upload-file.d.cts +1 -0
- package/highlevel/methods/files/upload-file.d.ts +1 -0
- package/highlevel/methods/files/upload-file.js +6 -3
- package/highlevel/methods/messages/send-common.d.cts +1 -0
- package/highlevel/methods/messages/send-common.d.ts +1 -0
- package/highlevel/methods/messages/send-media-group.cjs +3 -2
- package/highlevel/methods/messages/send-media-group.js +3 -2
- package/highlevel/methods/messages/send-media.cjs +3 -2
- package/highlevel/methods/messages/send-media.js +3 -2
- package/highlevel/methods/messages/send-text.cjs +1 -1
- package/highlevel/methods/messages/send-text.js +1 -1
- package/highlevel/methods/users/resolve-peer-many.cjs +8 -43
- package/highlevel/methods/users/resolve-peer-many.js +9 -44
- package/highlevel/storage/service/peers.cjs +37 -9
- package/highlevel/storage/service/peers.d.cts +4 -0
- package/highlevel/storage/service/peers.d.ts +4 -0
- package/highlevel/storage/service/peers.js +38 -10
- package/highlevel/storage/storage.cjs +3 -0
- package/highlevel/storage/storage.d.cts +1 -0
- package/highlevel/storage/storage.d.ts +1 -0
- package/highlevel/storage/storage.js +3 -0
- package/highlevel/types/conversation.cjs +3 -4
- package/highlevel/types/conversation.js +3 -4
- package/highlevel/types/messages/message-action.cjs +11 -0
- package/highlevel/types/messages/message-action.d.cts +15 -1
- package/highlevel/types/messages/message-action.d.ts +15 -1
- package/highlevel/types/messages/message-action.js +11 -0
- package/highlevel/types/peers/full-user.cjs +8 -0
- package/highlevel/types/peers/full-user.d.cts +4 -0
- package/highlevel/types/peers/full-user.d.ts +4 -0
- package/highlevel/types/peers/full-user.js +8 -0
- package/highlevel/types/peers/peers-index.cjs +10 -0
- package/highlevel/types/peers/peers-index.d.cts +1 -0
- package/highlevel/types/peers/peers-index.d.ts +1 -0
- package/highlevel/types/peers/peers-index.js +10 -0
- package/highlevel/types/premium/business-connection.cjs +3 -3
- package/highlevel/types/premium/business-connection.d.cts +2 -2
- package/highlevel/types/premium/business-connection.d.ts +2 -2
- package/highlevel/types/premium/business-connection.js +3 -3
- package/highlevel/types/premium/saved-star-gift.cjs +2 -2
- package/highlevel/types/premium/saved-star-gift.d.cts +2 -2
- package/highlevel/types/premium/saved-star-gift.d.ts +2 -2
- package/highlevel/types/premium/saved-star-gift.js +2 -2
- package/highlevel/types/premium/stars-gift-unique.cjs +35 -5
- package/highlevel/types/premium/stars-gift-unique.d.cts +23 -3
- package/highlevel/types/premium/stars-gift-unique.d.ts +23 -3
- package/highlevel/types/premium/stars-gift-unique.js +35 -5
- package/highlevel/types/premium/stars-transaction.cjs +4 -0
- package/highlevel/types/premium/stars-transaction.d.cts +2 -0
- package/highlevel/types/premium/stars-transaction.d.ts +2 -0
- package/highlevel/types/premium/stars-transaction.js +4 -0
- package/highlevel/updates/manager.cjs +4 -4
- package/highlevel/updates/manager.js +4 -4
- package/highlevel/worker/storage.cjs +4 -0
- package/highlevel/worker/storage.d.cts +2 -0
- package/highlevel/worker/storage.d.ts +2 -0
- package/highlevel/worker/storage.js +4 -0
- package/network/authorization.cjs +1 -1
- package/network/authorization.js +1 -1
- package/network/middlewares/flood-waiter.cjs +20 -4
- package/network/middlewares/flood-waiter.d.cts +9 -2
- package/network/middlewares/flood-waiter.d.ts +9 -2
- package/network/middlewares/flood-waiter.js +20 -4
- package/network/mtproto-session.cjs +3 -4
- package/network/mtproto-session.d.cts +1 -1
- package/network/mtproto-session.d.ts +1 -1
- package/network/mtproto-session.js +3 -4
- package/network/network-manager.cjs +3 -3
- package/network/network-manager.d.cts +1 -1
- package/network/network-manager.d.ts +1 -1
- package/network/network-manager.js +3 -3
- package/network/persistent-connection.cjs +1 -0
- package/network/persistent-connection.js +1 -0
- package/network/session-connection.cjs +7 -5
- package/network/session-connection.js +7 -5
- package/package.json +7 -7
- package/utils/binary/compat.cjs +2 -0
- package/utils/binary/compat.js +2 -0
- package/utils/early-timer.cjs +12 -7
- package/utils/early-timer.d.cts +3 -3
- package/utils/early-timer.d.ts +3 -3
- package/utils/early-timer.js +12 -7
|
@@ -201,14 +201,15 @@ async function _normalizeInputMedia(client, media, params = {}, uploadMedia = fa
|
|
|
201
201
|
fileMime: sendMime,
|
|
202
202
|
fileSize: media.fileSize,
|
|
203
203
|
requireFileSize: media.type === "photo",
|
|
204
|
-
requireExtension: media.type === "photo"
|
|
204
|
+
requireExtension: media.type === "photo",
|
|
205
|
+
abortSignal: params.abortSignal
|
|
205
206
|
});
|
|
206
207
|
inputFile = uploaded.inputFile;
|
|
207
208
|
mime = uploaded.mime;
|
|
208
209
|
};
|
|
209
210
|
let videoCover;
|
|
210
211
|
if (media.type === "video" && media.cover) {
|
|
211
|
-
const inputMedia = await _normalizeInputMedia(client, media.cover);
|
|
212
|
+
const inputMedia = await _normalizeInputMedia(client, media.cover, params);
|
|
212
213
|
assertTypeIs("uploadMediaIfNeeded", inputMedia, "inputMediaPhoto");
|
|
213
214
|
videoCover = inputMedia.id;
|
|
214
215
|
}
|
|
@@ -220,7 +221,7 @@ async function _normalizeInputMedia(client, media, params = {}, uploadMedia = fa
|
|
|
220
221
|
peer: uploadPeer,
|
|
221
222
|
media: inputMedia,
|
|
222
223
|
businessConnectionId: params.businessConnectionId
|
|
223
|
-
});
|
|
224
|
+
}, { abortSignal: params.abortSignal });
|
|
224
225
|
if (photo) {
|
|
225
226
|
assertTypeIs("normalizeInputMedia (@ messages.uploadMedia)", res, "messageMediaPhoto");
|
|
226
227
|
assertTypeIs("normalizeInputMedia (@ messages.uploadMedia)", res.photo, "photo");
|
|
@@ -308,7 +309,7 @@ async function _normalizeInputMedia(client, media, params = {}, uploadMedia = fa
|
|
|
308
309
|
);
|
|
309
310
|
}
|
|
310
311
|
if ("thumb" in media && media.thumb) {
|
|
311
|
-
thumb = await _normalizeInputFile(client, media.thumb, {});
|
|
312
|
+
thumb = await _normalizeInputFile(client, media.thumb, { abortSignal: params.abortSignal });
|
|
312
313
|
}
|
|
313
314
|
const attributes = [];
|
|
314
315
|
if (media.type !== "voice") {
|
|
@@ -318,14 +319,20 @@ async function _normalizeInputMedia(client, media, params = {}, uploadMedia = fa
|
|
|
318
319
|
});
|
|
319
320
|
}
|
|
320
321
|
if (media.type === "video") {
|
|
321
|
-
|
|
322
|
+
const attr = {
|
|
322
323
|
_: "documentAttributeVideo",
|
|
323
324
|
duration: media.duration || 0,
|
|
324
325
|
w: media.width || 0,
|
|
325
326
|
h: media.height || 0,
|
|
326
327
|
supportsStreaming: media.supportsStreaming,
|
|
327
328
|
roundMessage: media.isRound
|
|
328
|
-
}
|
|
329
|
+
};
|
|
330
|
+
if (media.isRound) {
|
|
331
|
+
if (attr.w === 0) attr.w = 1;
|
|
332
|
+
if (attr.h === 0) attr.h = 1;
|
|
333
|
+
if (attr.duration === 0) attr.duration = 1;
|
|
334
|
+
}
|
|
335
|
+
attributes.push(attr);
|
|
329
336
|
if (media.isAnimated) {
|
|
330
337
|
attributes.push({ _: "documentAttributeAnimated" });
|
|
331
338
|
}
|
|
@@ -30,6 +30,7 @@ async function uploadFile(client, params) {
|
|
|
30
30
|
let fileSize = -1;
|
|
31
31
|
let fileName = params.fileName;
|
|
32
32
|
let fileMime = params.fileMime;
|
|
33
|
+
const abortSignal = params.abortSignal;
|
|
33
34
|
if (client.platform.normalizeFile) {
|
|
34
35
|
const res = await client.platform.normalizeFile(file);
|
|
35
36
|
if (res?.file) {
|
|
@@ -127,6 +128,7 @@ async function uploadFile(client, params) {
|
|
|
127
128
|
let idx = 0;
|
|
128
129
|
let readableEnded = false;
|
|
129
130
|
const uploadNextPart = async () => {
|
|
131
|
+
if (abortSignal?.aborted) return;
|
|
130
132
|
const thisIdx = idx++;
|
|
131
133
|
await lock.acquire();
|
|
132
134
|
if (readableEnded) {
|
|
@@ -139,6 +141,7 @@ async function uploadFile(client, params) {
|
|
|
139
141
|
} finally {
|
|
140
142
|
lock.release();
|
|
141
143
|
}
|
|
144
|
+
if (abortSignal?.aborted) return;
|
|
142
145
|
const ended = part.length < partSize;
|
|
143
146
|
if (ended) {
|
|
144
147
|
readableEnded = true;
|
|
@@ -171,8 +174,9 @@ async function uploadFile(client, params) {
|
|
|
171
174
|
filePart: thisIdx,
|
|
172
175
|
bytes: part
|
|
173
176
|
};
|
|
174
|
-
const result = await client.call(request, { kind: connectionKind });
|
|
177
|
+
const result = await client.call(request, { kind: connectionKind, abortSignal });
|
|
175
178
|
if (!result) throw new Error(`Failed to upload part ${idx}`);
|
|
179
|
+
if (abortSignal?.aborted) return;
|
|
176
180
|
pos += part.length;
|
|
177
181
|
params.progressCallback?.(pos, fileSize);
|
|
178
182
|
if (idx === partCount) return;
|
|
@@ -181,6 +185,7 @@ async function uploadFile(client, params) {
|
|
|
181
185
|
let poolSize = partCount === -1 ? 1 : connectionPoolSize * requestsPerConnection;
|
|
182
186
|
if (partCount !== -1 && poolSize > partCount) poolSize = partCount;
|
|
183
187
|
await Promise.all(Array.from({ length: poolSize }, uploadNextPart));
|
|
188
|
+
abortSignal?.throwIfAborted();
|
|
184
189
|
if (fileName === void 0) {
|
|
185
190
|
const ext = fileType.MIME_TO_EXTENSION[fileMime];
|
|
186
191
|
fileName = ext ? `${DEFAULT_FILE_NAME}.${ext}` : DEFAULT_FILE_NAME;
|
|
@@ -193,8 +198,6 @@ async function uploadFile(client, params) {
|
|
|
193
198
|
throw new errors.MtArgumentError(`File name does not have an extension, and we cannot guess it from the mime type (${fileMime})`);
|
|
194
199
|
}
|
|
195
200
|
fileName = `${fileName}.${extFromMime}`;
|
|
196
|
-
} else if (extFromMime && extFromName !== extFromMime) {
|
|
197
|
-
throw new errors.MtArgumentError(`File name has ${extFromName} extension (${fileName}), but the mime type (${fileMime}) expects it to be ${extFromMime}`);
|
|
198
201
|
}
|
|
199
202
|
}
|
|
200
203
|
let inputFile;
|
|
@@ -23,6 +23,7 @@ async function uploadFile(client, params) {
|
|
|
23
23
|
let fileSize = -1;
|
|
24
24
|
let fileName = params.fileName;
|
|
25
25
|
let fileMime = params.fileMime;
|
|
26
|
+
const abortSignal = params.abortSignal;
|
|
26
27
|
if (client.platform.normalizeFile) {
|
|
27
28
|
const res = await client.platform.normalizeFile(file);
|
|
28
29
|
if (res?.file) {
|
|
@@ -120,6 +121,7 @@ async function uploadFile(client, params) {
|
|
|
120
121
|
let idx = 0;
|
|
121
122
|
let readableEnded = false;
|
|
122
123
|
const uploadNextPart = async () => {
|
|
124
|
+
if (abortSignal?.aborted) return;
|
|
123
125
|
const thisIdx = idx++;
|
|
124
126
|
await lock.acquire();
|
|
125
127
|
if (readableEnded) {
|
|
@@ -132,6 +134,7 @@ async function uploadFile(client, params) {
|
|
|
132
134
|
} finally {
|
|
133
135
|
lock.release();
|
|
134
136
|
}
|
|
137
|
+
if (abortSignal?.aborted) return;
|
|
135
138
|
const ended = part.length < partSize;
|
|
136
139
|
if (ended) {
|
|
137
140
|
readableEnded = true;
|
|
@@ -164,8 +167,9 @@ async function uploadFile(client, params) {
|
|
|
164
167
|
filePart: thisIdx,
|
|
165
168
|
bytes: part
|
|
166
169
|
};
|
|
167
|
-
const result = await client.call(request, { kind: connectionKind });
|
|
170
|
+
const result = await client.call(request, { kind: connectionKind, abortSignal });
|
|
168
171
|
if (!result) throw new Error(`Failed to upload part ${idx}`);
|
|
172
|
+
if (abortSignal?.aborted) return;
|
|
169
173
|
pos += part.length;
|
|
170
174
|
params.progressCallback?.(pos, fileSize);
|
|
171
175
|
if (idx === partCount) return;
|
|
@@ -174,6 +178,7 @@ async function uploadFile(client, params) {
|
|
|
174
178
|
let poolSize = partCount === -1 ? 1 : connectionPoolSize * requestsPerConnection;
|
|
175
179
|
if (partCount !== -1 && poolSize > partCount) poolSize = partCount;
|
|
176
180
|
await Promise.all(Array.from({ length: poolSize }, uploadNextPart));
|
|
181
|
+
abortSignal?.throwIfAborted();
|
|
177
182
|
if (fileName === void 0) {
|
|
178
183
|
const ext = MIME_TO_EXTENSION[fileMime];
|
|
179
184
|
fileName = ext ? `${DEFAULT_FILE_NAME}.${ext}` : DEFAULT_FILE_NAME;
|
|
@@ -186,8 +191,6 @@ async function uploadFile(client, params) {
|
|
|
186
191
|
throw new MtArgumentError(`File name does not have an extension, and we cannot guess it from the mime type (${fileMime})`);
|
|
187
192
|
}
|
|
188
193
|
fileName = `${fileName}.${extFromMime}`;
|
|
189
|
-
} else if (extFromMime && extFromName !== extFromMime) {
|
|
190
|
-
throw new MtArgumentError(`File name has ${extFromName} extension (${fileName}), but the mime type (${fileMime}) expects it to be ${extFromMime}`);
|
|
191
194
|
}
|
|
192
195
|
}
|
|
193
196
|
let inputFile;
|
|
@@ -103,6 +103,7 @@ export interface CommonSendParams {
|
|
|
103
103
|
* If set, the value represents the maximum number of stars to be paid
|
|
104
104
|
*/
|
|
105
105
|
allowPaidMessages?: tl.Long;
|
|
106
|
+
abortSignal?: AbortSignal;
|
|
106
107
|
/**
|
|
107
108
|
* ID of a message effect to use when sending the message
|
|
108
109
|
* (see {@link TelegramClient.getAvailableMessageEffects})
|
|
@@ -103,6 +103,7 @@ export interface CommonSendParams {
|
|
|
103
103
|
* If set, the value represents the maximum number of stars to be paid
|
|
104
104
|
*/
|
|
105
105
|
allowPaidMessages?: tl.Long;
|
|
106
|
+
abortSignal?: AbortSignal;
|
|
106
107
|
/**
|
|
107
108
|
* ID of a message effect to use when sending the message
|
|
108
109
|
* (see {@link TelegramClient.getAvailableMessageEffects})
|
|
@@ -39,7 +39,8 @@ async function sendMediaGroup(client, chatId, medias, params) {
|
|
|
39
39
|
// but otherwise Telegram throws MEDIA_INVALID
|
|
40
40
|
// fuck my life
|
|
41
41
|
uploadPeer: peer,
|
|
42
|
-
businessConnectionId: params.businessConnectionId
|
|
42
|
+
businessConnectionId: params.businessConnectionId,
|
|
43
|
+
abortSignal: params.abortSignal
|
|
43
44
|
},
|
|
44
45
|
true
|
|
45
46
|
);
|
|
@@ -76,7 +77,7 @@ async function sendMediaGroup(client, chatId, medias, params) {
|
|
|
76
77
|
allowPaidFloodskip: params.allowPaidFloodskip,
|
|
77
78
|
allowPaidStars: params.allowPaidMessages
|
|
78
79
|
},
|
|
79
|
-
{ chainId }
|
|
80
|
+
{ chainId, abortSignal: params.abortSignal }
|
|
80
81
|
);
|
|
81
82
|
utils.assertIsUpdatesGroup("sendMediaGroup", res);
|
|
82
83
|
client.handleClientUpdate(res);
|
|
@@ -32,7 +32,8 @@ async function sendMediaGroup(client, chatId, medias, params) {
|
|
|
32
32
|
// but otherwise Telegram throws MEDIA_INVALID
|
|
33
33
|
// fuck my life
|
|
34
34
|
uploadPeer: peer,
|
|
35
|
-
businessConnectionId: params.businessConnectionId
|
|
35
|
+
businessConnectionId: params.businessConnectionId,
|
|
36
|
+
abortSignal: params.abortSignal
|
|
36
37
|
},
|
|
37
38
|
true
|
|
38
39
|
);
|
|
@@ -69,7 +70,7 @@ async function sendMediaGroup(client, chatId, medias, params) {
|
|
|
69
70
|
allowPaidFloodskip: params.allowPaidFloodskip,
|
|
70
71
|
allowPaidStars: params.allowPaidMessages
|
|
71
72
|
},
|
|
72
|
-
{ chainId }
|
|
73
|
+
{ chainId, abortSignal: params.abortSignal }
|
|
73
74
|
);
|
|
74
75
|
assertIsUpdatesGroup("sendMediaGroup", res);
|
|
75
76
|
client.handleClientUpdate(res);
|
|
@@ -28,7 +28,8 @@ async function sendMedia(client, chatId, media, params) {
|
|
|
28
28
|
);
|
|
29
29
|
const inputMedia = await normalizeInputMedia._normalizeInputMedia(client, media, {
|
|
30
30
|
progressCallback: params.progressCallback,
|
|
31
|
-
uploadPeer: peer
|
|
31
|
+
uploadPeer: peer,
|
|
32
|
+
abortSignal: params.abortSignal
|
|
32
33
|
});
|
|
33
34
|
const [message, entities] = await normalizeText._normalizeInputText(
|
|
34
35
|
client,
|
|
@@ -61,7 +62,7 @@ async function sendMedia(client, chatId, media, params) {
|
|
|
61
62
|
allowPaidFloodskip: params.allowPaidFloodskip,
|
|
62
63
|
allowPaidStars: params.allowPaidMessages
|
|
63
64
|
},
|
|
64
|
-
{ chainId }
|
|
65
|
+
{ chainId, abortSignal: params.abortSignal }
|
|
65
66
|
);
|
|
66
67
|
const msg = findInUpdate._findMessageInUpdate(client, res, false, !params.shouldDispatch, false, randomId);
|
|
67
68
|
return msg;
|
|
@@ -21,7 +21,8 @@ async function sendMedia(client, chatId, media, params) {
|
|
|
21
21
|
);
|
|
22
22
|
const inputMedia = await _normalizeInputMedia(client, media, {
|
|
23
23
|
progressCallback: params.progressCallback,
|
|
24
|
-
uploadPeer: peer
|
|
24
|
+
uploadPeer: peer,
|
|
25
|
+
abortSignal: params.abortSignal
|
|
25
26
|
});
|
|
26
27
|
const [message, entities] = await _normalizeInputText(
|
|
27
28
|
client,
|
|
@@ -54,7 +55,7 @@ async function sendMedia(client, chatId, media, params) {
|
|
|
54
55
|
allowPaidFloodskip: params.allowPaidFloodskip,
|
|
55
56
|
allowPaidStars: params.allowPaidMessages
|
|
56
57
|
},
|
|
57
|
-
{ chainId }
|
|
58
|
+
{ chainId, abortSignal: params.abortSignal }
|
|
58
59
|
);
|
|
59
60
|
const msg = _findMessageInUpdate(client, res, false, !params.shouldDispatch, false, randomId);
|
|
60
61
|
return msg;
|
|
@@ -52,7 +52,7 @@ async function sendText(client, chatId, text, params) {
|
|
|
52
52
|
allowPaidFloodskip: params.allowPaidFloodskip,
|
|
53
53
|
allowPaidStars: params.allowPaidMessages
|
|
54
54
|
},
|
|
55
|
-
{ chainId }
|
|
55
|
+
{ chainId, abortSignal: params.abortSignal }
|
|
56
56
|
);
|
|
57
57
|
if (res._ === "updateShortSentMessage") {
|
|
58
58
|
const msg2 = {
|
|
@@ -45,7 +45,7 @@ async function sendText(client, chatId, text, params) {
|
|
|
45
45
|
allowPaidFloodskip: params.allowPaidFloodskip,
|
|
46
46
|
allowPaidStars: params.allowPaidMessages
|
|
47
47
|
},
|
|
48
|
-
{ chainId }
|
|
48
|
+
{ chainId, abortSignal: params.abortSignal }
|
|
49
49
|
);
|
|
50
50
|
if (res._ === "updateShortSentMessage") {
|
|
51
51
|
const msg2 = {
|
|
@@ -32,53 +32,18 @@ async function resolvePeerMany(client, peerIds, normalizer) {
|
|
|
32
32
|
}
|
|
33
33
|
return ret;
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
let nextIdx = 0;
|
|
38
|
-
let nextWorkerIdx = 0;
|
|
39
|
-
const fetchNext = async (idx = nextWorkerIdx++) => {
|
|
35
|
+
return utils.parallelMap(peerIds, async (it) => {
|
|
36
|
+
let peer;
|
|
40
37
|
try {
|
|
41
|
-
|
|
42
|
-
buffer[idx] = result;
|
|
38
|
+
peer = await resolvePeer.resolvePeer(client, it);
|
|
43
39
|
} catch (e) {
|
|
44
40
|
if (e instanceof errors.MtPeerNotFoundError) {
|
|
45
|
-
|
|
46
|
-
} else {
|
|
47
|
-
throw e;
|
|
41
|
+
return null;
|
|
48
42
|
}
|
|
43
|
+
throw e;
|
|
49
44
|
}
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (nextWorkerIdx < peerIds.length) {
|
|
54
|
-
await fetchNext(nextWorkerIdx++);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
let error;
|
|
58
|
-
void Promise.all(Array.from({ length: limit }, (_, i) => fetchNext(i))).catch((e) => {
|
|
59
|
-
client.log.debug("resolvePeerMany errored: %e", e);
|
|
60
|
-
error = e;
|
|
61
|
-
cv.notify();
|
|
62
|
-
});
|
|
63
|
-
while (nextIdx < peerIds.length) {
|
|
64
|
-
await cv.wait();
|
|
65
|
-
if (error) throw error;
|
|
66
|
-
while (nextIdx in buffer) {
|
|
67
|
-
const buf = buffer[nextIdx];
|
|
68
|
-
delete buffer[nextIdx];
|
|
69
|
-
nextIdx++;
|
|
70
|
-
if (!normalizer) {
|
|
71
|
-
ret.push(buf);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
if (buf !== null) {
|
|
75
|
-
const norm = normalizer(buf);
|
|
76
|
-
if (norm) {
|
|
77
|
-
ret.push(norm);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return ret;
|
|
45
|
+
if (normalizer) return normalizer(peer);
|
|
46
|
+
return peer;
|
|
47
|
+
}, { limit });
|
|
83
48
|
}
|
|
84
49
|
exports.resolvePeerMany = resolvePeerMany;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parallelMap } from "@fuman/utils";
|
|
2
2
|
import { MtPeerNotFoundError } from "../../types/errors.js";
|
|
3
3
|
import { resolvePeer } from "./resolve-peer.js";
|
|
4
4
|
async function resolvePeerMany(client, peerIds, normalizer) {
|
|
@@ -25,54 +25,19 @@ async function resolvePeerMany(client, peerIds, normalizer) {
|
|
|
25
25
|
}
|
|
26
26
|
return ret;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
let nextIdx = 0;
|
|
31
|
-
let nextWorkerIdx = 0;
|
|
32
|
-
const fetchNext = async (idx = nextWorkerIdx++) => {
|
|
28
|
+
return parallelMap(peerIds, async (it) => {
|
|
29
|
+
let peer;
|
|
33
30
|
try {
|
|
34
|
-
|
|
35
|
-
buffer[idx] = result;
|
|
31
|
+
peer = await resolvePeer(client, it);
|
|
36
32
|
} catch (e) {
|
|
37
33
|
if (e instanceof MtPeerNotFoundError) {
|
|
38
|
-
|
|
39
|
-
} else {
|
|
40
|
-
throw e;
|
|
34
|
+
return null;
|
|
41
35
|
}
|
|
36
|
+
throw e;
|
|
42
37
|
}
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (nextWorkerIdx < peerIds.length) {
|
|
47
|
-
await fetchNext(nextWorkerIdx++);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
let error;
|
|
51
|
-
void Promise.all(Array.from({ length: limit }, (_, i) => fetchNext(i))).catch((e) => {
|
|
52
|
-
client.log.debug("resolvePeerMany errored: %e", e);
|
|
53
|
-
error = e;
|
|
54
|
-
cv.notify();
|
|
55
|
-
});
|
|
56
|
-
while (nextIdx < peerIds.length) {
|
|
57
|
-
await cv.wait();
|
|
58
|
-
if (error) throw error;
|
|
59
|
-
while (nextIdx in buffer) {
|
|
60
|
-
const buf = buffer[nextIdx];
|
|
61
|
-
delete buffer[nextIdx];
|
|
62
|
-
nextIdx++;
|
|
63
|
-
if (!normalizer) {
|
|
64
|
-
ret.push(buf);
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
if (buf !== null) {
|
|
68
|
-
const norm = normalizer(buf);
|
|
69
|
-
if (norm) {
|
|
70
|
-
ret.push(norm);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return ret;
|
|
38
|
+
if (normalizer) return normalizer(peer);
|
|
39
|
+
return peer;
|
|
40
|
+
}, { limit });
|
|
76
41
|
}
|
|
77
42
|
export {
|
|
78
43
|
resolvePeerMany
|
|
@@ -41,9 +41,25 @@ class PeersService extends base.BaseService {
|
|
|
41
41
|
this._peers = _peers;
|
|
42
42
|
this._refs = _refs;
|
|
43
43
|
this._cache = new utils.LruMap(options.cacheSize ?? 100);
|
|
44
|
+
this._writePending = this._writePending.bind(this);
|
|
44
45
|
}
|
|
45
46
|
_cache;
|
|
46
47
|
_pendingWrites = /* @__PURE__ */ new Map();
|
|
48
|
+
_pendingWritesTimer = null;
|
|
49
|
+
async close() {
|
|
50
|
+
if (this._pendingWritesTimer) {
|
|
51
|
+
utils.timers.clearTimeout(this._pendingWritesTimer);
|
|
52
|
+
this._pendingWritesTimer = null;
|
|
53
|
+
}
|
|
54
|
+
await this._writePending();
|
|
55
|
+
}
|
|
56
|
+
_writePendingLater() {
|
|
57
|
+
if (this._pendingWritesTimer) return;
|
|
58
|
+
this._pendingWritesTimer = utils.timers.setTimeout(
|
|
59
|
+
this._writePending,
|
|
60
|
+
this.options.updatesWriteInterval ?? 3e4
|
|
61
|
+
);
|
|
62
|
+
}
|
|
47
63
|
async updatePeersFrom(obj) {
|
|
48
64
|
let count = 0;
|
|
49
65
|
let minCount = 0;
|
|
@@ -117,17 +133,9 @@ class PeersService extends base.BaseService {
|
|
|
117
133
|
return;
|
|
118
134
|
}
|
|
119
135
|
const cached = this._cache.get(peer.id);
|
|
120
|
-
if (cached && this.options.updatesWriteInterval !== 0) {
|
|
121
|
-
const oldAccessHash = cached.peer.accessHash;
|
|
122
|
-
if (oldAccessHash?.eq(accessHash)) {
|
|
123
|
-
this._pendingWrites.set(peer.id, dto);
|
|
124
|
-
cached.complete = peer;
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
136
|
let newComplete = peer;
|
|
129
137
|
if (peer.min) {
|
|
130
|
-
const existing =
|
|
138
|
+
const existing = cached?.complete ?? await this.getCompleteById(peer.id);
|
|
131
139
|
if (existing && !existing.min) {
|
|
132
140
|
if (existing._ === "channel" && peer._ === "channel") {
|
|
133
141
|
newComplete = {
|
|
@@ -188,6 +196,15 @@ class PeersService extends base.BaseService {
|
|
|
188
196
|
}
|
|
189
197
|
}
|
|
190
198
|
}
|
|
199
|
+
if (cached && this.options.updatesWriteInterval !== 0) {
|
|
200
|
+
const oldAccessHash = cached.peer.accessHash;
|
|
201
|
+
if (oldAccessHash?.eq(accessHash)) {
|
|
202
|
+
this._pendingWrites.set(peer.id, dto);
|
|
203
|
+
this._writePendingLater();
|
|
204
|
+
cached.complete = newComplete;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
191
208
|
await this._peers.store(dto);
|
|
192
209
|
this._cache.set(peer.id, {
|
|
193
210
|
peer: getInputPeer(dto),
|
|
@@ -195,6 +212,17 @@ class PeersService extends base.BaseService {
|
|
|
195
212
|
});
|
|
196
213
|
await this._refs.deleteByPeer(peer.id);
|
|
197
214
|
}
|
|
215
|
+
async _writePending() {
|
|
216
|
+
try {
|
|
217
|
+
await utils.asyncPool(this._pendingWrites.values(), async (dto) => {
|
|
218
|
+
await this._peers.store(dto);
|
|
219
|
+
await this._refs.deleteByPeer(dto.id);
|
|
220
|
+
});
|
|
221
|
+
this._pendingWrites.clear();
|
|
222
|
+
} catch (err) {
|
|
223
|
+
this._log.warn("failed to write pending updates: %e", err);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
198
226
|
_returnCaching(id, dto) {
|
|
199
227
|
const peer = getInputPeer(dto);
|
|
200
228
|
const complete = this._deserializeTl(dto.complete);
|
|
@@ -12,9 +12,13 @@ export declare class PeersService extends BaseService {
|
|
|
12
12
|
private _refs;
|
|
13
13
|
private _cache;
|
|
14
14
|
private _pendingWrites;
|
|
15
|
+
private _pendingWritesTimer;
|
|
15
16
|
constructor(options: PeersServiceOptions, _peers: IPeersRepository, _refs: RefMessagesService, common: ServiceOptions);
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
private _writePendingLater;
|
|
16
19
|
updatePeersFrom(obj: tl.TlObject | tl.TlObject[]): Promise<boolean>;
|
|
17
20
|
store(peer: tl.TypeUser | tl.TypeChat): Promise<void>;
|
|
21
|
+
private _writePending;
|
|
18
22
|
private _returnCaching;
|
|
19
23
|
getById(id: number, allowRefs?: boolean): Promise<tl.TypeInputPeer | null>;
|
|
20
24
|
getMinAccessHash(id: number): Promise<tl.Long | null>;
|
|
@@ -12,9 +12,13 @@ export declare class PeersService extends BaseService {
|
|
|
12
12
|
private _refs;
|
|
13
13
|
private _cache;
|
|
14
14
|
private _pendingWrites;
|
|
15
|
+
private _pendingWritesTimer;
|
|
15
16
|
constructor(options: PeersServiceOptions, _peers: IPeersRepository, _refs: RefMessagesService, common: ServiceOptions);
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
private _writePendingLater;
|
|
16
19
|
updatePeersFrom(obj: tl.TlObject | tl.TlObject[]): Promise<boolean>;
|
|
17
20
|
store(peer: tl.TypeUser | tl.TypeChat): Promise<void>;
|
|
21
|
+
private _writePending;
|
|
18
22
|
private _returnCaching;
|
|
19
23
|
getById(id: number, allowRefs?: boolean): Promise<tl.TypeInputPeer | null>;
|
|
20
24
|
getMinAccessHash(id: number): Promise<tl.Long | null>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LruMap } from "@fuman/utils";
|
|
1
|
+
import { LruMap, timers, asyncPool } from "@fuman/utils";
|
|
2
2
|
import Long from "long";
|
|
3
3
|
import { BaseService } from "../../../storage/service/base.js";
|
|
4
4
|
import { longToFastString, longFromFastString } from "../../../utils/long-utils.js";
|
|
@@ -34,9 +34,25 @@ class PeersService extends BaseService {
|
|
|
34
34
|
this._peers = _peers;
|
|
35
35
|
this._refs = _refs;
|
|
36
36
|
this._cache = new LruMap(options.cacheSize ?? 100);
|
|
37
|
+
this._writePending = this._writePending.bind(this);
|
|
37
38
|
}
|
|
38
39
|
_cache;
|
|
39
40
|
_pendingWrites = /* @__PURE__ */ new Map();
|
|
41
|
+
_pendingWritesTimer = null;
|
|
42
|
+
async close() {
|
|
43
|
+
if (this._pendingWritesTimer) {
|
|
44
|
+
timers.clearTimeout(this._pendingWritesTimer);
|
|
45
|
+
this._pendingWritesTimer = null;
|
|
46
|
+
}
|
|
47
|
+
await this._writePending();
|
|
48
|
+
}
|
|
49
|
+
_writePendingLater() {
|
|
50
|
+
if (this._pendingWritesTimer) return;
|
|
51
|
+
this._pendingWritesTimer = timers.setTimeout(
|
|
52
|
+
this._writePending,
|
|
53
|
+
this.options.updatesWriteInterval ?? 3e4
|
|
54
|
+
);
|
|
55
|
+
}
|
|
40
56
|
async updatePeersFrom(obj) {
|
|
41
57
|
let count = 0;
|
|
42
58
|
let minCount = 0;
|
|
@@ -110,17 +126,9 @@ class PeersService extends BaseService {
|
|
|
110
126
|
return;
|
|
111
127
|
}
|
|
112
128
|
const cached = this._cache.get(peer.id);
|
|
113
|
-
if (cached && this.options.updatesWriteInterval !== 0) {
|
|
114
|
-
const oldAccessHash = cached.peer.accessHash;
|
|
115
|
-
if (oldAccessHash?.eq(accessHash)) {
|
|
116
|
-
this._pendingWrites.set(peer.id, dto);
|
|
117
|
-
cached.complete = peer;
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
129
|
let newComplete = peer;
|
|
122
130
|
if (peer.min) {
|
|
123
|
-
const existing =
|
|
131
|
+
const existing = cached?.complete ?? await this.getCompleteById(peer.id);
|
|
124
132
|
if (existing && !existing.min) {
|
|
125
133
|
if (existing._ === "channel" && peer._ === "channel") {
|
|
126
134
|
newComplete = {
|
|
@@ -181,6 +189,15 @@ class PeersService extends BaseService {
|
|
|
181
189
|
}
|
|
182
190
|
}
|
|
183
191
|
}
|
|
192
|
+
if (cached && this.options.updatesWriteInterval !== 0) {
|
|
193
|
+
const oldAccessHash = cached.peer.accessHash;
|
|
194
|
+
if (oldAccessHash?.eq(accessHash)) {
|
|
195
|
+
this._pendingWrites.set(peer.id, dto);
|
|
196
|
+
this._writePendingLater();
|
|
197
|
+
cached.complete = newComplete;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
184
201
|
await this._peers.store(dto);
|
|
185
202
|
this._cache.set(peer.id, {
|
|
186
203
|
peer: getInputPeer(dto),
|
|
@@ -188,6 +205,17 @@ class PeersService extends BaseService {
|
|
|
188
205
|
});
|
|
189
206
|
await this._refs.deleteByPeer(peer.id);
|
|
190
207
|
}
|
|
208
|
+
async _writePending() {
|
|
209
|
+
try {
|
|
210
|
+
await asyncPool(this._pendingWrites.values(), async (dto) => {
|
|
211
|
+
await this._peers.store(dto);
|
|
212
|
+
await this._refs.deleteByPeer(dto.id);
|
|
213
|
+
});
|
|
214
|
+
this._pendingWrites.clear();
|
|
215
|
+
} catch (err) {
|
|
216
|
+
this._log.warn("failed to write pending updates: %e", err);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
191
219
|
_returnCaching(id, dto) {
|
|
192
220
|
const peer = getInputPeer(dto);
|
|
193
221
|
const complete = this._deserializeTl(dto.complete);
|
|
@@ -22,6 +22,7 @@ export declare class TelegramStorageManager {
|
|
|
22
22
|
readonly refMsgs: RefMessagesService;
|
|
23
23
|
readonly peers: PublicPart<PeersService>;
|
|
24
24
|
constructor(mt: StorageManager, options: TelegramStorageManagerOptions & TelegramStorageManagerExtraOptions);
|
|
25
|
+
close(): Promise<void>;
|
|
25
26
|
clear(withAuthKeys?: boolean): Promise<void>;
|
|
26
27
|
}
|
|
27
28
|
export {};
|
|
@@ -22,6 +22,7 @@ export declare class TelegramStorageManager {
|
|
|
22
22
|
readonly refMsgs: RefMessagesService;
|
|
23
23
|
readonly peers: PublicPart<PeersService>;
|
|
24
24
|
constructor(mt: StorageManager, options: TelegramStorageManagerOptions & TelegramStorageManagerExtraOptions);
|
|
25
|
+
close(): Promise<void>;
|
|
25
26
|
clear(withAuthKeys?: boolean): Promise<void>;
|
|
26
27
|
}
|
|
27
28
|
export {};
|