@mtcute/core 0.30.1 → 0.30.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 (83) hide show
  1. package/highlevel/methods/files/download-iterable.cjs +80 -45
  2. package/highlevel/methods/files/download-iterable.js +80 -45
  3. package/highlevel/methods/files/normalize-input-media.cjs +1 -1
  4. package/highlevel/methods/files/normalize-input-media.js +1 -1
  5. package/highlevel/methods/files/upload-file.cjs +6 -1
  6. package/highlevel/methods/files/upload-file.js +6 -1
  7. package/highlevel/methods/messages/normalize-rich-message.cjs +12 -1
  8. package/highlevel/methods/messages/normalize-rich-message.js +12 -1
  9. package/highlevel/methods/messages/send-common.cjs +3 -2
  10. package/highlevel/methods/messages/send-common.d.cts +4 -1
  11. package/highlevel/methods/messages/send-common.d.ts +4 -1
  12. package/highlevel/methods/messages/send-common.js +3 -2
  13. package/highlevel/types/files/utils.d.cts +9 -0
  14. package/highlevel/types/files/utils.d.ts +9 -0
  15. package/highlevel/updates/manager.cjs +6 -169
  16. package/highlevel/updates/manager.js +6 -169
  17. package/highlevel/utils/index.d.cts +1 -0
  18. package/highlevel/utils/index.d.ts +1 -0
  19. package/highlevel/utils/walk-page-blocks.cjs +164 -0
  20. package/highlevel/utils/walk-page-blocks.d.cts +9 -0
  21. package/highlevel/utils/walk-page-blocks.d.ts +9 -0
  22. package/highlevel/utils/walk-page-blocks.js +159 -0
  23. package/network/authorization.cjs +1 -1
  24. package/network/authorization.js +1 -1
  25. package/network/delay-gate.cjs +29 -0
  26. package/network/delay-gate.d.cts +5 -0
  27. package/network/delay-gate.d.ts +5 -0
  28. package/network/delay-gate.js +24 -0
  29. package/network/delay-gate.test.d.cts +1 -0
  30. package/network/delay-gate.test.d.ts +1 -0
  31. package/network/message-id-store.cjs +30 -0
  32. package/network/message-id-store.d.cts +7 -0
  33. package/network/message-id-store.d.ts +7 -0
  34. package/network/message-id-store.js +25 -0
  35. package/network/message-id-store.test.d.cts +1 -0
  36. package/network/message-id-store.test.d.ts +1 -0
  37. package/network/middlewares/bundle.cjs +2 -0
  38. package/network/middlewares/bundle.d.cts +1 -0
  39. package/network/middlewares/bundle.d.ts +1 -0
  40. package/network/middlewares/bundle.js +2 -0
  41. package/network/middlewares/default.cjs +6 -1
  42. package/network/middlewares/default.js +6 -1
  43. package/network/middlewares/flood-waiter.test.d.cts +1 -0
  44. package/network/middlewares/flood-waiter.test.d.ts +1 -0
  45. package/network/middlewares/internal-errors.test.d.cts +1 -0
  46. package/network/middlewares/internal-errors.test.d.ts +1 -0
  47. package/network/middlewares/media-throttle.cjs +65 -0
  48. package/network/middlewares/media-throttle.d.cts +5 -0
  49. package/network/middlewares/media-throttle.d.ts +5 -0
  50. package/network/middlewares/media-throttle.js +60 -0
  51. package/network/middlewares/media-throttle.test.d.cts +1 -0
  52. package/network/middlewares/media-throttle.test.d.ts +1 -0
  53. package/network/middlewares/on-error.test.d.cts +1 -0
  54. package/network/middlewares/on-error.test.d.ts +1 -0
  55. package/network/middlewares/on-method.test.d.cts +1 -0
  56. package/network/middlewares/on-method.test.d.ts +1 -0
  57. package/network/mtproto-session.cjs +9 -2
  58. package/network/mtproto-session.d.cts +5 -2
  59. package/network/mtproto-session.d.ts +5 -2
  60. package/network/mtproto-session.js +9 -2
  61. package/network/multi-session-connection.cjs +7 -0
  62. package/network/multi-session-connection.d.cts +2 -0
  63. package/network/multi-session-connection.d.ts +2 -0
  64. package/network/multi-session-connection.js +7 -0
  65. package/network/network-manager.cjs +7 -1
  66. package/network/network-manager.js +7 -1
  67. package/network/resource-limiter.cjs +60 -0
  68. package/network/resource-limiter.d.cts +11 -0
  69. package/network/resource-limiter.d.ts +11 -0
  70. package/network/resource-limiter.js +55 -0
  71. package/network/resource-limiter.test.d.cts +1 -0
  72. package/network/resource-limiter.test.d.ts +1 -0
  73. package/network/server-salt.cjs +7 -3
  74. package/network/server-salt.d.cts +2 -0
  75. package/network/server-salt.d.ts +2 -0
  76. package/network/server-salt.js +7 -3
  77. package/network/session-connection.cjs +106 -20
  78. package/network/session-connection.d.cts +11 -0
  79. package/network/session-connection.d.ts +11 -0
  80. package/network/session-connection.js +106 -20
  81. package/package.json +1 -1
  82. package/utils.cjs +2 -0
  83. package/utils.js +2 -0
@@ -0,0 +1,159 @@
1
+ import { assertNever } from "../../types/utils.js";
2
+ function walkRichText(text, visitor) {
3
+ if (!text) return;
4
+ visitor.richText?.(text);
5
+ switch (text._) {
6
+ case "textEmpty":
7
+ case "textPlain":
8
+ case "textEmail":
9
+ case "textPhone":
10
+ case "textImage":
11
+ case "textMath":
12
+ case "textCustomEmoji":
13
+ break;
14
+ case "textBold":
15
+ case "textItalic":
16
+ case "textUnderline":
17
+ case "textStrike":
18
+ case "textFixed":
19
+ case "textUrl":
20
+ case "textSubscript":
21
+ case "textSuperscript":
22
+ case "textMarked":
23
+ case "textAnchor":
24
+ case "textSpoiler":
25
+ case "textMention":
26
+ case "textHashtag":
27
+ case "textBotCommand":
28
+ case "textCashtag":
29
+ case "textAutoUrl":
30
+ case "textAutoEmail":
31
+ case "textAutoPhone":
32
+ case "textBankCard":
33
+ case "textDate":
34
+ case "textMentionName":
35
+ walkRichText(text.text, visitor);
36
+ break;
37
+ case "textConcat":
38
+ for (const child of text.texts) walkRichText(child, visitor);
39
+ break;
40
+ default:
41
+ assertNever();
42
+ }
43
+ }
44
+ function walkPageCaption(caption, visitor) {
45
+ if (!caption) return;
46
+ walkRichText(caption.text, visitor);
47
+ walkRichText(caption.credit, visitor);
48
+ }
49
+ function walkPageBlock(block, visitor) {
50
+ if (!block) return;
51
+ visitor.pageBlock?.(block);
52
+ switch (block._) {
53
+ case "pageBlockUnsupported":
54
+ case "pageBlockDivider":
55
+ case "pageBlockAnchor":
56
+ case "pageBlockMath":
57
+ break;
58
+ case "pageBlockTitle":
59
+ case "pageBlockSubtitle":
60
+ case "pageBlockHeader":
61
+ case "pageBlockSubheader":
62
+ case "pageBlockParagraph":
63
+ case "pageBlockPreformatted":
64
+ case "pageBlockFooter":
65
+ case "pageBlockKicker":
66
+ case "pageBlockThinking":
67
+ case "pageBlockHeading1":
68
+ case "pageBlockHeading2":
69
+ case "pageBlockHeading3":
70
+ case "pageBlockHeading4":
71
+ case "pageBlockHeading5":
72
+ case "pageBlockHeading6":
73
+ walkRichText(block.text, visitor);
74
+ break;
75
+ case "pageBlockAuthorDate":
76
+ walkRichText(block.author, visitor);
77
+ break;
78
+ case "pageBlockList":
79
+ for (const item of block.items) {
80
+ switch (item._) {
81
+ case "pageListItemText":
82
+ walkRichText(item.text, visitor);
83
+ break;
84
+ case "pageListItemBlocks":
85
+ for (const block2 of item.blocks) walkPageBlock(block2, visitor);
86
+ break;
87
+ default:
88
+ assertNever();
89
+ }
90
+ }
91
+ break;
92
+ case "pageBlockOrderedList":
93
+ for (const item of block.items) {
94
+ switch (item._) {
95
+ case "pageListOrderedItemText":
96
+ walkRichText(item.text, visitor);
97
+ break;
98
+ case "pageListOrderedItemBlocks":
99
+ for (const block2 of item.blocks) walkPageBlock(block2, visitor);
100
+ break;
101
+ default:
102
+ assertNever();
103
+ }
104
+ }
105
+ break;
106
+ case "pageBlockBlockquote":
107
+ case "pageBlockPullquote":
108
+ walkRichText(block.text, visitor);
109
+ walkRichText(block.caption, visitor);
110
+ break;
111
+ case "pageBlockPhoto":
112
+ case "pageBlockVideo":
113
+ case "pageBlockEmbed":
114
+ case "pageBlockAudio":
115
+ case "pageBlockMap":
116
+ case "inputPageBlockMap":
117
+ walkPageCaption(block.caption, visitor);
118
+ break;
119
+ case "pageBlockCover":
120
+ walkPageBlock(block.cover, visitor);
121
+ break;
122
+ case "pageBlockEmbedPost":
123
+ for (const child of block.blocks) walkPageBlock(child, visitor);
124
+ walkPageCaption(block.caption, visitor);
125
+ break;
126
+ case "pageBlockCollage":
127
+ case "pageBlockSlideshow":
128
+ for (const child of block.items) walkPageBlock(child, visitor);
129
+ walkPageCaption(block.caption, visitor);
130
+ break;
131
+ case "pageBlockChannel":
132
+ break;
133
+ case "pageBlockTable":
134
+ walkRichText(block.title, visitor);
135
+ for (const row of block.rows) {
136
+ for (const cell of row.cells) walkRichText(cell.text, visitor);
137
+ }
138
+ break;
139
+ case "pageBlockDetails":
140
+ for (const child of block.blocks) walkPageBlock(child, visitor);
141
+ walkRichText(block.title, visitor);
142
+ break;
143
+ case "pageBlockRelatedArticles":
144
+ walkRichText(block.title, visitor);
145
+ break;
146
+ case "pageBlockBlockquoteBlocks":
147
+ for (const child of block.blocks) walkPageBlock(child, visitor);
148
+ walkRichText(block.caption, visitor);
149
+ break;
150
+ default:
151
+ assertNever();
152
+ }
153
+ }
154
+ function walkPageBlocks(blocks, visitor) {
155
+ for (const block of blocks) walkPageBlock(block, visitor);
156
+ }
157
+ export {
158
+ walkPageBlocks
159
+ };
@@ -240,7 +240,7 @@ async function doAuthorization(connection, crypto, expiresIn) {
240
240
  }
241
241
  const dhPrime = utils.bigint.fromBytes(serverDhInner.dhPrime);
242
242
  const timeOffset = serverDhInner.serverTime - Math.floor(performance.now() / 1e3);
243
- session.updateTimeOffset(timeOffset);
243
+ session.updateTimeOffset(timeOffset, true);
244
244
  const g = BigInt(serverDhInner.g);
245
245
  const gA = utils.bigint.fromBytes(serverDhInner.gA);
246
246
  checkDhPrime(crypto, log, dhPrime, serverDhInner.g);
@@ -233,7 +233,7 @@ async function doAuthorization(connection, crypto, expiresIn) {
233
233
  }
234
234
  const dhPrime = bigint.fromBytes(serverDhInner.dhPrime);
235
235
  const timeOffset = serverDhInner.serverTime - Math.floor(performance.now() / 1e3);
236
- session.updateTimeOffset(timeOffset);
236
+ session.updateTimeOffset(timeOffset, true);
237
237
  const g = BigInt(serverDhInner.g);
238
238
  const gA = bigint.fromBytes(serverDhInner.gA);
239
239
  checkDhPrime(crypto, log, dhPrime, serverDhInner.g);
@@ -0,0 +1,29 @@
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 miscUtils = require("../utils/misc-utils.cjs");
10
+ const INITIAL_DELAY_MS = 50;
11
+ const MIN_DELAY_MS = 3;
12
+ const DELAY_DECAY = 0.8;
13
+ class DownloadDelayGate {
14
+ _nextAt = 0;
15
+ _delay = INITIAL_DELAY_MS;
16
+ wait(signal) {
17
+ const now = performance.now();
18
+ const at = Math.max(now, this._nextAt);
19
+ this._nextAt = at + this._delay;
20
+ this._delay = Math.max(this._delay * DELAY_DECAY, MIN_DELAY_MS);
21
+ const ms = at - now;
22
+ if (ms <= 0) return Promise.resolve();
23
+ if (signal) return miscUtils.sleepWithAbort(ms, signal);
24
+ return new Promise((resolve) => {
25
+ utils.timers.setTimeout(resolve, ms);
26
+ });
27
+ }
28
+ }
29
+ exports.DownloadDelayGate = DownloadDelayGate;
@@ -0,0 +1,5 @@
1
+ export declare class DownloadDelayGate {
2
+ private _nextAt;
3
+ private _delay;
4
+ wait(signal?: AbortSignal): Promise<void>;
5
+ }
@@ -0,0 +1,5 @@
1
+ export declare class DownloadDelayGate {
2
+ private _nextAt;
3
+ private _delay;
4
+ wait(signal?: AbortSignal): Promise<void>;
5
+ }
@@ -0,0 +1,24 @@
1
+ import { timers } from "@fuman/utils";
2
+ import { sleepWithAbort } from "../utils/misc-utils.js";
3
+ const INITIAL_DELAY_MS = 50;
4
+ const MIN_DELAY_MS = 3;
5
+ const DELAY_DECAY = 0.8;
6
+ class DownloadDelayGate {
7
+ _nextAt = 0;
8
+ _delay = INITIAL_DELAY_MS;
9
+ wait(signal) {
10
+ const now = performance.now();
11
+ const at = Math.max(now, this._nextAt);
12
+ this._nextAt = at + this._delay;
13
+ this._delay = Math.max(this._delay * DELAY_DECAY, MIN_DELAY_MS);
14
+ const ms = at - now;
15
+ if (ms <= 0) return Promise.resolve();
16
+ if (signal) return sleepWithAbort(ms, signal);
17
+ return new Promise((resolve) => {
18
+ timers.setTimeout(resolve, ms);
19
+ });
20
+ }
21
+ }
22
+ export {
23
+ DownloadDelayGate
24
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
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 longUtils = require("../utils/long-utils.cjs");
9
+ const sortedArray = require("../utils/sorted-array.cjs");
10
+ const MAX_SAVED_MESSAGE_IDS = 1e3;
11
+ class MessageIdStore {
12
+ _ids = new sortedArray.SortedArray([], longUtils.compareLongs);
13
+ add(msgId) {
14
+ const ids = this._ids;
15
+ if (ids.index(msgId) !== -1) return false;
16
+ if (ids.length >= MAX_SAVED_MESSAGE_IDS && longUtils.compareLongs(ids.raw[0], msgId) > 0) {
17
+ return false;
18
+ }
19
+ ids.insert(msgId);
20
+ if (ids.length > MAX_SAVED_MESSAGE_IDS) ids.raw.shift();
21
+ return true;
22
+ }
23
+ has(msgId) {
24
+ return this._ids.index(msgId) !== -1;
25
+ }
26
+ clear() {
27
+ this._ids.clear();
28
+ }
29
+ }
30
+ exports.MessageIdStore = MessageIdStore;
@@ -0,0 +1,7 @@
1
+ import { default as Long } from 'long';
2
+ export declare class MessageIdStore {
3
+ private _ids;
4
+ add(msgId: Long): boolean;
5
+ has(msgId: Long): boolean;
6
+ clear(): void;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { default as Long } from 'long';
2
+ export declare class MessageIdStore {
3
+ private _ids;
4
+ add(msgId: Long): boolean;
5
+ has(msgId: Long): boolean;
6
+ clear(): void;
7
+ }
@@ -0,0 +1,25 @@
1
+ import { compareLongs } from "../utils/long-utils.js";
2
+ import { SortedArray } from "../utils/sorted-array.js";
3
+ const MAX_SAVED_MESSAGE_IDS = 1e3;
4
+ class MessageIdStore {
5
+ _ids = new SortedArray([], compareLongs);
6
+ add(msgId) {
7
+ const ids = this._ids;
8
+ if (ids.index(msgId) !== -1) return false;
9
+ if (ids.length >= MAX_SAVED_MESSAGE_IDS && compareLongs(ids.raw[0], msgId) > 0) {
10
+ return false;
11
+ }
12
+ ids.insert(msgId);
13
+ if (ids.length > MAX_SAVED_MESSAGE_IDS) ids.raw.shift();
14
+ return true;
15
+ }
16
+ has(msgId) {
17
+ return this._ids.index(msgId) !== -1;
18
+ }
19
+ clear() {
20
+ this._ids.clear();
21
+ }
22
+ }
23
+ export {
24
+ MessageIdStore
25
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -8,10 +8,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
8
  const _default = require("./default.cjs");
9
9
  const floodWaiter = require("./flood-waiter.cjs");
10
10
  const internalErrors = require("./internal-errors.cjs");
11
+ const mediaThrottle = require("./media-throttle.cjs");
11
12
  const onError = require("./on-error.cjs");
12
13
  const onMethod = require("./on-method.cjs");
13
14
  exports.basic = _default.basic;
14
15
  exports.floodWaiter = floodWaiter.floodWaiter;
15
16
  exports.internalErrorsHandler = internalErrors.internalErrorsHandler;
17
+ exports.mediaThrottle = mediaThrottle.mediaThrottle;
16
18
  exports.onRpcError = onError.onRpcError;
17
19
  exports.onMethod = onMethod.onMethod;
@@ -1,5 +1,6 @@
1
1
  export * from './default.js';
2
2
  export * from './flood-waiter.js';
3
3
  export * from './internal-errors.js';
4
+ export * from './media-throttle.js';
4
5
  export * from './on-error.js';
5
6
  export * from './on-method.js';
@@ -1,5 +1,6 @@
1
1
  export * from './default.js';
2
2
  export * from './flood-waiter.js';
3
3
  export * from './internal-errors.js';
4
+ export * from './media-throttle.js';
4
5
  export * from './on-error.js';
5
6
  export * from './on-method.js';
@@ -1,12 +1,14 @@
1
1
  import { basic } from "./default.js";
2
2
  import { floodWaiter } from "./flood-waiter.js";
3
3
  import { internalErrorsHandler } from "./internal-errors.js";
4
+ import { mediaThrottle } from "./media-throttle.js";
4
5
  import { onRpcError } from "./on-error.js";
5
6
  import { onMethod } from "./on-method.js";
6
7
  export {
7
8
  basic,
8
9
  floodWaiter,
9
10
  internalErrorsHandler,
11
+ mediaThrottle,
10
12
  onMethod,
11
13
  onRpcError
12
14
  };
@@ -7,7 +7,12 @@ if (typeof globalThis !== "undefined" && !globalThis._MTCUTE_CJS_DEPRECATION_WAR
7
7
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
8
  const floodWaiter = require("./flood-waiter.cjs");
9
9
  const internalErrors = require("./internal-errors.cjs");
10
+ const mediaThrottle = require("./media-throttle.cjs");
10
11
  function basic(options) {
11
- return [floodWaiter.floodWaiter(options?.floodWaiter ?? {}), internalErrors.internalErrorsHandler(options?.internalErrors ?? {})];
12
+ return [
13
+ mediaThrottle.mediaThrottle(),
14
+ floodWaiter.floodWaiter(options?.floodWaiter ?? {}),
15
+ internalErrors.internalErrorsHandler(options?.internalErrors ?? {})
16
+ ];
12
17
  }
13
18
  exports.basic = basic;
@@ -1,7 +1,12 @@
1
1
  import { floodWaiter } from "./flood-waiter.js";
2
2
  import { internalErrorsHandler } from "./internal-errors.js";
3
+ import { mediaThrottle } from "./media-throttle.js";
3
4
  function basic(options) {
4
- return [floodWaiter(options?.floodWaiter ?? {}), internalErrorsHandler(options?.internalErrors ?? {})];
5
+ return [
6
+ mediaThrottle(),
7
+ floodWaiter(options?.floodWaiter ?? {}),
8
+ internalErrorsHandler(options?.internalErrors ?? {})
9
+ ];
5
10
  }
6
11
  export {
7
12
  basic
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,65 @@
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 abortSignal = require("../../utils/abort-signal.cjs");
9
+ const resourceLimiter = require("../resource-limiter.cjs");
10
+ const DOWNLOAD_RESOURCE_LIMIT = 2 * 1024 * 1024;
11
+ const DOWNLOAD_RESOURCE_LIMIT_PREMIUM = 16 * 1024 * 1024;
12
+ const UPLOAD_RESOURCE_LIMIT = 4 * 1024 * 1024;
13
+ function defaultResourceLimit(kind, isPremium) {
14
+ if (kind === "upload") return UPLOAD_RESOURCE_LIMIT;
15
+ return isPremium ? DOWNLOAD_RESOURCE_LIMIT_PREMIUM : DOWNLOAD_RESOURCE_LIMIT;
16
+ }
17
+ function mediaThrottle(params) {
18
+ const { getResourceLimit = defaultResourceLimit } = params ?? {};
19
+ const limiters = /* @__PURE__ */ new Map();
20
+ const getLimiter = (kind, dcId, isPremium) => {
21
+ let byDc = limiters.get(kind);
22
+ if (!byDc) {
23
+ byDc = /* @__PURE__ */ new Map();
24
+ limiters.set(kind, byDc);
25
+ }
26
+ const max = getResourceLimit(kind, isPremium);
27
+ let limiter = byDc.get(dcId);
28
+ if (!limiter) {
29
+ limiter = new resourceLimiter.ResourceLimiter(max);
30
+ byDc.set(dcId, limiter);
31
+ } else if (limiter.max !== max) {
32
+ limiter.setMax(max);
33
+ }
34
+ return limiter;
35
+ };
36
+ return async (ctx, next) => {
37
+ let kind;
38
+ let bytes = 0;
39
+ switch (ctx.request._) {
40
+ case "upload.getFile":
41
+ case "upload.getWebFile":
42
+ kind = ctx.params?.kind ?? "download";
43
+ bytes = ctx.request.limit;
44
+ break;
45
+ case "upload.saveFilePart":
46
+ case "upload.saveBigFilePart":
47
+ kind = "upload";
48
+ bytes = ctx.request.bytes.length;
49
+ break;
50
+ }
51
+ if (kind === void 0) return next(ctx);
52
+ const dcId = ctx.params?.dcId ?? ctx.manager.getPrimaryDcId();
53
+ const limiter = getLimiter(kind, dcId, ctx.manager.params.isPremium);
54
+ if (!limiter.tryAcquire(bytes)) {
55
+ const abortSignal$1 = abortSignal.combineAbortSignals(ctx.manager.params.stopSignal, ctx.params?.abortSignal);
56
+ await limiter.acquire(bytes, abortSignal$1);
57
+ }
58
+ try {
59
+ return await next(ctx);
60
+ } finally {
61
+ limiter.release(bytes);
62
+ }
63
+ };
64
+ }
65
+ exports.mediaThrottle = mediaThrottle;
@@ -0,0 +1,5 @@
1
+ import { ConnectionKind, RpcCallMiddleware } from '../network-manager.js';
2
+ export interface MediaThrottleOptions {
3
+ getResourceLimit?: (kind: ConnectionKind, isPremium: boolean) => number;
4
+ }
5
+ export declare function mediaThrottle(params?: MediaThrottleOptions): RpcCallMiddleware;
@@ -0,0 +1,5 @@
1
+ import { ConnectionKind, RpcCallMiddleware } from '../network-manager.js';
2
+ export interface MediaThrottleOptions {
3
+ getResourceLimit?: (kind: ConnectionKind, isPremium: boolean) => number;
4
+ }
5
+ export declare function mediaThrottle(params?: MediaThrottleOptions): RpcCallMiddleware;
@@ -0,0 +1,60 @@
1
+ import { combineAbortSignals } from "../../utils/abort-signal.js";
2
+ import { ResourceLimiter } from "../resource-limiter.js";
3
+ const DOWNLOAD_RESOURCE_LIMIT = 2 * 1024 * 1024;
4
+ const DOWNLOAD_RESOURCE_LIMIT_PREMIUM = 16 * 1024 * 1024;
5
+ const UPLOAD_RESOURCE_LIMIT = 4 * 1024 * 1024;
6
+ function defaultResourceLimit(kind, isPremium) {
7
+ if (kind === "upload") return UPLOAD_RESOURCE_LIMIT;
8
+ return isPremium ? DOWNLOAD_RESOURCE_LIMIT_PREMIUM : DOWNLOAD_RESOURCE_LIMIT;
9
+ }
10
+ function mediaThrottle(params) {
11
+ const { getResourceLimit = defaultResourceLimit } = params ?? {};
12
+ const limiters = /* @__PURE__ */ new Map();
13
+ const getLimiter = (kind, dcId, isPremium) => {
14
+ let byDc = limiters.get(kind);
15
+ if (!byDc) {
16
+ byDc = /* @__PURE__ */ new Map();
17
+ limiters.set(kind, byDc);
18
+ }
19
+ const max = getResourceLimit(kind, isPremium);
20
+ let limiter = byDc.get(dcId);
21
+ if (!limiter) {
22
+ limiter = new ResourceLimiter(max);
23
+ byDc.set(dcId, limiter);
24
+ } else if (limiter.max !== max) {
25
+ limiter.setMax(max);
26
+ }
27
+ return limiter;
28
+ };
29
+ return async (ctx, next) => {
30
+ let kind;
31
+ let bytes = 0;
32
+ switch (ctx.request._) {
33
+ case "upload.getFile":
34
+ case "upload.getWebFile":
35
+ kind = ctx.params?.kind ?? "download";
36
+ bytes = ctx.request.limit;
37
+ break;
38
+ case "upload.saveFilePart":
39
+ case "upload.saveBigFilePart":
40
+ kind = "upload";
41
+ bytes = ctx.request.bytes.length;
42
+ break;
43
+ }
44
+ if (kind === void 0) return next(ctx);
45
+ const dcId = ctx.params?.dcId ?? ctx.manager.getPrimaryDcId();
46
+ const limiter = getLimiter(kind, dcId, ctx.manager.params.isPremium);
47
+ if (!limiter.tryAcquire(bytes)) {
48
+ const abortSignal = combineAbortSignals(ctx.manager.params.stopSignal, ctx.params?.abortSignal);
49
+ await limiter.acquire(bytes, abortSignal);
50
+ }
51
+ try {
52
+ return await next(ctx);
53
+ } finally {
54
+ limiter.release(bytes);
55
+ }
56
+ };
57
+ }
58
+ export {
59
+ mediaThrottle
60
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -12,6 +12,7 @@ const longUtils = require("../utils/long-utils.cjs");
12
12
  const miscUtils = require("../utils/misc-utils.cjs");
13
13
  const sortedArray = require("../utils/sorted-array.cjs");
14
14
  const authKey = require("./auth-key.cjs");
15
+ const messageIdStore = require("./message-id-store.cjs");
15
16
  const errors = require("../types/errors.cjs");
16
17
  class MtprotoSession {
17
18
  constructor(_crypto, log, _readerMap, _writerMap, _salts) {
@@ -21,6 +22,7 @@ class MtprotoSession {
21
22
  this._writerMap = _writerMap;
22
23
  this._salts = _salts;
23
24
  this.log.prefix = `[SESSION ${this._sessionId.toString(16)}] `;
25
+ this._salts.setTimeSource(this.getServerTime.bind(this));
24
26
  this._authKey = new authKey.AuthKey(_crypto, log, _readerMap);
25
27
  this._authKeyTemp = new authKey.AuthKey(_crypto, log, _readerMap);
26
28
  this._authKeyTempSecondary = new authKey.AuthKey(_crypto, log, _readerMap);
@@ -35,7 +37,7 @@ class MtprotoSession {
35
37
  /// state ///
36
38
  // recent msg ids
37
39
  recentOutgoingMsgIds = new utils.LruSet(1e3, longUtils.LongSet);
38
- recentIncomingMsgIds = new utils.LruSet(1e3, longUtils.LongSet);
40
+ recentIncomingMsgIds = new messageIdStore.MessageIdStore();
39
41
  // <deno-tsignore>
40
42
  recentStateRequests = new utils.LruMap(1e3, longUtils.LongMap);
41
43
  // queues
@@ -58,6 +60,7 @@ class MtprotoSession {
58
60
  lastPingRtt = Number.NaN;
59
61
  lastPingTime = 0;
60
62
  lastPingMsgId = Long.ZERO;
63
+ lastActivityTime = 0;
61
64
  lastSessionCreatedUid = Long.ZERO;
62
65
  initConnectionCalled = false;
63
66
  authorizationPending = false;
@@ -80,11 +83,15 @@ class MtprotoSession {
80
83
  this._authKeyTemp.reset();
81
84
  this._authKeyTempSecondary.reset();
82
85
  }
83
- updateTimeOffset(offset) {
86
+ updateTimeOffset(offset, force = false) {
87
+ if (!force && offset <= this._timeOffset) return;
84
88
  this.log.debug("time offset updated: %d", offset);
85
89
  this._timeOffset = offset;
86
90
  this._lastMessageId = Long.ZERO;
87
91
  }
92
+ getServerTime() {
93
+ return Math.floor(performance.now() / 1e3) + this._timeOffset;
94
+ }
88
95
  /**
89
96
  * Reset session state and generate a new session ID.
90
97
  *