@mtcute/core 0.29.6 → 0.30.0

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 (118) hide show
  1. package/client.cjs +8 -0
  2. package/client.js +8 -0
  3. package/highlevel/client.d.cts +23 -7
  4. package/highlevel/client.d.ts +23 -7
  5. package/highlevel/methods/bots/answer-bot-guest-chat-query.cjs +26 -0
  6. package/highlevel/methods/bots/answer-bot-guest-chat-query.d.cts +12 -0
  7. package/highlevel/methods/bots/answer-bot-guest-chat-query.d.ts +12 -0
  8. package/highlevel/methods/bots/answer-bot-guest-chat-query.js +21 -0
  9. package/highlevel/methods/chats/join-chat.cjs +38 -16
  10. package/highlevel/methods/chats/join-chat.d.cts +20 -6
  11. package/highlevel/methods/chats/join-chat.d.ts +20 -6
  12. package/highlevel/methods/chats/join-chat.js +38 -16
  13. package/highlevel/methods/chats/save-draft.d.cts +4 -1
  14. package/highlevel/methods/chats/save-draft.d.ts +4 -1
  15. package/highlevel/methods/messages/send-copy-group.cjs +5 -9
  16. package/highlevel/methods/messages/send-copy-group.js +5 -9
  17. package/highlevel/methods.d.cts +3 -0
  18. package/highlevel/methods.d.ts +3 -0
  19. package/highlevel/storage/service/peers.cjs +2 -0
  20. package/highlevel/storage/service/peers.js +2 -0
  21. package/highlevel/types/files/utils.d.cts +1 -1
  22. package/highlevel/types/files/utils.d.ts +1 -1
  23. package/highlevel/types/media/poll.cjs +14 -0
  24. package/highlevel/types/media/poll.d.cts +6 -0
  25. package/highlevel/types/media/poll.d.ts +6 -0
  26. package/highlevel/types/media/poll.js +14 -0
  27. package/highlevel/types/messages/index.d.cts +1 -0
  28. package/highlevel/types/messages/index.d.ts +1 -0
  29. package/highlevel/types/messages/message.cjs +15 -1
  30. package/highlevel/types/messages/message.d.cts +8 -0
  31. package/highlevel/types/messages/message.d.ts +8 -0
  32. package/highlevel/types/messages/message.js +15 -1
  33. package/highlevel/types/messages/rich-message.cjs +50 -0
  34. package/highlevel/types/messages/rich-message.d.cts +18 -0
  35. package/highlevel/types/messages/rich-message.d.ts +18 -0
  36. package/highlevel/types/messages/rich-message.js +45 -0
  37. package/highlevel/types/peers/chat-permissions.cjs +6 -0
  38. package/highlevel/types/peers/chat-permissions.d.cts +4 -0
  39. package/highlevel/types/peers/chat-permissions.d.ts +4 -0
  40. package/highlevel/types/peers/chat-permissions.js +6 -0
  41. package/highlevel/types/peers/full-chat.cjs +6 -0
  42. package/highlevel/types/peers/full-chat.d.cts +2 -0
  43. package/highlevel/types/peers/full-chat.d.ts +2 -0
  44. package/highlevel/types/peers/full-chat.js +6 -0
  45. package/highlevel/types/peers/user.cjs +8 -0
  46. package/highlevel/types/peers/user.d.cts +4 -0
  47. package/highlevel/types/peers/user.d.ts +4 -0
  48. package/highlevel/types/peers/user.js +8 -0
  49. package/highlevel/types/updates/bot-guest-chat-query.cjs +39 -0
  50. package/highlevel/types/updates/bot-guest-chat-query.d.cts +21 -0
  51. package/highlevel/types/updates/bot-guest-chat-query.d.ts +21 -0
  52. package/highlevel/types/updates/bot-guest-chat-query.js +34 -0
  53. package/highlevel/types/updates/index.d.cts +5 -1
  54. package/highlevel/types/updates/index.d.ts +5 -1
  55. package/highlevel/types/updates/parse-update.cjs +3 -0
  56. package/highlevel/types/updates/parse-update.js +3 -0
  57. package/highlevel/types/updates/user-typing-update.cjs +2 -0
  58. package/highlevel/types/updates/user-typing-update.js +2 -0
  59. package/highlevel/updates/manager.cjs +214 -3
  60. package/highlevel/updates/manager.d.cts +1 -0
  61. package/highlevel/updates/manager.d.ts +1 -0
  62. package/highlevel/updates/manager.js +214 -3
  63. package/highlevel/utils/inspectable.cjs +1 -0
  64. package/highlevel/utils/inspectable.d.cts +1 -0
  65. package/highlevel/utils/inspectable.d.ts +1 -0
  66. package/highlevel/utils/inspectable.js +1 -0
  67. package/index.cjs +4 -0
  68. package/index.js +4 -0
  69. package/methods.cjs +2 -0
  70. package/methods.js +2 -0
  71. package/network/flood-control.cjs +149 -0
  72. package/network/flood-control.d.cts +79 -0
  73. package/network/flood-control.d.ts +79 -0
  74. package/network/flood-control.js +144 -0
  75. package/network/flood-control.test.d.cts +1 -0
  76. package/network/flood-control.test.d.ts +1 -0
  77. package/network/mtproto-session.cjs +1 -21
  78. package/network/mtproto-session.d.cts +1 -5
  79. package/network/mtproto-session.d.ts +1 -5
  80. package/network/mtproto-session.js +2 -22
  81. package/network/multi-session-connection.cjs +26 -16
  82. package/network/multi-session-connection.d.cts +1 -1
  83. package/network/multi-session-connection.d.ts +1 -1
  84. package/network/multi-session-connection.js +26 -16
  85. package/network/multi-session-connection.test.d.cts +1 -0
  86. package/network/multi-session-connection.test.d.ts +1 -0
  87. package/network/network-manager.cjs +3 -2
  88. package/network/network-manager.d.cts +12 -0
  89. package/network/network-manager.d.ts +12 -0
  90. package/network/network-manager.js +3 -2
  91. package/network/persistent-connection.cjs +25 -1
  92. package/network/persistent-connection.d.cts +5 -0
  93. package/network/persistent-connection.d.ts +5 -0
  94. package/network/persistent-connection.js +25 -1
  95. package/network/session-connection.cjs +5 -10
  96. package/network/session-connection.d.cts +0 -2
  97. package/network/session-connection.d.ts +0 -2
  98. package/network/session-connection.js +5 -10
  99. package/package.json +1 -1
  100. package/tl/api-schema.json +1 -1
  101. package/tl/binary/reader.cjs +257 -62
  102. package/tl/binary/reader.js +257 -62
  103. package/tl/binary/writer.cjs +837 -212
  104. package/tl/binary/writer.js +837 -212
  105. package/tl/compat/reader.cjs +31 -0
  106. package/tl/compat/reader.js +31 -0
  107. package/tl/index.d.cts +2478 -186
  108. package/tl/index.d.ts +2478 -186
  109. package/tl/inner-tl.cjs +34 -10
  110. package/tl/inner-tl.js +34 -10
  111. package/utils/binary/compat.cjs +84 -0
  112. package/utils/binary/compat.js +84 -0
  113. package/utils/index.d.cts +1 -0
  114. package/utils/index.d.ts +1 -0
  115. package/utils/long-utils.cjs +10 -0
  116. package/utils/long-utils.js +10 -0
  117. package/utils.cjs +7 -0
  118. package/utils.js +8 -1
@@ -14,6 +14,178 @@ import { RpcError } from "../../tl/inner-tl.js";
14
14
  const WARN_EVERY = 100;
15
15
  const KEEP_ALIVE_INTERVAL = 15 * 60 * 1e3;
16
16
  const UPDATES_TOO_LONG = { _: "updatesTooLong" };
17
+ function collectRichTextPeerIds(text, peers) {
18
+ if (!text) return;
19
+ switch (text._) {
20
+ case "textEmpty":
21
+ case "textPlain":
22
+ case "textEmail":
23
+ case "textPhone":
24
+ case "textImage":
25
+ case "textMath":
26
+ case "textCustomEmoji":
27
+ break;
28
+ case "textBold":
29
+ case "textItalic":
30
+ case "textUnderline":
31
+ case "textStrike":
32
+ case "textFixed":
33
+ case "textUrl":
34
+ case "textSubscript":
35
+ case "textSuperscript":
36
+ case "textMarked":
37
+ case "textAnchor":
38
+ case "textSpoiler":
39
+ case "textMention":
40
+ case "textHashtag":
41
+ case "textBotCommand":
42
+ case "textCashtag":
43
+ case "textAutoUrl":
44
+ case "textAutoEmail":
45
+ case "textAutoPhone":
46
+ case "textBankCard":
47
+ case "textDate":
48
+ collectRichTextPeerIds(text.text, peers);
49
+ break;
50
+ case "textConcat":
51
+ for (const child of text.texts) collectRichTextPeerIds(child, peers);
52
+ break;
53
+ case "textMentionName":
54
+ peers.add(text.userId);
55
+ collectRichTextPeerIds(text.text, peers);
56
+ break;
57
+ default:
58
+ assertNever();
59
+ }
60
+ }
61
+ function collectPageCaptionPeerIds(caption, peers) {
62
+ if (!caption) return;
63
+ collectRichTextPeerIds(caption.text, peers);
64
+ collectRichTextPeerIds(caption.credit, peers);
65
+ }
66
+ function collectPageBlockPeerIds(block, peers) {
67
+ if (!block) return;
68
+ switch (block._) {
69
+ case "pageBlockUnsupported":
70
+ case "pageBlockDivider":
71
+ case "pageBlockAnchor":
72
+ case "pageBlockMath":
73
+ break;
74
+ case "pageBlockTitle":
75
+ case "pageBlockSubtitle":
76
+ case "pageBlockHeader":
77
+ case "pageBlockSubheader":
78
+ case "pageBlockParagraph":
79
+ case "pageBlockPreformatted":
80
+ case "pageBlockFooter":
81
+ case "pageBlockKicker":
82
+ case "pageBlockThinking":
83
+ case "pageBlockHeading1":
84
+ case "pageBlockHeading2":
85
+ case "pageBlockHeading3":
86
+ case "pageBlockHeading4":
87
+ case "pageBlockHeading5":
88
+ case "pageBlockHeading6":
89
+ collectRichTextPeerIds(block.text, peers);
90
+ break;
91
+ case "pageBlockAuthorDate":
92
+ collectRichTextPeerIds(block.author, peers);
93
+ break;
94
+ case "pageBlockList":
95
+ for (const item of block.items) collectPageListItemPeerIds(item, peers);
96
+ break;
97
+ case "pageBlockOrderedList":
98
+ for (const item of block.items) collectPageListOrderedItemPeerIds(item, peers);
99
+ break;
100
+ case "pageBlockBlockquote":
101
+ case "pageBlockPullquote":
102
+ collectRichTextPeerIds(block.text, peers);
103
+ collectRichTextPeerIds(block.caption, peers);
104
+ break;
105
+ case "pageBlockPhoto":
106
+ case "pageBlockVideo":
107
+ case "pageBlockEmbed":
108
+ case "pageBlockAudio":
109
+ case "pageBlockMap":
110
+ case "inputPageBlockMap":
111
+ collectPageCaptionPeerIds(block.caption, peers);
112
+ break;
113
+ case "pageBlockCover":
114
+ collectPageBlockPeerIds(block.cover, peers);
115
+ break;
116
+ case "pageBlockEmbedPost":
117
+ for (const child of block.blocks) collectPageBlockPeerIds(child, peers);
118
+ collectPageCaptionPeerIds(block.caption, peers);
119
+ break;
120
+ case "pageBlockCollage":
121
+ case "pageBlockSlideshow":
122
+ for (const child of block.items) collectPageBlockPeerIds(child, peers);
123
+ collectPageCaptionPeerIds(block.caption, peers);
124
+ break;
125
+ case "pageBlockChannel":
126
+ switch (block.channel._) {
127
+ case "chatEmpty":
128
+ case "chat":
129
+ case "chatForbidden":
130
+ peers.add(getMarkedPeerId(block.channel.id, "chat"));
131
+ break;
132
+ case "channel":
133
+ case "channelForbidden":
134
+ peers.add(getMarkedPeerId(block.channel.id, "channel"));
135
+ break;
136
+ default:
137
+ assertNever(block.channel);
138
+ }
139
+ break;
140
+ case "pageBlockTable":
141
+ collectRichTextPeerIds(block.title, peers);
142
+ for (const row of block.rows) {
143
+ for (const cell of row.cells) collectRichTextPeerIds(cell.text, peers);
144
+ }
145
+ break;
146
+ case "pageBlockDetails":
147
+ for (const child of block.blocks) collectPageBlockPeerIds(child, peers);
148
+ collectRichTextPeerIds(block.title, peers);
149
+ break;
150
+ case "pageBlockRelatedArticles":
151
+ collectRichTextPeerIds(block.title, peers);
152
+ break;
153
+ case "pageBlockBlockquoteBlocks":
154
+ for (const child of block.blocks) collectPageBlockPeerIds(child, peers);
155
+ collectRichTextPeerIds(block.caption, peers);
156
+ break;
157
+ default:
158
+ assertNever();
159
+ }
160
+ }
161
+ function collectPageListItemPeerIds(item, peers) {
162
+ switch (item._) {
163
+ case "pageListItemText":
164
+ collectRichTextPeerIds(item.text, peers);
165
+ break;
166
+ case "pageListItemBlocks":
167
+ for (const block of item.blocks) collectPageBlockPeerIds(block, peers);
168
+ break;
169
+ default:
170
+ assertNever();
171
+ }
172
+ }
173
+ function collectPageListOrderedItemPeerIds(item, peers) {
174
+ switch (item._) {
175
+ case "pageListOrderedItemText":
176
+ collectRichTextPeerIds(item.text, peers);
177
+ break;
178
+ case "pageListOrderedItemBlocks":
179
+ for (const block of item.blocks) collectPageBlockPeerIds(block, peers);
180
+ break;
181
+ default:
182
+ assertNever();
183
+ }
184
+ }
185
+ function collectRichMessagePeerIds(richMessage, peers) {
186
+ if (!richMessage) return;
187
+ for (const block of richMessage.blocks) collectPageBlockPeerIds(block, peers);
188
+ }
17
189
  class UpdatesManager {
18
190
  constructor(client, params = {}) {
19
191
  this.client = client;
@@ -86,6 +258,9 @@ class UpdatesManager {
86
258
  cptsMod = /* @__PURE__ */ new Map();
87
259
  channelDiffTimeouts = /* @__PURE__ */ new Map();
88
260
  channelsOpened = /* @__PURE__ */ new Map();
261
+ // channels we got CHANNEL_PRIVATE for when fetching diff — skip gap handling.
262
+ // invalidated when an updateChannel for that channel arrives
263
+ inaccessibleChannels = /* @__PURE__ */ new Set();
89
264
  log;
90
265
  _onCatchingUp = () => {
91
266
  };
@@ -107,6 +282,7 @@ class UpdatesManager {
107
282
  this.stopLoop();
108
283
  this.cpts.clear();
109
284
  this.cptsMod.clear();
285
+ this.inaccessibleChannels.clear();
110
286
  this.pts = this.qts = this.date = this.seq = void 0;
111
287
  }
112
288
  async prepare() {
@@ -482,6 +658,7 @@ class UpdatesManager {
482
658
  return missing;
483
659
  }
484
660
  if (!await fetchPeer(msg.viaBotId)) return missing;
661
+ if (!await fetchPeer(msg.guestchatViaFrom)) return missing;
485
662
  if (msg.entities) {
486
663
  for (const ent of msg.entities) {
487
664
  if (ent._ === "messageEntityMentionName") {
@@ -489,6 +666,13 @@ class UpdatesManager {
489
666
  }
490
667
  }
491
668
  }
669
+ if (msg.richMessage) {
670
+ const richMessagePeers = /* @__PURE__ */ new Set();
671
+ collectRichMessagePeerIds(msg.richMessage, richMessagePeers);
672
+ for (const peer of richMessagePeers) {
673
+ if (!await fetchPeer(peer)) return missing;
674
+ }
675
+ }
492
676
  if (msg.media) {
493
677
  switch (msg.media._) {
494
678
  case "messageMediaContact":
@@ -538,6 +722,13 @@ class UpdatesManager {
538
722
  }
539
723
  }
540
724
  }
725
+ if ("richMessage" in upd.draft && upd.draft.richMessage) {
726
+ const richMessagePeers = /* @__PURE__ */ new Set();
727
+ collectRichMessagePeerIds(upd.draft.richMessage, richMessagePeers);
728
+ for (const peer of richMessagePeers) {
729
+ if (!await fetchPeer(peer)) return missing;
730
+ }
731
+ }
541
732
  }
542
733
  return missing;
543
734
  }
@@ -560,7 +751,13 @@ class UpdatesManager {
560
751
  store(msg.fromId);
561
752
  if (msg._ === "message") {
562
753
  store(msg.viaBotId);
754
+ store(msg.guestchatViaFrom);
563
755
  store(msg.fwdFrom?.fromId);
756
+ if (msg.richMessage) {
757
+ const richMessagePeers = /* @__PURE__ */ new Set();
758
+ collectRichMessagePeerIds(msg.richMessage, richMessagePeers);
759
+ store([...richMessagePeers]);
760
+ }
564
761
  if (msg.media) {
565
762
  switch (msg.media._) {
566
763
  case "messageMediaWebPage":
@@ -725,14 +922,20 @@ class UpdatesManager {
725
922
  channelId,
726
923
  this._fetchChannelDifference(channelId, fallbackPts).catch((err) => {
727
924
  this.log.warn("error fetching difference for %d: %e", channelId, err);
728
- if (RpcError.is("PERSISTENT_TIMESTAMP_INVALID")) {
925
+ if (RpcError.is(err, "PERSISTENT_TIMESTAMP_INVALID")) {
729
926
  this.log.warn("received PERSISTENT_TIMESTAMP_INVALID, resetting channel pts value");
730
927
  this.cpts.delete(channelId);
731
928
  this.cptsMod.delete(channelId);
732
929
  }
930
+ if (RpcError.is(err, "CHANNEL_PRIVATE") || RpcError.is(err, "CHANNEL_INVALID")) {
931
+ this.log.debug("channel %d is inaccessible, skipping gap fills until updateChannel", channelId);
932
+ this.inaccessibleChannels.add(channelId);
933
+ this.cpts.delete(channelId);
934
+ this.cptsMod.delete(channelId);
935
+ }
733
936
  }).then((ok) => {
734
937
  requestedDiff.delete(channelId);
735
- if (!ok) {
938
+ if (!ok && !this.inaccessibleChannels.has(channelId)) {
736
939
  this.log.debug("channel difference for %d failed, falling back to common diff", channelId);
737
940
  this._fetchDifferenceLater(requestedDiff);
738
941
  }
@@ -933,6 +1136,13 @@ class UpdatesManager {
933
1136
  }
934
1137
  break;
935
1138
  }
1139
+ case "updateChannel": {
1140
+ const channel = pending.peers.chat(upd.channelId);
1141
+ if (channel._ !== "channelForbidden") {
1142
+ this.inaccessibleChannels.delete(upd.channelId);
1143
+ }
1144
+ break;
1145
+ }
936
1146
  case "updateConfig":
937
1147
  client.mt.network.config.update(true).catch((err) => client.onError.emit(unknownToError(err)));
938
1148
  break;
@@ -1250,7 +1460,8 @@ class UpdatesManager {
1250
1460
  );
1251
1461
  continue;
1252
1462
  }
1253
- if (diff < 0) {
1463
+ const isInaccessibleChannel = pending.channelId && this.inaccessibleChannels.has(pending.channelId);
1464
+ if (diff < 0 && !isInaccessibleChannel) {
1254
1465
  if (diff > -3) {
1255
1466
  log.debug(
1256
1467
  "postponing %s for 0.5s (cid = %d) because small gap detected (by pts: exp %d, got %d, diff=%d)",
@@ -50,4 +50,5 @@ function makeInspectable(obj, props, hide) {
50
50
  obj.prototype[customInspectSymbol] = obj.prototype.toJSON;
51
51
  return obj;
52
52
  }
53
+ exports.customInspectSymbol = customInspectSymbol;
53
54
  exports.makeInspectable = makeInspectable;
@@ -1,3 +1,4 @@
1
+ export declare const customInspectSymbol: symbol;
1
2
  /**
2
3
  * Small helper function that adds `toJSON` and `util.custom.inspect`
3
4
  * methods to a given class based on its getters
@@ -1,3 +1,4 @@
1
+ export declare const customInspectSymbol: symbol;
1
2
  /**
2
3
  * Small helper function that adds `toJSON` and `util.custom.inspect`
3
4
  * methods to a given class based on its getters
@@ -44,5 +44,6 @@ function makeInspectable(obj, props, hide) {
44
44
  return obj;
45
45
  }
46
46
  export {
47
+ customInspectSymbol,
47
48
  makeInspectable
48
49
  };
package/index.cjs CHANGED
@@ -56,6 +56,7 @@ const messageReactions = require("./highlevel/types/messages/message-reactions.c
56
56
  const messageReplies = require("./highlevel/types/messages/message-replies.cjs");
57
57
  const message = require("./highlevel/types/messages/message.cjs");
58
58
  const repliedMessage = require("./highlevel/types/messages/replied-message.cjs");
59
+ const richMessage = require("./highlevel/types/messages/rich-message.cjs");
59
60
  const searchFilters = require("./highlevel/types/messages/search-filters.cjs");
60
61
  const suggestedPost = require("./highlevel/types/messages/suggested-post.cjs");
61
62
  const collectibleInfo = require("./highlevel/types/misc/collectible-info.cjs");
@@ -118,6 +119,7 @@ const storyInteractions = require("./highlevel/types/stories/story-interactions.
118
119
  const storyViewer = require("./highlevel/types/stories/story-viewer.cjs");
119
120
  const story$1 = require("./highlevel/types/stories/story.cjs");
120
121
  const botChatJoinRequest = require("./highlevel/types/updates/bot-chat-join-request.cjs");
122
+ const botGuestChatQuery = require("./highlevel/types/updates/bot-guest-chat-query.cjs");
121
123
  const botReaction = require("./highlevel/types/updates/bot-reaction.cjs");
122
124
  const botStopped = require("./highlevel/types/updates/bot-stopped.cjs");
123
125
  const callbackQuery = require("./highlevel/types/updates/callback-query.cjs");
@@ -224,6 +226,7 @@ exports.MessageReactions = messageReactions.MessageReactions;
224
226
  exports.MessageRepliesInfo = messageReplies.MessageRepliesInfo;
225
227
  exports.Message = message.Message;
226
228
  exports.RepliedMessageInfo = repliedMessage.RepliedMessageInfo;
229
+ exports.RichMessage = richMessage.RichMessage;
227
230
  exports.SearchFilters = searchFilters.SearchFilters;
228
231
  exports.SuggestedPostInfo = suggestedPost.SuggestedPostInfo;
229
232
  exports.CollectibleInfo = collectibleInfo.CollectibleInfo;
@@ -297,6 +300,7 @@ exports.StoryViewer = storyViewer.StoryViewer;
297
300
  exports.StoryViewersList = storyViewer.StoryViewersList;
298
301
  exports.Story = story$1.Story;
299
302
  exports.BotChatJoinRequestUpdate = botChatJoinRequest.BotChatJoinRequestUpdate;
303
+ exports.BotGuestChatQuery = botGuestChatQuery.BotGuestChatQuery;
300
304
  exports.BotReactionCountUpdate = botReaction.BotReactionCountUpdate;
301
305
  exports.BotReactionUpdate = botReaction.BotReactionUpdate;
302
306
  exports.BotStoppedUpdate = botStopped.BotStoppedUpdate;
package/index.js CHANGED
@@ -49,6 +49,7 @@ import { MessageReactions } from "./highlevel/types/messages/message-reactions.j
49
49
  import { MessageRepliesInfo } from "./highlevel/types/messages/message-replies.js";
50
50
  import { Message } from "./highlevel/types/messages/message.js";
51
51
  import { RepliedMessageInfo } from "./highlevel/types/messages/replied-message.js";
52
+ import { RichMessage } from "./highlevel/types/messages/rich-message.js";
52
53
  import { SearchFilters } from "./highlevel/types/messages/search-filters.js";
53
54
  import { SuggestedPostInfo } from "./highlevel/types/messages/suggested-post.js";
54
55
  import { CollectibleInfo } from "./highlevel/types/misc/collectible-info.js";
@@ -111,6 +112,7 @@ import { StoryInteractions } from "./highlevel/types/stories/story-interactions.
111
112
  import { StoryRepost, StoryViewer, StoryViewersList } from "./highlevel/types/stories/story-viewer.js";
112
113
  import { Story } from "./highlevel/types/stories/story.js";
113
114
  import { BotChatJoinRequestUpdate } from "./highlevel/types/updates/bot-chat-join-request.js";
115
+ import { BotGuestChatQuery } from "./highlevel/types/updates/bot-guest-chat-query.js";
114
116
  import { BotReactionCountUpdate, BotReactionUpdate } from "./highlevel/types/updates/bot-reaction.js";
115
117
  import { BotStoppedUpdate } from "./highlevel/types/updates/bot-stopped.js";
116
118
  import { BusinessCallbackQuery, CallbackQuery, InlineCallbackQuery } from "./highlevel/types/updates/callback-query.js";
@@ -163,6 +165,7 @@ export {
163
165
  BoostStats,
164
166
  BotChatJoinRequestUpdate,
165
167
  inner as BotCommands,
168
+ BotGuestChatQuery,
166
169
  BotInfo,
167
170
  factories$1 as BotInline,
168
171
  factories as BotInlineMessage,
@@ -269,6 +272,7 @@ export {
269
272
  RawUpdateInfo,
270
273
  ReactionCount,
271
274
  RepliedMessageInfo,
275
+ RichMessage,
272
276
  SavedStarGift,
273
277
  SearchFilters,
274
278
  SentCode,
package/methods.cjs CHANGED
@@ -18,6 +18,7 @@ const signIn = require("./highlevel/methods/auth/sign-in.cjs");
18
18
  const startTest = require("./highlevel/methods/auth/start-test.cjs");
19
19
  const start = require("./highlevel/methods/auth/start.cjs");
20
20
  const utils = require("./highlevel/methods/auth/utils.cjs");
21
+ const answerBotGuestChatQuery = require("./highlevel/methods/bots/answer-bot-guest-chat-query.cjs");
21
22
  const answerCallbackQuery = require("./highlevel/methods/bots/answer-callback-query.cjs");
22
23
  const answerInlineQuery = require("./highlevel/methods/bots/answer-inline-query.cjs");
23
24
  const answerPreCheckoutQuery = require("./highlevel/methods/bots/answer-pre-checkout-query.cjs");
@@ -299,6 +300,7 @@ exports.signIn = signIn.signIn;
299
300
  exports.startTest = startTest.startTest;
300
301
  exports.start = start.start;
301
302
  exports.isSelfPeer = utils.isSelfPeer;
303
+ exports.answerBotGuestChatQuery = answerBotGuestChatQuery.answerBotGuestChatQuery;
302
304
  exports.answerCallbackQuery = answerCallbackQuery.answerCallbackQuery;
303
305
  exports.answerInlineQuery = answerInlineQuery.answerInlineQuery;
304
306
  exports.answerPreCheckoutQuery = answerPreCheckoutQuery.answerPreCheckoutQuery;
package/methods.js CHANGED
@@ -11,6 +11,7 @@ import { signIn } from "./highlevel/methods/auth/sign-in.js";
11
11
  import { startTest } from "./highlevel/methods/auth/start-test.js";
12
12
  import { start } from "./highlevel/methods/auth/start.js";
13
13
  import { isSelfPeer } from "./highlevel/methods/auth/utils.js";
14
+ import { answerBotGuestChatQuery } from "./highlevel/methods/bots/answer-bot-guest-chat-query.js";
14
15
  import { answerCallbackQuery } from "./highlevel/methods/bots/answer-callback-query.js";
15
16
  import { answerInlineQuery } from "./highlevel/methods/bots/answer-inline-query.js";
16
17
  import { answerPreCheckoutQuery } from "./highlevel/methods/bots/answer-pre-checkout-query.js";
@@ -289,6 +290,7 @@ export {
289
290
  addChatMembers,
290
291
  addContact,
291
292
  addStickerToSet,
293
+ answerBotGuestChatQuery,
292
294
  answerCallbackQuery,
293
295
  answerInlineQuery,
294
296
  answerMedia,
@@ -0,0 +1,149 @@
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
+ class FloodControl {
10
+ _rules;
11
+ _maxWindow;
12
+ _events = [];
13
+ constructor(rules) {
14
+ if (rules.length === 0) throw new Error("FloodControl needs at least one rule");
15
+ this._rules = rules;
16
+ this._maxWindow = rules.reduce((m, r) => Math.max(m, r.windowMs), 0);
17
+ }
18
+ /** Earliest absolute perf-now ms at which a new event is permitted. */
19
+ getWakeupAt(now) {
20
+ let wakeup = 0;
21
+ for (const { count, windowMs } of this._rules) {
22
+ const cutoff = now - windowMs;
23
+ let inWindow = 0;
24
+ let oldestInWindowIdx = -1;
25
+ for (let i = this._events.length - 1; i >= 0; i--) {
26
+ if (this._events[i] <= cutoff) break;
27
+ inWindow++;
28
+ oldestInWindowIdx = i;
29
+ }
30
+ if (inWindow >= count) {
31
+ const t = this._events[oldestInWindowIdx] + windowMs;
32
+ if (t > wakeup) wakeup = t;
33
+ }
34
+ }
35
+ return wakeup;
36
+ }
37
+ addEvent(now) {
38
+ this._events.push(now);
39
+ this._prune(now);
40
+ }
41
+ _prune(now) {
42
+ const cutoff = now - this._maxWindow;
43
+ let i = 0;
44
+ while (i < this._events.length && this._events[i] < cutoff) i++;
45
+ if (i > 0) this._events.splice(0, i);
46
+ }
47
+ reset() {
48
+ this._events = [];
49
+ }
50
+ }
51
+ const DEFAULT_SANITY_LIMITS = [
52
+ { count: 5, windowMs: 1e4 }
53
+ ];
54
+ const DEFAULT_FLOOD_LIMITS = [
55
+ { count: 1, windowMs: 1e3 },
56
+ { count: 4, windowMs: 2e3 },
57
+ { count: 8, windowMs: 3e3 }
58
+ ];
59
+ const DEFAULT_MTPROTO_ERROR_LIMITS = [
60
+ { count: 1, windowMs: 1e3 },
61
+ { count: 4, windowMs: 2e3 },
62
+ { count: 8, windowMs: 3e3 }
63
+ ];
64
+ class ConnectionFloodController {
65
+ sanity;
66
+ flood;
67
+ mtprotoError;
68
+ _log;
69
+ constructor(limits = {}) {
70
+ this.sanity = new FloodControl(limits.sanity ?? DEFAULT_SANITY_LIMITS);
71
+ this.flood = new FloodControl(limits.flood ?? DEFAULT_FLOOD_LIMITS);
72
+ this.mtprotoError = new FloodControl(limits.mtprotoError ?? DEFAULT_MTPROTO_ERROR_LIMITS);
73
+ }
74
+ setLogger(log) {
75
+ this._log = log;
76
+ }
77
+ /**
78
+ * Notify a network-up transition.
79
+ *
80
+ * TDLib clears sanity + online-regime flood + backoff on
81
+ * `ConnectionCreator::on_network(true)`. We don't model the online regime,
82
+ * and our transport layer owns its own reconnect backoff, so only the
83
+ * sanity limiter is reset here.
84
+ */
85
+ notifyNetworkUp() {
86
+ this._log?.debug("network up, resetting sanity limiter");
87
+ this.sanity.reset();
88
+ }
89
+ /** Record an MTProto-level error (transport 429; per TDLib, other codes don't tick this). */
90
+ addMtprotoError(now = performance.now()) {
91
+ this._log?.debug("recording mtproto error");
92
+ this.mtprotoError.addEvent(now);
93
+ }
94
+ /** Earliest perf-now ms at which a new connection attempt is permitted. */
95
+ getWakeupAt(now) {
96
+ return Math.max(
97
+ this.sanity.getWakeupAt(now),
98
+ this.flood.getWakeupAt(now),
99
+ this.mtprotoError.getWakeupAt(now)
100
+ );
101
+ }
102
+ /**
103
+ * Block until a connection attempt is permitted under all applicable
104
+ * limiters, then record the attempt. Concurrent waiters serialize fairly
105
+ * because the first to wake records its event before the next checks state.
106
+ *
107
+ * If `signal` aborts, the pending timer is cleared and the promise rejects
108
+ * with the signal's reason.
109
+ */
110
+ async wait(signal) {
111
+ let waited = false;
112
+ while (true) {
113
+ signal?.throwIfAborted();
114
+ const now = performance.now();
115
+ const wakeup = this.getWakeupAt(now);
116
+ if (wakeup <= now) {
117
+ this.sanity.addEvent(now);
118
+ this.flood.addEvent(now);
119
+ if (waited) this._log?.debug("admitted connect after waiting");
120
+ return;
121
+ }
122
+ const delay = wakeup - now;
123
+ this._log?.debug("connect throttled (waiting %dms)", Math.round(delay));
124
+ waited = true;
125
+ await new Promise((resolve, reject) => {
126
+ const handle = utils.timers.setTimeout(() => {
127
+ signal?.removeEventListener("abort", onAbort);
128
+ resolve();
129
+ }, delay);
130
+ const onAbort = () => {
131
+ utils.timers.clearTimeout(handle);
132
+ reject(signal.reason);
133
+ };
134
+ signal?.addEventListener("abort", onAbort, { once: true });
135
+ });
136
+ }
137
+ }
138
+ /** Reset all internal state. Mainly for tests. */
139
+ reset() {
140
+ this.sanity.reset();
141
+ this.flood.reset();
142
+ this.mtprotoError.reset();
143
+ }
144
+ }
145
+ exports.ConnectionFloodController = ConnectionFloodController;
146
+ exports.DEFAULT_FLOOD_LIMITS = DEFAULT_FLOOD_LIMITS;
147
+ exports.DEFAULT_MTPROTO_ERROR_LIMITS = DEFAULT_MTPROTO_ERROR_LIMITS;
148
+ exports.DEFAULT_SANITY_LIMITS = DEFAULT_SANITY_LIMITS;
149
+ exports.FloodControl = FloodControl;
@@ -0,0 +1,79 @@
1
+ import { Logger } from '../utils/logger.js';
2
+ export interface FloodLimit {
3
+ /** maximum events allowed within `windowMs` */
4
+ count: number;
5
+ /** window size in ms */
6
+ windowMs: number;
7
+ }
8
+ /**
9
+ * Sliding-window flood control. Port of TDLib's `FloodControlStrict`
10
+ * (tdutils/td/utils/FloodControlStrict.h).
11
+ */
12
+ export declare class FloodControl {
13
+ private readonly _rules;
14
+ private readonly _maxWindow;
15
+ private _events;
16
+ constructor(rules: readonly FloodLimit[]);
17
+ /** Earliest absolute perf-now ms at which a new event is permitted. */
18
+ getWakeupAt(now: number): number;
19
+ addEvent(now: number): void;
20
+ private _prune;
21
+ reset(): void;
22
+ }
23
+ export declare const DEFAULT_SANITY_LIMITS: readonly FloodLimit[];
24
+ export declare const DEFAULT_FLOOD_LIMITS: readonly FloodLimit[];
25
+ export declare const DEFAULT_MTPROTO_ERROR_LIMITS: readonly FloodLimit[];
26
+ export interface ConnectionFloodLimits {
27
+ sanity?: readonly FloodLimit[];
28
+ flood?: readonly FloodLimit[];
29
+ mtprotoError?: readonly FloodLimit[];
30
+ }
31
+ /**
32
+ * Per-connection-slot flood control bundle modeled after TDLib's
33
+ * `ConnectionCreator` client state (`ConnectionCreator.cpp`) — TDLib keys
34
+ * its flood control by pool slot (the `SessionProxy#i` hash), so each
35
+ * socket's connect history is throttled independently.
36
+ *
37
+ * Three limiters compose:
38
+ * - `sanity` — absolute ceiling, always applied
39
+ * - `flood` — burst limit on connection attempts, always applied
40
+ * - `mtprotoError` — ticks only on MTProto-level errors, always applied
41
+ *
42
+ * TDLib additionally has a stricter "online" regime keyed to app foreground
43
+ * state — we have no such signal, so only the permissive regime is modeled.
44
+ *
45
+ * `wait()` blocks until all limiters allow a fresh connection and records
46
+ * the event atomically (sanity + flood).
47
+ */
48
+ export declare class ConnectionFloodController {
49
+ readonly sanity: FloodControl;
50
+ readonly flood: FloodControl;
51
+ readonly mtprotoError: FloodControl;
52
+ private _log?;
53
+ constructor(limits?: ConnectionFloodLimits);
54
+ setLogger(log: Logger): void;
55
+ /**
56
+ * Notify a network-up transition.
57
+ *
58
+ * TDLib clears sanity + online-regime flood + backoff on
59
+ * `ConnectionCreator::on_network(true)`. We don't model the online regime,
60
+ * and our transport layer owns its own reconnect backoff, so only the
61
+ * sanity limiter is reset here.
62
+ */
63
+ notifyNetworkUp(): void;
64
+ /** Record an MTProto-level error (transport 429; per TDLib, other codes don't tick this). */
65
+ addMtprotoError(now?: number): void;
66
+ /** Earliest perf-now ms at which a new connection attempt is permitted. */
67
+ getWakeupAt(now: number): number;
68
+ /**
69
+ * Block until a connection attempt is permitted under all applicable
70
+ * limiters, then record the attempt. Concurrent waiters serialize fairly
71
+ * because the first to wake records its event before the next checks state.
72
+ *
73
+ * If `signal` aborts, the pending timer is cleared and the promise rejects
74
+ * with the signal's reason.
75
+ */
76
+ wait(signal?: AbortSignal): Promise<void>;
77
+ /** Reset all internal state. Mainly for tests. */
78
+ reset(): void;
79
+ }