@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.
Files changed (35) hide show
  1. package/client.cjs +12 -0
  2. package/client.js +13 -1
  3. package/highlevel/client.d.cts +131 -90
  4. package/highlevel/client.d.ts +131 -90
  5. package/highlevel/client.test.d.cts +1 -0
  6. package/highlevel/client.test.d.ts +1 -0
  7. package/highlevel/methods/contacts/set-contact-note.cjs +21 -0
  8. package/highlevel/methods/contacts/set-contact-note.js +16 -0
  9. package/highlevel/methods/files/download-chunk.cjs +63 -0
  10. package/highlevel/methods/files/download-chunk.d.cts +29 -0
  11. package/highlevel/methods/files/download-chunk.d.ts +29 -0
  12. package/highlevel/methods/files/download-chunk.js +58 -0
  13. package/highlevel/methods/files/download-chunk.test.d.cts +1 -0
  14. package/highlevel/methods/files/download-chunk.test.d.ts +1 -0
  15. package/highlevel/methods/files/download-iterable.cjs +39 -23
  16. package/highlevel/methods/files/download-iterable.d.cts +6 -0
  17. package/highlevel/methods/files/download-iterable.d.ts +6 -0
  18. package/highlevel/methods/files/download-iterable.js +33 -17
  19. package/highlevel/methods/forums/reorder-pinned-forum-topics.cjs +2 -2
  20. package/highlevel/methods/forums/reorder-pinned-forum-topics.js +3 -3
  21. package/highlevel/methods/forums/toggle-forum-topic-closed.cjs +2 -2
  22. package/highlevel/methods/forums/toggle-forum-topic-closed.js +3 -3
  23. package/highlevel/methods/forums/toggle-forum-topic-pinned.cjs +2 -2
  24. package/highlevel/methods/forums/toggle-forum-topic-pinned.js +3 -3
  25. package/highlevel/methods.d.cts +3 -0
  26. package/highlevel/methods.d.ts +3 -0
  27. package/highlevel/types/premium/star-gift.cjs +5 -1
  28. package/highlevel/types/premium/star-gift.d.cts +3 -1
  29. package/highlevel/types/premium/star-gift.d.ts +3 -1
  30. package/highlevel/types/premium/star-gift.js +5 -1
  31. package/methods.cjs +5 -0
  32. package/methods.js +6 -1
  33. package/network/network-manager.cjs +1 -1
  34. package/network/network-manager.js +1 -1
  35. 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$1 = require("../../types/errors.cjs");
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* downloadAsIterable(client, input, params) {
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
- if (ArrayBuffer.isView(locationInner)) {
35
- yield locationInner;
36
- return;
37
- }
38
- if (!dcId) dcId = input.dcId;
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$1.MtPeerNotFoundError(`Peer ${peerId} not found`);
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* downloadAsIterable(client, input, params) {
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
- if (ArrayBuffer.isView(locationInner)) {
28
- yield locationInner;
29
- return;
30
- }
31
- if (!dcId) dcId = input.dcId;
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
- _: "channels.reorderPinnedForumTopics",
13
- channel: await resolvePeer.resolveChannel(client, chatId),
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 { resolveChannel } from "../users/resolve-peer.js";
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
- _: "channels.reorderPinnedForumTopics",
6
- channel: await resolveChannel(client, chatId),
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
- _: "channels.editForumTopic",
14
- channel: await resolvePeer.resolveChannel(client, chatId),
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 { resolveChannel } from "../users/resolve-peer.js";
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
- _: "channels.editForumTopic",
7
- channel: await resolveChannel(client, chatId),
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
- _: "channels.updatePinnedForumTopic",
13
- channel: await resolvePeer.resolveChannel(client, chatId),
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 { resolveChannel } from "../users/resolve-peer.js";
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
- _: "channels.updatePinnedForumTopic",
6
- channel: await resolveChannel(client, chatId),
5
+ _: "messages.updatePinnedForumTopic",
6
+ peer: await resolvePeer(client, chatId),
7
7
  topicId: typeof topicId === "number" ? topicId : topicId.id,
8
8
  pinned
9
9
  });
@@ -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';
@@ -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 action() {
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 action(): {
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 action(): {
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 */