@mtcute/core 0.16.10 → 0.16.14

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.
@@ -8,7 +8,7 @@ const platform = require("./j7rWn_1y.js");
8
8
  const tl = require("@mtcute/tl");
9
9
  const conditionVariable = require("./eX3zeDAz.js");
10
10
  const controllablePromise = require("./CZAB54t2.js");
11
- const storyViewer = require("./UVFvMVPt.js");
11
+ const storyViewer = require("./chPq0GcA.js");
12
12
  const Long = require("long");
13
13
  const peersIndex = require("./ija5tZ1t.js");
14
14
  const fileId = require("@mtcute/file-id");
@@ -260,6 +260,8 @@ async function start(client, params) {
260
260
  if (tl.tl.RpcError.is(e)) {
261
261
  if (e.text === "SESSION_PASSWORD_NEEDED") has2fa = true;
262
262
  else if (e.text !== "AUTH_KEY_UNREGISTERED") throw e;
263
+ } else {
264
+ throw e;
263
265
  }
264
266
  }
265
267
  if (!has2fa && !params.qrCodeHandler) {
@@ -4619,6 +4621,36 @@ async function getUsers(client, ids) {
4619
4621
  const res = await Promise.all(inputPeers.map((peer) => storyViewer._getUsersBatched(client, peer)));
4620
4622
  return res.map((it) => it ? new storyViewer.User$2(it) : null);
4621
4623
  }
4624
+ async function isPeerAvailable(client, peerId) {
4625
+ peerId = storyViewer._normalizePeerId(peerId);
4626
+ if (typeof peerId === "object") {
4627
+ return true;
4628
+ }
4629
+ if (typeof peerId === "number") {
4630
+ const fromStorage = await client.storage.peers.getById(peerId);
4631
+ if (fromStorage) return true;
4632
+ const [peerType] = conditionVariable.parseMarkedPeerId(peerId);
4633
+ if (peerType === "chat" || client.storage.self.getCached(true)?.isBot) {
4634
+ return true;
4635
+ }
4636
+ return false;
4637
+ }
4638
+ if (typeof peerId === "string") {
4639
+ if (peerId === "self" || peerId === "me") {
4640
+ return true;
4641
+ }
4642
+ peerId = peerId.replace(/[@+\s()]/g, "");
4643
+ if (peerId.match(/^\d+$/)) {
4644
+ const fromStorage = await client.storage.peers.getByPhone(peerId);
4645
+ if (fromStorage) return true;
4646
+ } else {
4647
+ const fromStorage = await client.storage.peers.getByUsername(peerId);
4648
+ if (fromStorage) return true;
4649
+ }
4650
+ return false;
4651
+ }
4652
+ return false;
4653
+ }
4622
4654
  async function* iterProfilePhotos(client, userId, params) {
4623
4655
  if (!params) params = {};
4624
4656
  const peer = await storyViewer.resolveUser(client, userId);
@@ -4869,6 +4901,7 @@ exports.hideMyStoriesViews = hideMyStoriesViews;
4869
4901
  exports.importContacts = importContacts;
4870
4902
  exports.incrementStoriesViews = incrementStoriesViews;
4871
4903
  exports.initTakeoutSession = initTakeoutSession;
4904
+ exports.isPeerAvailable = isPeerAvailable;
4872
4905
  exports.isSelfPeer = isSelfPeer;
4873
4906
  exports.iterAllStories = iterAllStories;
4874
4907
  exports.iterBoosters = iterBoosters;
@@ -9,11 +9,11 @@ const Long = require("long");
9
9
  const conditionVariable = require("./eX3zeDAz.js");
10
10
  const platform = require("./j7rWn_1y.js");
11
11
  const controllablePromise = require("./CZAB54t2.js");
12
- const storyViewer = require("./UVFvMVPt.js");
12
+ const storyViewer = require("./chPq0GcA.js");
13
13
  const tlRuntime = require("@mtcute/tl-runtime");
14
14
  const tl = require("@mtcute/tl");
15
15
  const peersIndex = require("./ija5tZ1t.js");
16
- const EventEmitter = require("node:events");
16
+ const EventEmitter = require("events");
17
17
  const reader_js = require("@mtcute/tl/binary/reader.js");
18
18
  const writer_js = require("@mtcute/tl/binary/writer.js");
19
19
  const logger = require("./D4qcXFYA.js");
@@ -52,14 +52,17 @@ class PeersService extends sortedArray.BaseService {
52
52
  _pendingWrites = /* @__PURE__ */ new Map();
53
53
  async updatePeersFrom(obj) {
54
54
  let count = 0;
55
+ let minCount = 0;
55
56
  for (const peer of conditionVariable.getAllPeersFrom(obj)) {
56
- if (peer.min) continue;
57
+ if (peer.min) {
58
+ minCount += 1;
59
+ }
57
60
  count += 1;
58
61
  await this.store(peer);
59
62
  }
60
63
  if (count > 0) {
61
64
  await this._driver.save?.();
62
- this._log.debug("cached %d peers", count);
65
+ this._log.debug("cached %d peers (%d min)", count, minCount);
63
66
  return true;
64
67
  }
65
68
  return false;
@@ -76,6 +79,7 @@ class PeersService extends sortedArray.BaseService {
76
79
  dto = {
77
80
  id: peer.id,
78
81
  accessHash: conditionVariable.longToFastString(peer.accessHash),
82
+ isMin: peer.min && !(peer.phone !== void 0 && peer.phone.length === 0),
79
83
  phone: peer.phone,
80
84
  usernames: conditionVariable.extractUsernames(peer),
81
85
  updated: Date.now(),
@@ -89,6 +93,8 @@ class PeersService extends sortedArray.BaseService {
89
93
  dto = {
90
94
  id: -peer.id,
91
95
  accessHash: "",
96
+ isMin: false,
97
+ // chats can't be "min"
92
98
  updated: Date.now(),
93
99
  complete: this._serializeTl(peer),
94
100
  usernames: []
@@ -105,6 +111,7 @@ class PeersService extends sortedArray.BaseService {
105
111
  dto = {
106
112
  id: conditionVariable.toggleChannelIdMark(peer.id),
107
113
  accessHash: conditionVariable.longToFastString(peer.accessHash),
114
+ isMin: peer._ === "channel" ? peer.min : false,
108
115
  usernames: conditionVariable.extractUsernames(peer),
109
116
  updated: Date.now(),
110
117
  complete: this._serializeTl(peer)
@@ -124,10 +131,73 @@ class PeersService extends sortedArray.BaseService {
124
131
  return;
125
132
  }
126
133
  }
134
+ let newComplete = peer;
135
+ if (peer.min) {
136
+ const existing = this._cache.get(peer.id)?.complete ?? await this.getCompleteById(peer.id);
137
+ if (existing && !existing.min) {
138
+ if (existing._ === "channel" && peer._ === "channel") {
139
+ newComplete = {
140
+ ...existing,
141
+ title: peer.title,
142
+ megagroup: peer.megagroup,
143
+ color: peer.color,
144
+ photo: peer.photo,
145
+ username: peer.username,
146
+ usernames: peer.usernames,
147
+ hasGeo: peer.hasGeo,
148
+ noforwards: peer.noforwards,
149
+ emojiStatus: peer.emojiStatus,
150
+ hasLink: peer.hasLink,
151
+ slowmodeEnabled: peer.slowmodeEnabled,
152
+ scam: peer.scam,
153
+ fake: peer.fake,
154
+ gigagroup: peer.gigagroup,
155
+ forum: peer.forum,
156
+ level: peer.level,
157
+ restricted: peer.restricted,
158
+ restrictionReason: peer.restrictionReason,
159
+ joinToSend: peer.joinToSend,
160
+ joinRequest: peer.joinRequest,
161
+ verified: peer.verified,
162
+ defaultBannedRights: peer.defaultBannedRights
163
+ };
164
+ } else if (existing._ === "user" && peer._ === "user") {
165
+ newComplete = {
166
+ ...existing,
167
+ deleted: peer.deleted,
168
+ bot: peer.bot,
169
+ botChatHistory: peer.botChatHistory,
170
+ botNochats: peer.botNochats,
171
+ verified: peer.verified,
172
+ restricted: peer.restricted,
173
+ botInlineGeo: peer.botInlineGeo,
174
+ support: peer.support,
175
+ scam: peer.scam,
176
+ fake: peer.fake,
177
+ botAttachMenu: peer.botAttachMenu,
178
+ premium: peer.premium,
179
+ storiesUnavailable: peer.storiesUnavailable,
180
+ contactRequirePremium: peer.contactRequirePremium,
181
+ botBusiness: peer.botBusiness,
182
+ botHasMainApp: peer.botHasMainApp,
183
+ photo: peer.applyMinPhoto ? peer.photo : existing.photo,
184
+ status: !existing.status || existing.status._ === "userStatusEmpty" ? peer.status : existing.status,
185
+ botInfoVersion: peer.botInfoVersion,
186
+ restrictionReason: peer.restrictionReason,
187
+ botInlinePlaceholder: peer.botInlinePlaceholder,
188
+ langCode: peer.langCode,
189
+ emojiStatus: peer.emojiStatus,
190
+ color: peer.color,
191
+ profileColor: peer.profileColor,
192
+ botActiveUsers: peer.botActiveUsers
193
+ };
194
+ }
195
+ }
196
+ }
127
197
  await this._peers.store(dto);
128
198
  this._cache.set(peer.id, {
129
199
  peer: getInputPeer(dto),
130
- complete: peer
200
+ complete: newComplete
131
201
  });
132
202
  await this._refs.deleteByPeer(peer.id);
133
203
  }
@@ -143,7 +213,7 @@ class PeersService extends sortedArray.BaseService {
143
213
  async getById(id, allowRefs = true) {
144
214
  const cached = this._cache.get(id);
145
215
  if (cached) return cached.peer;
146
- const dto = await this._peers.getById(id);
216
+ const dto = await this._peers.getById(id, false);
147
217
  if (dto) {
148
218
  return this._returnCaching(id, dto);
149
219
  }
@@ -183,10 +253,10 @@ class PeersService extends sortedArray.BaseService {
183
253
  }
184
254
  return this._returnCaching(dto.id, dto);
185
255
  }
186
- async getCompleteById(id) {
256
+ async getCompleteById(id, allowMin = false) {
187
257
  const cached = this._cache.get(id);
188
258
  if (cached) return cached.complete;
189
- const dto = await this._peers.getById(id);
259
+ const dto = await this._peers.getById(id, allowMin);
190
260
  if (!dto) return null;
191
261
  const cacheItem = {
192
262
  peer: getInputPeer(dto),
@@ -2157,20 +2227,33 @@ class UpdatesManager {
2157
2227
  conditionVariable.assertNever();
2158
2228
  }
2159
2229
  }
2160
- async _fetchMissingPeers(upd, peers, allowMissing = false) {
2161
- const { client } = this;
2230
+ async _fetchMissingPeers(upd, peers, fromDifference = false) {
2231
+ const { client, log } = this;
2162
2232
  const missing = /* @__PURE__ */ new Set();
2163
- async function fetchPeer(peer) {
2233
+ async function fetchPeer(peer, allowZeroHash = false) {
2164
2234
  if (!peer) return true;
2165
2235
  const bare = typeof peer === "number" ? conditionVariable.parseMarkedPeerId(peer)[1] : conditionVariable.getBarePeerId(peer);
2166
2236
  const marked = typeof peer === "number" ? peer : conditionVariable.getMarkedPeerId(peer);
2167
2237
  const index = marked > 0 ? peers.users : peers.chats;
2168
- if (index.has(bare)) return true;
2238
+ const fromIndex = index.get(bare);
2239
+ if (fromIndex && !fromIndex.min) return true;
2169
2240
  if (missing.has(marked)) return false;
2170
2241
  const cached = await client.storage.peers.getCompleteById(marked);
2171
2242
  if (!cached) {
2243
+ if (fromDifference && allowZeroHash && conditionVariable.parseMarkedPeerId(marked)[0] === "channel") {
2244
+ log.debug("trying to fetch peer %d with zero access hash", marked);
2245
+ const fetched = await storyViewer._getChannelsBatched(client, {
2246
+ _: "inputChannel",
2247
+ channelId: bare,
2248
+ accessHash: Long.ZERO
2249
+ });
2250
+ if (fetched?._ === "channel" && !fetched.min) {
2251
+ index.set(bare, fetched);
2252
+ return true;
2253
+ }
2254
+ }
2172
2255
  missing.add(marked);
2173
- return allowMissing;
2256
+ return fromDifference;
2174
2257
  }
2175
2258
  index.set(bare, cached);
2176
2259
  return true;
@@ -2182,7 +2265,7 @@ class UpdatesManager {
2182
2265
  case "updateEditChannelMessage": {
2183
2266
  const msg = upd.message;
2184
2267
  if (msg._ === "messageEmpty") return missing;
2185
- if (!await fetchPeer(msg.peerId)) return missing;
2268
+ if (!await fetchPeer(msg.peerId, true)) return missing;
2186
2269
  if (!await fetchPeer(msg.fromId)) return missing;
2187
2270
  if (msg.replyTo) {
2188
2271
  if (msg.replyTo._ === "messageReplyHeader" && !await fetchPeer(msg.replyTo.replyToPeerId)) {
@@ -2193,7 +2276,7 @@ class UpdatesManager {
2193
2276
  }
2194
2277
  }
2195
2278
  if (msg._ !== "messageService") {
2196
- if (msg.fwdFrom && (!await fetchPeer(msg.fwdFrom.fromId) || !await fetchPeer(msg.fwdFrom.savedFromPeer))) {
2279
+ if (msg.fwdFrom && (!await fetchPeer(msg.fwdFrom.fromId) || !await fetchPeer(msg.fwdFrom.savedFromPeer, true))) {
2197
2280
  return missing;
2198
2281
  }
2199
2282
  if (!await fetchPeer(msg.viaBotId)) return missing;
@@ -2230,7 +2313,7 @@ class UpdatesManager {
2230
2313
  if (!await fetchPeer(msg.action.userId)) return missing;
2231
2314
  break;
2232
2315
  case "messageActionChatMigrateTo":
2233
- if (!await fetchPeer(conditionVariable.toggleChannelIdMark(msg.action.channelId))) {
2316
+ if (!await fetchPeer(conditionVariable.toggleChannelIdMark(msg.action.channelId), true)) {
2234
2317
  return missing;
2235
2318
  }
2236
2319
  break;
@@ -6132,7 +6215,7 @@ class NetworkManager {
6132
6215
  _: "initConnection",
6133
6216
  deviceModel,
6134
6217
  systemVersion: "1.0",
6135
- appVersion: "0.16.10",
6218
+ appVersion: "0.16.14",
6136
6219
  systemLangCode: "en",
6137
6220
  langPack: "",
6138
6221
  // "langPacks are for official apps only"
@@ -418,12 +418,8 @@ class User {
418
418
  * are always available, but other fields may be omitted
419
419
  * despite being available.
420
420
  *
421
- * It was observed that these fields may be missing:
422
- * - `username, usernames`
423
- * - `status, lastOnline, nextOffline`
424
- * - `storiesMaxId`
425
- * - `photo` - in some cases when user has some some privacy settings
426
- * - and probably more
421
+ * For a rough list of fields that may be missing, see the
422
+ * [official docs](https://core.telegram.org/constructor/user).
427
423
  *
428
424
  * This currently only ever happens for non-bot users, so if you are building
429
425
  * a normal bot, you can safely ignore this field.
@@ -862,7 +858,7 @@ class GameHighScore {
862
858
  }
863
859
  const GameHighScore$1 = /* @__PURE__ */ memoizeGetters(GameHighScore, ["user"]);
864
860
  const GameHighScore$2 = /* @__PURE__ */ conditionVariable.makeInspectable(GameHighScore$1);
865
- async function resolvePeer(client, peerId, force = false) {
861
+ function _normalizePeerId(peerId) {
866
862
  if (typeof peerId === "object") {
867
863
  if (tl.tl.isAnyPeer(peerId)) {
868
864
  peerId = conditionVariable.getMarkedPeerId(peerId);
@@ -875,15 +871,20 @@ async function resolvePeer(client, peerId, force = false) {
875
871
  if (typeof peerId === "object") {
876
872
  switch (peerId._) {
877
873
  case "mtcute.dummyInputPeerMinUser":
878
- peerId = peerId.userId;
879
- break;
874
+ return peerId.userId;
880
875
  case "mtcute.dummyInputPeerMinChannel":
881
- peerId = conditionVariable.toggleChannelIdMark(peerId.channelId);
882
- break;
876
+ return conditionVariable.toggleChannelIdMark(peerId.channelId);
883
877
  default:
884
878
  return peerId;
885
879
  }
886
880
  }
881
+ return peerId;
882
+ }
883
+ async function resolvePeer(client, peerId, force = false) {
884
+ peerId = _normalizePeerId(peerId);
885
+ if (typeof peerId === "object") {
886
+ return peerId;
887
+ }
887
888
  if (typeof peerId === "number" && !force) {
888
889
  const fromStorage = await client.storage.peers.getById(peerId);
889
890
  if (fromStorage) return fromStorage;
@@ -962,7 +963,23 @@ async function resolvePeer(client, peerId, force = false) {
962
963
  throw new controllablePromise.MtPeerNotFoundError(`Could not find a peer by ${peerId}`);
963
964
  }
964
965
  const [peerType, bareId] = conditionVariable.parseMarkedPeerId(peerId);
965
- if (peerType !== "chat" && !client.storage.self.getCached(true)?.isBot) {
966
+ if (!(peerType === "chat" || client.storage.self.getCached(true)?.isBot)) {
967
+ const cached = await client.storage.peers.getCompleteById(peerId, true);
968
+ if (cached && (cached._ === "channel" || cached._ === "user")) {
969
+ const [username] = conditionVariable.extractUsernames(cached);
970
+ if (username) {
971
+ const resolved = await resolvePeer(client, username, true);
972
+ if (conditionVariable.getMarkedPeerId(resolved) === peerId) {
973
+ return resolved;
974
+ }
975
+ }
976
+ if (cached._ === "user" && cached.phone) {
977
+ const resolved = await resolvePeer(client, cached.phone, true);
978
+ if (conditionVariable.getMarkedPeerId(resolved) === peerId) {
979
+ return resolved;
980
+ }
981
+ }
982
+ }
966
983
  throw new controllablePromise.MtPeerNotFoundError(`Peer ${peerId} is not found in local cache`);
967
984
  }
968
985
  switch (peerType) {
@@ -2236,9 +2253,9 @@ class Chat {
2236
2253
  * are always available, but other fields may be omitted
2237
2254
  * despite being available.
2238
2255
  *
2239
- * It was observed that these fields may be missing:
2240
- * - `isMember`
2241
- * - and probably more
2256
+ * For a rough list of fields that may be missing, see the
2257
+ * official docs for [channel](https://core.telegram.org/constructor/channel)
2258
+ * and [user](https://core.telegram.org/constructor/user).
2242
2259
  *
2243
2260
  * This currently only ever happens for non-bot users, so if you are building
2244
2261
  * a normal bot, you can safely ignore this field.
@@ -10113,6 +10130,7 @@ exports._callDiscardReasonToTl = _callDiscardReasonToTl;
10113
10130
  exports._convertToTl = _convertToTl;
10114
10131
  exports._convertToTl$1 = _convertToTl$2;
10115
10132
  exports._findMessageInUpdate = _findMessageInUpdate;
10133
+ exports._getChannelsBatched = _getChannelsBatched;
10116
10134
  exports._getDiscussionMessage = _getDiscussionMessage;
10117
10135
  exports._getRawPeerBatched = _getRawPeerBatched;
10118
10136
  exports._getUsersBatched = _getUsersBatched;
@@ -10122,6 +10140,7 @@ exports._messageMediaFromTl = _messageMediaFromTl;
10122
10140
  exports._normalizeInputFile = _normalizeInputFile;
10123
10141
  exports._normalizeInputMedia = _normalizeInputMedia;
10124
10142
  exports._normalizeInputText = _normalizeInputText;
10143
+ exports._normalizePeerId = _normalizePeerId;
10125
10144
  exports._normalizeQuickReplyShortcut = _normalizeQuickReplyShortcut;
10126
10145
  exports._storyInteractiveElementFromTl = _storyInteractiveElementFromTl;
10127
10146
  exports.assertIsUpdatesGroup = assertIsUpdatesGroup;
@@ -1,4 +1,4 @@
1
- import { makeInspectable, toggleChannelIdMark, strippedPhotoToJpg, getMarkedPeerId, toInputPeer, parseMarkedPeerId, toInputUser, toInputChannel, assertNever, extractFileName, inflateSvgPath, svgPathToFile, decodeWaveform, ConditionVariable, isInputPeerChannel, bufferToStream, streamToBuffer, determinePartSize, randomLong, createChunkedReader, isProbablyPlainText, normalizeDate, encodeWaveform, LruMap, LongMap, normalizeMessageId, Deque, isInputPeerUser, isInputPeerChat, inputPeerToPeer } from "./DY1E3mHM.js";
1
+ import { makeInspectable, toggleChannelIdMark, strippedPhotoToJpg, parseMarkedPeerId, extractUsernames, getMarkedPeerId, toInputUser, toInputChannel, toInputPeer, assertNever, extractFileName, inflateSvgPath, svgPathToFile, decodeWaveform, ConditionVariable, isInputPeerChannel, bufferToStream, streamToBuffer, determinePartSize, randomLong, createChunkedReader, isProbablyPlainText, normalizeDate, encodeWaveform, LruMap, LongMap, normalizeMessageId, Deque, isInputPeerUser, isInputPeerChat, inputPeerToPeer } from "./DY1E3mHM.js";
2
2
  import { MtArgumentError, getPlatform, MtTypeAssertionError, MtUnsupportedError } from "./DBMBgE7t.js";
3
3
  import { assertTypeIs, MtPeerNotFoundError, assertTypeIsNot, hasValueAtKey, isPresent, assertTrue, MtMessageNotFoundError, MtEmptyError } from "./BN3qj7tU.js";
4
4
  import { PeersIndex } from "./N3PMYmCL.js";
@@ -412,12 +412,8 @@ class User {
412
412
  * are always available, but other fields may be omitted
413
413
  * despite being available.
414
414
  *
415
- * It was observed that these fields may be missing:
416
- * - `username, usernames`
417
- * - `status, lastOnline, nextOffline`
418
- * - `storiesMaxId`
419
- * - `photo` - in some cases when user has some some privacy settings
420
- * - and probably more
415
+ * For a rough list of fields that may be missing, see the
416
+ * [official docs](https://core.telegram.org/constructor/user).
421
417
  *
422
418
  * This currently only ever happens for non-bot users, so if you are building
423
419
  * a normal bot, you can safely ignore this field.
@@ -856,7 +852,7 @@ class GameHighScore {
856
852
  }
857
853
  const GameHighScore$1 = /* @__PURE__ */ memoizeGetters(GameHighScore, ["user"]);
858
854
  const GameHighScore$2 = /* @__PURE__ */ makeInspectable(GameHighScore$1);
859
- async function resolvePeer(client, peerId, force = false) {
855
+ function _normalizePeerId(peerId) {
860
856
  if (typeof peerId === "object") {
861
857
  if (tl.isAnyPeer(peerId)) {
862
858
  peerId = getMarkedPeerId(peerId);
@@ -869,15 +865,20 @@ async function resolvePeer(client, peerId, force = false) {
869
865
  if (typeof peerId === "object") {
870
866
  switch (peerId._) {
871
867
  case "mtcute.dummyInputPeerMinUser":
872
- peerId = peerId.userId;
873
- break;
868
+ return peerId.userId;
874
869
  case "mtcute.dummyInputPeerMinChannel":
875
- peerId = toggleChannelIdMark(peerId.channelId);
876
- break;
870
+ return toggleChannelIdMark(peerId.channelId);
877
871
  default:
878
872
  return peerId;
879
873
  }
880
874
  }
875
+ return peerId;
876
+ }
877
+ async function resolvePeer(client, peerId, force = false) {
878
+ peerId = _normalizePeerId(peerId);
879
+ if (typeof peerId === "object") {
880
+ return peerId;
881
+ }
881
882
  if (typeof peerId === "number" && !force) {
882
883
  const fromStorage = await client.storage.peers.getById(peerId);
883
884
  if (fromStorage) return fromStorage;
@@ -956,7 +957,23 @@ async function resolvePeer(client, peerId, force = false) {
956
957
  throw new MtPeerNotFoundError(`Could not find a peer by ${peerId}`);
957
958
  }
958
959
  const [peerType, bareId] = parseMarkedPeerId(peerId);
959
- if (peerType !== "chat" && !client.storage.self.getCached(true)?.isBot) {
960
+ if (!(peerType === "chat" || client.storage.self.getCached(true)?.isBot)) {
961
+ const cached = await client.storage.peers.getCompleteById(peerId, true);
962
+ if (cached && (cached._ === "channel" || cached._ === "user")) {
963
+ const [username] = extractUsernames(cached);
964
+ if (username) {
965
+ const resolved = await resolvePeer(client, username, true);
966
+ if (getMarkedPeerId(resolved) === peerId) {
967
+ return resolved;
968
+ }
969
+ }
970
+ if (cached._ === "user" && cached.phone) {
971
+ const resolved = await resolvePeer(client, cached.phone, true);
972
+ if (getMarkedPeerId(resolved) === peerId) {
973
+ return resolved;
974
+ }
975
+ }
976
+ }
960
977
  throw new MtPeerNotFoundError(`Peer ${peerId} is not found in local cache`);
961
978
  }
962
979
  switch (peerType) {
@@ -2230,9 +2247,9 @@ class Chat {
2230
2247
  * are always available, but other fields may be omitted
2231
2248
  * despite being available.
2232
2249
  *
2233
- * It was observed that these fields may be missing:
2234
- * - `isMember`
2235
- * - and probably more
2250
+ * For a rough list of fields that may be missing, see the
2251
+ * official docs for [channel](https://core.telegram.org/constructor/channel)
2252
+ * and [user](https://core.telegram.org/constructor/user).
2236
2253
  *
2237
2254
  * This currently only ever happens for non-bot users, so if you are building
2238
2255
  * a normal bot, you can safely ignore this field.
@@ -10108,6 +10125,7 @@ export {
10108
10125
  _convertToTl,
10109
10126
  _convertToTl$2 as _convertToTl$1,
10110
10127
  _findMessageInUpdate,
10128
+ _getChannelsBatched,
10111
10129
  _getDiscussionMessage,
10112
10130
  _getRawPeerBatched,
10113
10131
  _getUsersBatched,
@@ -10117,6 +10135,7 @@ export {
10117
10135
  _normalizeInputFile,
10118
10136
  _normalizeInputMedia,
10119
10137
  _normalizeInputText,
10138
+ _normalizePeerId,
10120
10139
  _normalizeQuickReplyShortcut,
10121
10140
  _storyInteractiveElementFromTl,
10122
10141
  assertIsUpdatesGroup,
@@ -1,8 +1,8 @@
1
1
  import { getPlatform, MtArgumentError, MtcuteError, MtTypeAssertionError, MtUnsupportedError } from "./DBMBgE7t.js";
2
2
  import { tl } from "@mtcute/tl";
3
- import { normalizePhoneNumber, sleepWithAbort, resolveMaybeDynamic, assertNever, normalizeInlineId, isInputPeerChat, isInputPeerChannel, toInputChannel, toInputUser, normalizeDate, isInputPeerUser, makeArrayWithTotal, INVITE_LINK_REGEX, getMarkedPeerId, determinePartSize, ConditionVariable, concatBuffers, bufferToStream, randomLong, makeArrayPaginated, LongMap, toggleChannelIdMark, LongSet } from "./DY1E3mHM.js";
3
+ import { normalizePhoneNumber, sleepWithAbort, resolveMaybeDynamic, assertNever, normalizeInlineId, isInputPeerChat, isInputPeerChannel, toInputChannel, toInputUser, normalizeDate, isInputPeerUser, makeArrayWithTotal, INVITE_LINK_REGEX, getMarkedPeerId, determinePartSize, ConditionVariable, concatBuffers, bufferToStream, randomLong, makeArrayPaginated, LongMap, toggleChannelIdMark, LongSet, parseMarkedPeerId } from "./DY1E3mHM.js";
4
4
  import { assertTypeIs, createControllablePromise, assertTrue, MtInvalidPeerTypeError, isPresent, MtPeerNotFoundError, assertTypeIsNot, MtMessageNotFoundError, hasValueAtKey } from "./BN3qj7tU.js";
5
- import { User$2, SentCode$1, _convertToTl, resolveUser, resolvePeer, normalizeInputMessageId, GameHighScore$2, _findMessageInUpdate, resolvePeerMany, assertIsUpdatesGroup, Chat$2, resolveChannel, createDummyUpdate, ChatEvent$2, ChatMember$2, ChatPreview$2, _getRawPeerBatched, FullChat$2, getPeerDialogs, uploadFile, fileIdToInputPhoto, isUploadedFile, Dialog$2, ChatlistPreview$2, FileLocation$1, fileIdToInputWebFileLocation, fileIdToInputFileLocation, _normalizeInputMedia, parseDocument, Photo$2, ForumTopic$2, ChatInviteLink$2, ChatInviteLinkMember$2, Poll$2, _normalizeInputText, _convertToTl$1, _maybeInvokeWithBusinessConnection, _normalizeQuickReplyShortcut, Message$2, MessageEffect$2, FactCheck$2, _getDiscussionMessage, getMessages, MessageReactions$2, normalizeInputReaction, PeerReaction$2, SearchFilters, sendText, sendMedia, sendMediaGroup, CollectibleInfo$1, TakeoutSession$1, BoostSlot$2, BusinessChatLink$2, BoostStats$1, Boost$2, StarsStatus$2, businessWorkHoursDaysToRaw, MASK_POSITION_POINT_TO_TL, normalizeInputStickerSet, StickerSet$2, fileIdToInputDocument, Story$2, AllStories$2, PeerStories$2, StoryInteractions$2, StoryViewersList$2, StoriesStealthMode$1, _getUsersBatched, _normalizeInputFile } from "./CPnecqvf.js";
5
+ import { User$2, SentCode$1, _convertToTl, resolveUser, resolvePeer, normalizeInputMessageId, GameHighScore$2, _findMessageInUpdate, resolvePeerMany, assertIsUpdatesGroup, Chat$2, resolveChannel, createDummyUpdate, ChatEvent$2, ChatMember$2, ChatPreview$2, _getRawPeerBatched, FullChat$2, getPeerDialogs, uploadFile, fileIdToInputPhoto, isUploadedFile, Dialog$2, ChatlistPreview$2, FileLocation$1, fileIdToInputWebFileLocation, fileIdToInputFileLocation, _normalizeInputMedia, parseDocument, Photo$2, ForumTopic$2, ChatInviteLink$2, ChatInviteLinkMember$2, Poll$2, _normalizeInputText, _convertToTl$1, _maybeInvokeWithBusinessConnection, _normalizeQuickReplyShortcut, Message$2, MessageEffect$2, FactCheck$2, _getDiscussionMessage, getMessages, MessageReactions$2, normalizeInputReaction, PeerReaction$2, SearchFilters, sendText, sendMedia, sendMediaGroup, CollectibleInfo$1, TakeoutSession$1, BoostSlot$2, BusinessChatLink$2, BoostStats$1, Boost$2, StarsStatus$2, businessWorkHoursDaysToRaw, MASK_POSITION_POINT_TO_TL, normalizeInputStickerSet, StickerSet$2, fileIdToInputDocument, Story$2, AllStories$2, PeerStories$2, StoryInteractions$2, StoryViewersList$2, StoriesStealthMode$1, _getUsersBatched, _normalizePeerId, _normalizeInputFile } from "./Btmu4f4t.js";
6
6
  import Long from "long";
7
7
  import { PeersIndex } from "./N3PMYmCL.js";
8
8
  import { tdFileId, parseFileId } from "@mtcute/file-id";
@@ -254,6 +254,8 @@ async function start(client, params) {
254
254
  if (tl.RpcError.is(e)) {
255
255
  if (e.text === "SESSION_PASSWORD_NEEDED") has2fa = true;
256
256
  else if (e.text !== "AUTH_KEY_UNREGISTERED") throw e;
257
+ } else {
258
+ throw e;
257
259
  }
258
260
  }
259
261
  if (!has2fa && !params.qrCodeHandler) {
@@ -4613,6 +4615,36 @@ async function getUsers(client, ids) {
4613
4615
  const res = await Promise.all(inputPeers.map((peer) => _getUsersBatched(client, peer)));
4614
4616
  return res.map((it) => it ? new User$2(it) : null);
4615
4617
  }
4618
+ async function isPeerAvailable(client, peerId) {
4619
+ peerId = _normalizePeerId(peerId);
4620
+ if (typeof peerId === "object") {
4621
+ return true;
4622
+ }
4623
+ if (typeof peerId === "number") {
4624
+ const fromStorage = await client.storage.peers.getById(peerId);
4625
+ if (fromStorage) return true;
4626
+ const [peerType] = parseMarkedPeerId(peerId);
4627
+ if (peerType === "chat" || client.storage.self.getCached(true)?.isBot) {
4628
+ return true;
4629
+ }
4630
+ return false;
4631
+ }
4632
+ if (typeof peerId === "string") {
4633
+ if (peerId === "self" || peerId === "me") {
4634
+ return true;
4635
+ }
4636
+ peerId = peerId.replace(/[@+\s()]/g, "");
4637
+ if (peerId.match(/^\d+$/)) {
4638
+ const fromStorage = await client.storage.peers.getByPhone(peerId);
4639
+ if (fromStorage) return true;
4640
+ } else {
4641
+ const fromStorage = await client.storage.peers.getByUsername(peerId);
4642
+ if (fromStorage) return true;
4643
+ }
4644
+ return false;
4645
+ }
4646
+ return false;
4647
+ }
4616
4648
  async function* iterProfilePhotos(client, userId, params) {
4617
4649
  if (!params) params = {};
4618
4650
  const peer = await resolveUser(client, userId);
@@ -4864,6 +4896,7 @@ export {
4864
4896
  importContacts,
4865
4897
  incrementStoriesViews,
4866
4898
  initTakeoutSession,
4899
+ isPeerAvailable,
4867
4900
  isSelfPeer,
4868
4901
  iterAllStories,
4869
4902
  iterBoosters,