@mtcute/core 0.27.1 → 0.27.2
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 +12 -0
- package/client.js +13 -1
- package/highlevel/client.d.cts +131 -90
- package/highlevel/client.d.ts +131 -90
- package/highlevel/client.test.d.cts +1 -0
- package/highlevel/client.test.d.ts +1 -0
- package/highlevel/methods/contacts/set-contact-note.cjs +21 -0
- package/highlevel/methods/contacts/set-contact-note.js +16 -0
- package/highlevel/methods/files/download-chunk.cjs +63 -0
- package/highlevel/methods/files/download-chunk.d.cts +29 -0
- package/highlevel/methods/files/download-chunk.d.ts +29 -0
- package/highlevel/methods/files/download-chunk.js +58 -0
- package/highlevel/methods/files/download-chunk.test.d.cts +1 -0
- package/highlevel/methods/files/download-chunk.test.d.ts +1 -0
- package/highlevel/methods/files/download-iterable.cjs +39 -23
- package/highlevel/methods/files/download-iterable.d.cts +6 -0
- package/highlevel/methods/files/download-iterable.d.ts +6 -0
- package/highlevel/methods/files/download-iterable.js +33 -17
- package/highlevel/methods/forums/reorder-pinned-forum-topics.cjs +2 -2
- package/highlevel/methods/forums/reorder-pinned-forum-topics.js +3 -3
- package/highlevel/methods/forums/toggle-forum-topic-closed.cjs +2 -2
- package/highlevel/methods/forums/toggle-forum-topic-closed.js +3 -3
- package/highlevel/methods/forums/toggle-forum-topic-pinned.cjs +2 -2
- package/highlevel/methods/forums/toggle-forum-topic-pinned.js +3 -3
- package/highlevel/methods.d.cts +3 -0
- package/highlevel/methods.d.ts +3 -0
- package/highlevel/types/premium/star-gift.cjs +5 -1
- package/highlevel/types/premium/star-gift.d.cts +3 -1
- package/highlevel/types/premium/star-gift.d.ts +3 -1
- package/highlevel/types/premium/star-gift.js +5 -1
- package/methods.cjs +5 -0
- package/methods.js +6 -1
- package/network/network-manager.cjs +1 -1
- package/network/network-manager.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
if (typeof globalThis !== "undefined" && !globalThis._MTCUTE_CJS_DEPRECATION_WARNED) {
|
|
2
|
+
globalThis._MTCUTE_CJS_DEPRECATION_WARNED = true;
|
|
3
|
+
console.warn("[@mtcute/core] CommonJS bundles are deprecated. They will be removed completely in one of the upcoming releases. No support is provided for CommonJS users. Please consider switching to ESM, it's " + (/* @__PURE__ */ new Date()).getFullYear() + " already.");
|
|
4
|
+
console.warn("[@mtcute/core] Learn more about switching to ESM: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c");
|
|
5
|
+
}
|
|
6
|
+
"use strict";
|
|
7
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
8
|
+
const typeAssertions = require("../../../utils/type-assertions.cjs");
|
|
9
|
+
require("@mtcute/tl-runtime");
|
|
10
|
+
const resolvePeer = require("../users/resolve-peer.cjs");
|
|
11
|
+
const entities = require("../../types/misc/entities.cjs");
|
|
12
|
+
async function setContactNote(client, userId, note) {
|
|
13
|
+
const peer = await resolvePeer.resolveUser(client, userId);
|
|
14
|
+
const r = await client.call({
|
|
15
|
+
_: "contacts.updateContactNote",
|
|
16
|
+
id: peer,
|
|
17
|
+
note: entities.inputTextToTl(note)
|
|
18
|
+
});
|
|
19
|
+
typeAssertions.assertTrue("contacts.updateContactNote", r);
|
|
20
|
+
}
|
|
21
|
+
exports.setContactNote = setContactNote;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { assertTrue } from "../../../utils/type-assertions.js";
|
|
2
|
+
import "@mtcute/tl-runtime";
|
|
3
|
+
import { resolveUser } from "../users/resolve-peer.js";
|
|
4
|
+
import { inputTextToTl } from "../../types/misc/entities.js";
|
|
5
|
+
async function setContactNote(client, userId, note) {
|
|
6
|
+
const peer = await resolveUser(client, userId);
|
|
7
|
+
const r = await client.call({
|
|
8
|
+
_: "contacts.updateContactNote",
|
|
9
|
+
id: peer,
|
|
10
|
+
note: inputTextToTl(note)
|
|
11
|
+
});
|
|
12
|
+
assertTrue("contacts.updateContactNote", r);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
setContactNote
|
|
16
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
if (typeof globalThis !== "undefined" && !globalThis._MTCUTE_CJS_DEPRECATION_WARNED) {
|
|
2
|
+
globalThis._MTCUTE_CJS_DEPRECATION_WARNED = true;
|
|
3
|
+
console.warn("[@mtcute/core] CommonJS bundles are deprecated. They will be removed completely in one of the upcoming releases. No support is provided for CommonJS users. Please consider switching to ESM, it's " + (/* @__PURE__ */ new Date()).getFullYear() + " already.");
|
|
4
|
+
console.warn("[@mtcute/core] Learn more about switching to ESM: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c");
|
|
5
|
+
}
|
|
6
|
+
"use strict";
|
|
7
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
8
|
+
const utils = require("@fuman/utils");
|
|
9
|
+
const tl = require("@mtcute/tl");
|
|
10
|
+
const errors = require("../../../types/errors.cjs");
|
|
11
|
+
const downloadIterable = require("./download-iterable.cjs");
|
|
12
|
+
async function downloadChunk(client, params) {
|
|
13
|
+
const { location: input, dcId, offset, limit, maxRetryCount, floodSleepThreshold, abortSignal } = params;
|
|
14
|
+
const normalized = await downloadIterable._normalizeFileDownloadLocation(client, input);
|
|
15
|
+
const location = normalized.location;
|
|
16
|
+
if (tl.tl.isAnyInputWebFileLocation(location)) {
|
|
17
|
+
throw new errors.MtUnsupportedError("Web file locations are not supported for chunked downloads");
|
|
18
|
+
}
|
|
19
|
+
if (ArrayBuffer.isView(location)) {
|
|
20
|
+
throw new errors.MtArgumentError("Inline file locations are not supported for chunked downloads");
|
|
21
|
+
}
|
|
22
|
+
let alignedOffset = offset;
|
|
23
|
+
let alignedLimit = limit;
|
|
24
|
+
if (alignedOffset % 1024 !== 0) {
|
|
25
|
+
alignedOffset = Math.floor(alignedOffset / 1024) * 1024;
|
|
26
|
+
}
|
|
27
|
+
const stripStart = offset - alignedOffset;
|
|
28
|
+
if (stripStart > 0) {
|
|
29
|
+
alignedLimit += 1024 - stripStart;
|
|
30
|
+
}
|
|
31
|
+
if (alignedLimit % 1024 !== 0) {
|
|
32
|
+
alignedLimit = Math.ceil(alignedLimit / 1024) * 1024;
|
|
33
|
+
}
|
|
34
|
+
if (alignedLimit > 1048576) {
|
|
35
|
+
throw new errors.MtArgumentError(`Limit (${alignedLimit}) is too large for chunked downloads`);
|
|
36
|
+
}
|
|
37
|
+
const stripEnd = alignedLimit - limit - stripStart;
|
|
38
|
+
const result = await client.call(
|
|
39
|
+
{
|
|
40
|
+
_: "upload.getFile",
|
|
41
|
+
location,
|
|
42
|
+
offset: alignedOffset,
|
|
43
|
+
limit: alignedLimit,
|
|
44
|
+
precise: true
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
dcId,
|
|
48
|
+
maxRetryCount,
|
|
49
|
+
floodSleepThreshold,
|
|
50
|
+
abortSignal
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
utils.assert(result._ === "upload.file");
|
|
54
|
+
let bytes = result.bytes;
|
|
55
|
+
if (stripStart > 0) {
|
|
56
|
+
bytes = bytes.subarray(stripStart);
|
|
57
|
+
}
|
|
58
|
+
if (stripEnd > 0) {
|
|
59
|
+
bytes = bytes.subarray(0, -stripEnd);
|
|
60
|
+
}
|
|
61
|
+
return bytes;
|
|
62
|
+
}
|
|
63
|
+
exports.downloadChunk = downloadChunk;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ITelegramClient } from '../../client.types.js';
|
|
2
|
+
import { FileDownloadLocation } from '../../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Download a single chunk of a file, using [`precise`](https://core.telegram.org/api/files#downloading-files) download mode
|
|
5
|
+
*
|
|
6
|
+
* @param params Download parameters
|
|
7
|
+
*/
|
|
8
|
+
export declare function downloadChunk(client: ITelegramClient, params: {
|
|
9
|
+
/** File from which to download a chunk */
|
|
10
|
+
location: FileDownloadLocation;
|
|
11
|
+
/**
|
|
12
|
+
* DC id from which the file will be downloaded.
|
|
13
|
+
*
|
|
14
|
+
* If provided DC is not the one storing the file,
|
|
15
|
+
* redirection will be handled automatically.
|
|
16
|
+
*/
|
|
17
|
+
dcId?: number;
|
|
18
|
+
/** Offset of the chunk in bytes */
|
|
19
|
+
offset: number;
|
|
20
|
+
/**
|
|
21
|
+
* Number of bytes to download (starting from the offset)
|
|
22
|
+
*
|
|
23
|
+
* Max 1MB (1048576)
|
|
24
|
+
*/
|
|
25
|
+
limit: number;
|
|
26
|
+
maxRetryCount?: number;
|
|
27
|
+
floodSleepThreshold?: number;
|
|
28
|
+
abortSignal?: AbortSignal;
|
|
29
|
+
}): Promise<Uint8Array>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ITelegramClient } from '../../client.types.js';
|
|
2
|
+
import { FileDownloadLocation } from '../../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Download a single chunk of a file, using [`precise`](https://core.telegram.org/api/files#downloading-files) download mode
|
|
5
|
+
*
|
|
6
|
+
* @param params Download parameters
|
|
7
|
+
*/
|
|
8
|
+
export declare function downloadChunk(client: ITelegramClient, params: {
|
|
9
|
+
/** File from which to download a chunk */
|
|
10
|
+
location: FileDownloadLocation;
|
|
11
|
+
/**
|
|
12
|
+
* DC id from which the file will be downloaded.
|
|
13
|
+
*
|
|
14
|
+
* If provided DC is not the one storing the file,
|
|
15
|
+
* redirection will be handled automatically.
|
|
16
|
+
*/
|
|
17
|
+
dcId?: number;
|
|
18
|
+
/** Offset of the chunk in bytes */
|
|
19
|
+
offset: number;
|
|
20
|
+
/**
|
|
21
|
+
* Number of bytes to download (starting from the offset)
|
|
22
|
+
*
|
|
23
|
+
* Max 1MB (1048576)
|
|
24
|
+
*/
|
|
25
|
+
limit: number;
|
|
26
|
+
maxRetryCount?: number;
|
|
27
|
+
floodSleepThreshold?: number;
|
|
28
|
+
abortSignal?: AbortSignal;
|
|
29
|
+
}): Promise<Uint8Array>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { assert } from "@fuman/utils";
|
|
2
|
+
import { tl } from "@mtcute/tl";
|
|
3
|
+
import { MtUnsupportedError, MtArgumentError } from "../../../types/errors.js";
|
|
4
|
+
import { _normalizeFileDownloadLocation } from "./download-iterable.js";
|
|
5
|
+
async function downloadChunk(client, params) {
|
|
6
|
+
const { location: input, dcId, offset, limit, maxRetryCount, floodSleepThreshold, abortSignal } = params;
|
|
7
|
+
const normalized = await _normalizeFileDownloadLocation(client, input);
|
|
8
|
+
const location = normalized.location;
|
|
9
|
+
if (tl.isAnyInputWebFileLocation(location)) {
|
|
10
|
+
throw new MtUnsupportedError("Web file locations are not supported for chunked downloads");
|
|
11
|
+
}
|
|
12
|
+
if (ArrayBuffer.isView(location)) {
|
|
13
|
+
throw new MtArgumentError("Inline file locations are not supported for chunked downloads");
|
|
14
|
+
}
|
|
15
|
+
let alignedOffset = offset;
|
|
16
|
+
let alignedLimit = limit;
|
|
17
|
+
if (alignedOffset % 1024 !== 0) {
|
|
18
|
+
alignedOffset = Math.floor(alignedOffset / 1024) * 1024;
|
|
19
|
+
}
|
|
20
|
+
const stripStart = offset - alignedOffset;
|
|
21
|
+
if (stripStart > 0) {
|
|
22
|
+
alignedLimit += 1024 - stripStart;
|
|
23
|
+
}
|
|
24
|
+
if (alignedLimit % 1024 !== 0) {
|
|
25
|
+
alignedLimit = Math.ceil(alignedLimit / 1024) * 1024;
|
|
26
|
+
}
|
|
27
|
+
if (alignedLimit > 1048576) {
|
|
28
|
+
throw new MtArgumentError(`Limit (${alignedLimit}) is too large for chunked downloads`);
|
|
29
|
+
}
|
|
30
|
+
const stripEnd = alignedLimit - limit - stripStart;
|
|
31
|
+
const result = await client.call(
|
|
32
|
+
{
|
|
33
|
+
_: "upload.getFile",
|
|
34
|
+
location,
|
|
35
|
+
offset: alignedOffset,
|
|
36
|
+
limit: alignedLimit,
|
|
37
|
+
precise: true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
dcId,
|
|
41
|
+
maxRetryCount,
|
|
42
|
+
floodSleepThreshold,
|
|
43
|
+
abortSignal
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
assert(result._ === "upload.file");
|
|
47
|
+
let bytes = result.bytes;
|
|
48
|
+
if (stripStart > 0) {
|
|
49
|
+
bytes = bytes.subarray(stripStart);
|
|
50
|
+
}
|
|
51
|
+
if (stripEnd > 0) {
|
|
52
|
+
bytes = bytes.subarray(0, -stripEnd);
|
|
53
|
+
}
|
|
54
|
+
return bytes;
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
downloadChunk
|
|
58
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,36 +8,26 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
8
8
|
const utils = require("@fuman/utils");
|
|
9
9
|
const fileId = require("@mtcute/file-id");
|
|
10
10
|
const tl = require("@mtcute/tl");
|
|
11
|
-
const errors = require("../../../types/errors.cjs");
|
|
11
|
+
const errors$1 = require("../../../types/errors.cjs");
|
|
12
12
|
const peerUtils = require("../../../utils/peer-utils.cjs");
|
|
13
13
|
const convertFileId = require("../../utils/convert-file-id.cjs");
|
|
14
14
|
const fileUtils = require("../../utils/file-utils.cjs");
|
|
15
15
|
const fileLocation = require("../../types/files/file-location.cjs");
|
|
16
|
-
const errors
|
|
16
|
+
const errors = require("../../types/errors.cjs");
|
|
17
17
|
const SMALL_FILE_MAX_SIZE = 131072;
|
|
18
18
|
const REQUESTS_PER_CONNECTION = 3;
|
|
19
|
-
async function
|
|
20
|
-
const offset = params?.offset ?? 0;
|
|
21
|
-
if (offset % 4096 !== 0) {
|
|
22
|
-
throw new errors.MtArgumentError(`Invalid offset: ${offset}. Must be divisible by 4096`);
|
|
23
|
-
}
|
|
24
|
-
let dcId = params?.dcId;
|
|
25
|
-
let fileSize = params?.fileSize;
|
|
26
|
-
const abortSignal = params?.abortSignal;
|
|
27
|
-
let ended = false;
|
|
19
|
+
async function _normalizeFileDownloadLocation(client, input) {
|
|
28
20
|
let location;
|
|
29
21
|
if (input instanceof fileLocation.FileLocation) {
|
|
30
22
|
let locationInner = input.location;
|
|
31
23
|
if (typeof locationInner === "function") {
|
|
32
24
|
locationInner = locationInner();
|
|
33
25
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!fileSize) fileSize = input.fileSize;
|
|
40
|
-
location = locationInner;
|
|
26
|
+
return {
|
|
27
|
+
location: locationInner,
|
|
28
|
+
dcId: input.dcId,
|
|
29
|
+
fileSize: input.fileSize
|
|
30
|
+
};
|
|
41
31
|
} else if (typeof input === "string") {
|
|
42
32
|
const parsed = fileId.parseFileId(input);
|
|
43
33
|
if (parsed.location._ === "web") {
|
|
@@ -48,13 +38,12 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
48
38
|
} else {
|
|
49
39
|
location = input;
|
|
50
40
|
}
|
|
51
|
-
const isWeb = tl.tl.isAnyInputWebFileLocation(location);
|
|
52
41
|
if (location._ === "inputPeerPhotoFileLocation") {
|
|
53
42
|
if (location.peer._ === "mtcute.dummyInputPeerMinUser" || location.peer._ === "mtcute.dummyInputPeerMinChannel") {
|
|
54
43
|
const peerId = location.peer._ === "mtcute.dummyInputPeerMinUser" ? location.peer.userId : peerUtils.toggleChannelIdMark(location.peer.channelId);
|
|
55
44
|
const accessHash = await client.storage.peers.getMinAccessHash(peerId);
|
|
56
45
|
if (!accessHash) {
|
|
57
|
-
throw new errors
|
|
46
|
+
throw new errors.MtPeerNotFoundError(`Peer ${peerId} not found`);
|
|
58
47
|
}
|
|
59
48
|
location = {
|
|
60
49
|
_: "inputPeerPhotoFileLocation",
|
|
@@ -72,15 +61,41 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
72
61
|
};
|
|
73
62
|
}
|
|
74
63
|
}
|
|
64
|
+
return { location };
|
|
65
|
+
}
|
|
66
|
+
async function* downloadAsIterable(client, input, params) {
|
|
67
|
+
const offset = params?.offset ?? 0;
|
|
68
|
+
if (offset % 4096 !== 0) {
|
|
69
|
+
throw new errors$1.MtArgumentError(`Invalid offset: ${offset}. Must be divisible by 4096`);
|
|
70
|
+
}
|
|
71
|
+
const normalized = await _normalizeFileDownloadLocation(client, input);
|
|
72
|
+
const fileSize = params?.fileSize ?? normalized.fileSize;
|
|
73
|
+
const location = normalized.location;
|
|
74
|
+
if (ArrayBuffer.isView(location)) {
|
|
75
|
+
yield location;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const isWeb = tl.tl.isAnyInputWebFileLocation(location);
|
|
79
|
+
let dcId = params?.dcId ?? normalized?.dcId;
|
|
75
80
|
const primaryDcId = await client.getPrimaryDcId();
|
|
76
81
|
if (!dcId) dcId = primaryDcId;
|
|
82
|
+
const abortSignal = params?.abortSignal;
|
|
83
|
+
let ended = false;
|
|
77
84
|
const partSizeKb = params?.partSize ?? (fileSize ? fileUtils.determinePartSize(fileSize) : 64);
|
|
78
85
|
if (partSizeKb % 4 !== 0) {
|
|
79
|
-
throw new errors.MtArgumentError(`Invalid part size: ${partSizeKb}. Must be divisible by 4.`);
|
|
86
|
+
throw new errors$1.MtArgumentError(`Invalid part size: ${partSizeKb}. Must be divisible by 4.`);
|
|
80
87
|
}
|
|
81
88
|
const chunkSize = partSizeKb * 1024;
|
|
82
89
|
let limitBytes = params?.limit ?? fileSize ?? Infinity;
|
|
83
90
|
if (limitBytes === 0) return;
|
|
91
|
+
if (limitBytes !== Infinity && limitBytes !== fileSize) {
|
|
92
|
+
if (limitBytes % 4096 !== 0) {
|
|
93
|
+
throw new errors$1.MtArgumentError(`Invalid limit: ${limitBytes}. Must be divisible by 4096.`);
|
|
94
|
+
}
|
|
95
|
+
if (1048576 % limitBytes !== 0) {
|
|
96
|
+
throw new errors$1.MtArgumentError(`Invalid limit: ${limitBytes}. Must be a multiple of 1MB.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
84
99
|
let numChunks = limitBytes === Infinity ? Infinity : ~~((limitBytes + chunkSize - offset - 1) / chunkSize);
|
|
85
100
|
let nextChunkIdx = 0;
|
|
86
101
|
let nextWorkerChunkIdx = 0;
|
|
@@ -131,7 +146,7 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
131
146
|
dcId = e.newDc;
|
|
132
147
|
return downloadChunk(chunk);
|
|
133
148
|
} else if (e.is("FILEREF_UPGRADE_NEEDED")) {
|
|
134
|
-
throw new errors.MtUnsupportedError("File ref expired!");
|
|
149
|
+
throw new errors$1.MtUnsupportedError("File ref expired!");
|
|
135
150
|
} else if (e.is("MTPROTO_CLUSTER_INVALID") && dcId != null) {
|
|
136
151
|
client.log.debug("received cluster invalid error for dc %d, recreating dc", dcId);
|
|
137
152
|
await client.recreateDc(dcId);
|
|
@@ -141,7 +156,7 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
141
156
|
}
|
|
142
157
|
}
|
|
143
158
|
if (result._ === "upload.fileCdnRedirect") {
|
|
144
|
-
throw new errors.MtUnsupportedError("Received CDN redirect, which is not supported (yet)");
|
|
159
|
+
throw new errors$1.MtUnsupportedError("Received CDN redirect, which is not supported (yet)");
|
|
145
160
|
}
|
|
146
161
|
if (ended) {
|
|
147
162
|
return;
|
|
@@ -192,4 +207,5 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
192
207
|
}
|
|
193
208
|
}
|
|
194
209
|
}
|
|
210
|
+
exports._normalizeFileDownloadLocation = _normalizeFileDownloadLocation;
|
|
195
211
|
exports.downloadAsIterable = downloadAsIterable;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ITelegramClient } from '../../client.types.js';
|
|
2
2
|
import { FileDownloadLocation, FileDownloadParameters } from '../../types/index.js';
|
|
3
|
+
import { tl } from '@mtcute/tl';
|
|
4
|
+
export declare function _normalizeFileDownloadLocation(client: ITelegramClient, input: FileDownloadLocation): Promise<{
|
|
5
|
+
location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | Uint8Array<ArrayBufferLike>;
|
|
6
|
+
dcId?: number;
|
|
7
|
+
fileSize?: number;
|
|
8
|
+
}>;
|
|
3
9
|
/**
|
|
4
10
|
* Download a file and return it as an iterable, which yields file contents
|
|
5
11
|
* in chunks of a given size. Order of the chunks is guaranteed to be
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ITelegramClient } from '../../client.types.js';
|
|
2
2
|
import { FileDownloadLocation, FileDownloadParameters } from '../../types/index.js';
|
|
3
|
+
import { tl } from '@mtcute/tl';
|
|
4
|
+
export declare function _normalizeFileDownloadLocation(client: ITelegramClient, input: FileDownloadLocation): Promise<{
|
|
5
|
+
location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | Uint8Array<ArrayBufferLike>;
|
|
6
|
+
dcId?: number;
|
|
7
|
+
fileSize?: number;
|
|
8
|
+
}>;
|
|
3
9
|
/**
|
|
4
10
|
* Download a file and return it as an iterable, which yields file contents
|
|
5
11
|
* in chunks of a given size. Order of the chunks is guaranteed to be
|
|
@@ -9,28 +9,18 @@ import { FileLocation as FileLocation$1 } from "../../types/files/file-location.
|
|
|
9
9
|
import { MtPeerNotFoundError } from "../../types/errors.js";
|
|
10
10
|
const SMALL_FILE_MAX_SIZE = 131072;
|
|
11
11
|
const REQUESTS_PER_CONNECTION = 3;
|
|
12
|
-
async function
|
|
13
|
-
const offset = params?.offset ?? 0;
|
|
14
|
-
if (offset % 4096 !== 0) {
|
|
15
|
-
throw new MtArgumentError(`Invalid offset: ${offset}. Must be divisible by 4096`);
|
|
16
|
-
}
|
|
17
|
-
let dcId = params?.dcId;
|
|
18
|
-
let fileSize = params?.fileSize;
|
|
19
|
-
const abortSignal = params?.abortSignal;
|
|
20
|
-
let ended = false;
|
|
12
|
+
async function _normalizeFileDownloadLocation(client, input) {
|
|
21
13
|
let location;
|
|
22
14
|
if (input instanceof FileLocation$1) {
|
|
23
15
|
let locationInner = input.location;
|
|
24
16
|
if (typeof locationInner === "function") {
|
|
25
17
|
locationInner = locationInner();
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!fileSize) fileSize = input.fileSize;
|
|
33
|
-
location = locationInner;
|
|
19
|
+
return {
|
|
20
|
+
location: locationInner,
|
|
21
|
+
dcId: input.dcId,
|
|
22
|
+
fileSize: input.fileSize
|
|
23
|
+
};
|
|
34
24
|
} else if (typeof input === "string") {
|
|
35
25
|
const parsed = parseFileId(input);
|
|
36
26
|
if (parsed.location._ === "web") {
|
|
@@ -41,7 +31,6 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
41
31
|
} else {
|
|
42
32
|
location = input;
|
|
43
33
|
}
|
|
44
|
-
const isWeb = tl.isAnyInputWebFileLocation(location);
|
|
45
34
|
if (location._ === "inputPeerPhotoFileLocation") {
|
|
46
35
|
if (location.peer._ === "mtcute.dummyInputPeerMinUser" || location.peer._ === "mtcute.dummyInputPeerMinChannel") {
|
|
47
36
|
const peerId = location.peer._ === "mtcute.dummyInputPeerMinUser" ? location.peer.userId : toggleChannelIdMark(location.peer.channelId);
|
|
@@ -65,8 +54,26 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
65
54
|
};
|
|
66
55
|
}
|
|
67
56
|
}
|
|
57
|
+
return { location };
|
|
58
|
+
}
|
|
59
|
+
async function* downloadAsIterable(client, input, params) {
|
|
60
|
+
const offset = params?.offset ?? 0;
|
|
61
|
+
if (offset % 4096 !== 0) {
|
|
62
|
+
throw new MtArgumentError(`Invalid offset: ${offset}. Must be divisible by 4096`);
|
|
63
|
+
}
|
|
64
|
+
const normalized = await _normalizeFileDownloadLocation(client, input);
|
|
65
|
+
const fileSize = params?.fileSize ?? normalized.fileSize;
|
|
66
|
+
const location = normalized.location;
|
|
67
|
+
if (ArrayBuffer.isView(location)) {
|
|
68
|
+
yield location;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const isWeb = tl.isAnyInputWebFileLocation(location);
|
|
72
|
+
let dcId = params?.dcId ?? normalized?.dcId;
|
|
68
73
|
const primaryDcId = await client.getPrimaryDcId();
|
|
69
74
|
if (!dcId) dcId = primaryDcId;
|
|
75
|
+
const abortSignal = params?.abortSignal;
|
|
76
|
+
let ended = false;
|
|
70
77
|
const partSizeKb = params?.partSize ?? (fileSize ? determinePartSize(fileSize) : 64);
|
|
71
78
|
if (partSizeKb % 4 !== 0) {
|
|
72
79
|
throw new MtArgumentError(`Invalid part size: ${partSizeKb}. Must be divisible by 4.`);
|
|
@@ -74,6 +81,14 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
74
81
|
const chunkSize = partSizeKb * 1024;
|
|
75
82
|
let limitBytes = params?.limit ?? fileSize ?? Infinity;
|
|
76
83
|
if (limitBytes === 0) return;
|
|
84
|
+
if (limitBytes !== Infinity && limitBytes !== fileSize) {
|
|
85
|
+
if (limitBytes % 4096 !== 0) {
|
|
86
|
+
throw new MtArgumentError(`Invalid limit: ${limitBytes}. Must be divisible by 4096.`);
|
|
87
|
+
}
|
|
88
|
+
if (1048576 % limitBytes !== 0) {
|
|
89
|
+
throw new MtArgumentError(`Invalid limit: ${limitBytes}. Must be a multiple of 1MB.`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
77
92
|
let numChunks = limitBytes === Infinity ? Infinity : ~~((limitBytes + chunkSize - offset - 1) / chunkSize);
|
|
78
93
|
let nextChunkIdx = 0;
|
|
79
94
|
let nextWorkerChunkIdx = 0;
|
|
@@ -186,5 +201,6 @@ async function* downloadAsIterable(client, input, params) {
|
|
|
186
201
|
}
|
|
187
202
|
}
|
|
188
203
|
export {
|
|
204
|
+
_normalizeFileDownloadLocation,
|
|
189
205
|
downloadAsIterable
|
|
190
206
|
};
|
|
@@ -9,8 +9,8 @@ const resolvePeer = require("../users/resolve-peer.cjs");
|
|
|
9
9
|
async function reorderPinnedForumTopics(client, params) {
|
|
10
10
|
const { chatId, order, force } = params;
|
|
11
11
|
await client.call({
|
|
12
|
-
_: "
|
|
13
|
-
|
|
12
|
+
_: "messages.reorderPinnedForumTopics",
|
|
13
|
+
peer: await resolvePeer.resolvePeer(client, chatId),
|
|
14
14
|
order: order.map((it) => typeof it === "number" ? it : it.id),
|
|
15
15
|
force
|
|
16
16
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolvePeer } from "../users/resolve-peer.js";
|
|
2
2
|
async function reorderPinnedForumTopics(client, params) {
|
|
3
3
|
const { chatId, order, force } = params;
|
|
4
4
|
await client.call({
|
|
5
|
-
_: "
|
|
6
|
-
|
|
5
|
+
_: "messages.reorderPinnedForumTopics",
|
|
6
|
+
peer: await resolvePeer(client, chatId),
|
|
7
7
|
order: order.map((it) => typeof it === "number" ? it : it.id),
|
|
8
8
|
force
|
|
9
9
|
});
|
|
@@ -10,8 +10,8 @@ const resolvePeer = require("../users/resolve-peer.cjs");
|
|
|
10
10
|
async function toggleForumTopicClosed(client, parmas) {
|
|
11
11
|
const { chatId, topicId, closed, shouldDispatch } = parmas;
|
|
12
12
|
const res = await client.call({
|
|
13
|
-
_: "
|
|
14
|
-
|
|
13
|
+
_: "messages.editForumTopic",
|
|
14
|
+
peer: await resolvePeer.resolvePeer(client, chatId),
|
|
15
15
|
topicId: typeof topicId === "number" ? topicId : topicId.id,
|
|
16
16
|
closed
|
|
17
17
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { _findMessageInUpdate } from "../messages/find-in-update.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolvePeer } from "../users/resolve-peer.js";
|
|
3
3
|
async function toggleForumTopicClosed(client, parmas) {
|
|
4
4
|
const { chatId, topicId, closed, shouldDispatch } = parmas;
|
|
5
5
|
const res = await client.call({
|
|
6
|
-
_: "
|
|
7
|
-
|
|
6
|
+
_: "messages.editForumTopic",
|
|
7
|
+
peer: await resolvePeer(client, chatId),
|
|
8
8
|
topicId: typeof topicId === "number" ? topicId : topicId.id,
|
|
9
9
|
closed
|
|
10
10
|
});
|
|
@@ -9,8 +9,8 @@ const resolvePeer = require("../users/resolve-peer.cjs");
|
|
|
9
9
|
async function toggleForumTopicPinned(client, params) {
|
|
10
10
|
const { chatId, topicId, pinned } = params;
|
|
11
11
|
await client.call({
|
|
12
|
-
_: "
|
|
13
|
-
|
|
12
|
+
_: "messages.updatePinnedForumTopic",
|
|
13
|
+
peer: await resolvePeer.resolvePeer(client, chatId),
|
|
14
14
|
topicId: typeof topicId === "number" ? topicId : topicId.id,
|
|
15
15
|
pinned
|
|
16
16
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolvePeer } from "../users/resolve-peer.js";
|
|
2
2
|
async function toggleForumTopicPinned(client, params) {
|
|
3
3
|
const { chatId, topicId, pinned } = params;
|
|
4
4
|
await client.call({
|
|
5
|
-
_: "
|
|
6
|
-
|
|
5
|
+
_: "messages.updatePinnedForumTopic",
|
|
6
|
+
peer: await resolvePeer(client, chatId),
|
|
7
7
|
topicId: typeof topicId === "number" ? topicId : topicId.id,
|
|
8
8
|
pinned
|
|
9
9
|
});
|
package/highlevel/methods.d.cts
CHANGED
|
@@ -86,6 +86,7 @@ export { addContact } from './methods/contacts/add-contact.js';
|
|
|
86
86
|
export { deleteContacts } from './methods/contacts/delete-contacts.js';
|
|
87
87
|
export { getContacts } from './methods/contacts/get-contacts.js';
|
|
88
88
|
export { importContacts } from './methods/contacts/import-contacts.js';
|
|
89
|
+
export { setContactNote } from './methods/contacts/set-contact-note.js';
|
|
89
90
|
export { createFolder } from './methods/dialogs/create-folder.js';
|
|
90
91
|
export { deleteFolder } from './methods/dialogs/delete-folder.js';
|
|
91
92
|
export { editFolder } from './methods/dialogs/edit-folder.js';
|
|
@@ -98,6 +99,8 @@ export { iterDialogs } from './methods/dialogs/iter-dialogs.js';
|
|
|
98
99
|
export { joinChatlist } from './methods/dialogs/join-chatlist.js';
|
|
99
100
|
export { setFoldersOrder } from './methods/dialogs/set-folders-order.js';
|
|
100
101
|
export { downloadAsBuffer } from './methods/files/download-buffer.js';
|
|
102
|
+
export { downloadChunk } from './methods/files/download-chunk.js';
|
|
103
|
+
export { _normalizeFileDownloadLocation } from './methods/files/download-iterable.js';
|
|
101
104
|
export { downloadAsIterable } from './methods/files/download-iterable.js';
|
|
102
105
|
export { downloadAsStream } from './methods/files/download-stream.js';
|
|
103
106
|
export { _normalizeInputFile } from './methods/files/normalize-input-file.js';
|
package/highlevel/methods.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ export { addContact } from './methods/contacts/add-contact.js';
|
|
|
86
86
|
export { deleteContacts } from './methods/contacts/delete-contacts.js';
|
|
87
87
|
export { getContacts } from './methods/contacts/get-contacts.js';
|
|
88
88
|
export { importContacts } from './methods/contacts/import-contacts.js';
|
|
89
|
+
export { setContactNote } from './methods/contacts/set-contact-note.js';
|
|
89
90
|
export { createFolder } from './methods/dialogs/create-folder.js';
|
|
90
91
|
export { deleteFolder } from './methods/dialogs/delete-folder.js';
|
|
91
92
|
export { editFolder } from './methods/dialogs/edit-folder.js';
|
|
@@ -98,6 +99,8 @@ export { iterDialogs } from './methods/dialogs/iter-dialogs.js';
|
|
|
98
99
|
export { joinChatlist } from './methods/dialogs/join-chatlist.js';
|
|
99
100
|
export { setFoldersOrder } from './methods/dialogs/set-folders-order.js';
|
|
100
101
|
export { downloadAsBuffer } from './methods/files/download-buffer.js';
|
|
102
|
+
export { downloadChunk } from './methods/files/download-chunk.js';
|
|
103
|
+
export { _normalizeFileDownloadLocation } from './methods/files/download-iterable.js';
|
|
101
104
|
export { downloadAsIterable } from './methods/files/download-iterable.js';
|
|
102
105
|
export { downloadAsStream } from './methods/files/download-stream.js';
|
|
103
106
|
export { _normalizeInputFile } from './methods/files/normalize-input-file.js';
|
|
@@ -34,13 +34,17 @@ class StarGift {
|
|
|
34
34
|
return this.raw.requirePremium;
|
|
35
35
|
}
|
|
36
36
|
/** If this gift is currently sold through an auction, info about that auction. `null` otherwise */
|
|
37
|
-
get
|
|
37
|
+
get auction() {
|
|
38
38
|
if (!this.raw.auctionSlug || this.raw.giftsPerRound == null) return null;
|
|
39
39
|
return {
|
|
40
40
|
slug: this.raw.auctionSlug,
|
|
41
41
|
giftsPerRound: this.raw.giftsPerRound
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
/** @deprecated Use {@link auction} instead (typo in older versions) */
|
|
45
|
+
get action() {
|
|
46
|
+
return this.auction;
|
|
47
|
+
}
|
|
44
48
|
/** Whether this gift includes a peer color that can be applied to user's profile */
|
|
45
49
|
get hasPeerColor() {
|
|
46
50
|
return this.raw.peerColorAvailable;
|
|
@@ -29,10 +29,12 @@ export declare class StarGift {
|
|
|
29
29
|
/** Whether this gift is available only to premium users */
|
|
30
30
|
get isPremiumOnly(): boolean;
|
|
31
31
|
/** If this gift is currently sold through an auction, info about that auction. `null` otherwise */
|
|
32
|
-
get
|
|
32
|
+
get auction(): {
|
|
33
33
|
slug: string;
|
|
34
34
|
giftsPerRound: number;
|
|
35
35
|
} | null;
|
|
36
|
+
/** @deprecated Use {@link auction} instead (typo in older versions) */
|
|
37
|
+
get action(): this['auction'];
|
|
36
38
|
/** Whether this gift includes a peer color that can be applied to user's profile */
|
|
37
39
|
get hasPeerColor(): boolean;
|
|
38
40
|
/** Whether this gift is a unique gift */
|
|
@@ -29,10 +29,12 @@ export declare class StarGift {
|
|
|
29
29
|
/** Whether this gift is available only to premium users */
|
|
30
30
|
get isPremiumOnly(): boolean;
|
|
31
31
|
/** If this gift is currently sold through an auction, info about that auction. `null` otherwise */
|
|
32
|
-
get
|
|
32
|
+
get auction(): {
|
|
33
33
|
slug: string;
|
|
34
34
|
giftsPerRound: number;
|
|
35
35
|
} | null;
|
|
36
|
+
/** @deprecated Use {@link auction} instead (typo in older versions) */
|
|
37
|
+
get action(): this['auction'];
|
|
36
38
|
/** Whether this gift includes a peer color that can be applied to user's profile */
|
|
37
39
|
get hasPeerColor(): boolean;
|
|
38
40
|
/** Whether this gift is a unique gift */
|