@mtcute/core 0.16.13 → 0.17.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 (36) hide show
  1. package/chunks/cjs/{CntZHjXA.js → BcdQkLTS.js} +83 -15
  2. package/chunks/cjs/{chPq0GcA.js → CSfUPcui.js} +914 -796
  3. package/chunks/cjs/{BO3RV06t.js → kxT7E_JE.js} +3 -3
  4. package/chunks/es/{xihQcMp0.js → BJRm2PAH.js} +3 -3
  5. package/chunks/es/{Jz_hDg6M.js → CbXFWEiB.js} +83 -15
  6. package/chunks/es/{Btmu4f4t.js → DKzd1_Yg.js} +914 -796
  7. package/client.cjs +21 -9
  8. package/client.js +21 -9
  9. package/highlevel/client.d.ts +109 -25
  10. package/highlevel/methods/files/upload-file.d.ts +8 -0
  11. package/highlevel/methods/premium/accept-star-gift.d.ts +16 -0
  12. package/highlevel/methods/premium/get-star-gift-options.d.ts +6 -0
  13. package/highlevel/methods/premium/get-star-gifts.d.ts +22 -0
  14. package/highlevel/methods/premium/iter-star-gifts.d.ts +26 -0
  15. package/highlevel/methods/premium/send-star-gift.d.ts +35 -0
  16. package/highlevel/methods/stickers/create-sticker-set.d.ts +1 -7
  17. package/highlevel/methods.d.ts +5 -1
  18. package/highlevel/types/bots/keyboards/factories.d.ts +7 -0
  19. package/highlevel/types/media/video.d.ts +1 -0
  20. package/highlevel/types/messages/message-action.d.ts +19 -2
  21. package/highlevel/types/misc/sticker-set.d.ts +1 -5
  22. package/highlevel/types/premium/index.d.ts +1 -0
  23. package/highlevel/types/premium/stars-gift.d.ts +57 -0
  24. package/highlevel/types/premium/stars-transaction.d.ts +8 -0
  25. package/index.cjs +5 -3
  26. package/index.js +7 -5
  27. package/methods.cjs +7 -3
  28. package/methods.js +7 -3
  29. package/network/client.d.ts +1 -1
  30. package/network/multi-session-connection.d.ts +1 -1
  31. package/network/persistent-connection.d.ts +1 -1
  32. package/network/transports/abstract.d.ts +1 -1
  33. package/network/transports/streamed.d.ts +1 -1
  34. package/network/transports/wrapped.d.ts +1 -1
  35. package/package.json +4 -4
  36. package/highlevel/methods/stories/report-story.d.ts +0 -19
@@ -1218,6 +1218,13 @@ function requestPeer(text2, buttonId, params) {
1218
1218
  maxQuantity: params.count ?? 1
1219
1219
  };
1220
1220
  }
1221
+ function copy(params) {
1222
+ return {
1223
+ _: "keyboardButtonCopy",
1224
+ text: params.text,
1225
+ copyText: params?.copyText ?? params.text
1226
+ };
1227
+ }
1221
1228
  function findButton(buttons, predicate) {
1222
1229
  if (typeof predicate === "string") {
1223
1230
  const text2 = predicate;
@@ -1295,6 +1302,7 @@ const factories$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
1295
1302
  _rowsTo2d,
1296
1303
  builder,
1297
1304
  callback,
1305
+ copy,
1298
1306
  findButton,
1299
1307
  forceReply,
1300
1308
  game: game$2,
@@ -3148,945 +3156,1044 @@ class Photo extends FileLocation$1 {
3148
3156
  }
3149
3157
  const Photo$1 = /* @__PURE__ */ memoizeGetters(Photo, ["thumbnails", "fileId", "uniqueFileId"]);
3150
3158
  const Photo$2 = /* @__PURE__ */ makeInspectable(Photo$1, ["fileSize", "dcId", "width", "height"], ["inputMedia", "inputPhoto"]);
3151
- function _messageActionFromTl(act) {
3152
- switch (act._) {
3153
- case "messageActionChatCreate":
3154
- return {
3155
- type: "chat_created",
3156
- title: act.title,
3157
- users: act.users
3158
- };
3159
- case "messageActionChannelCreate":
3160
- return {
3161
- type: "channel_created",
3162
- title: act.title
3163
- };
3164
- case "messageActionChatMigrateTo":
3165
- return {
3166
- type: "chat_migrate_to",
3167
- id: act.channelId
3168
- };
3169
- case "messageActionChannelMigrateFrom":
3170
- return {
3171
- type: "channel_migrate_from",
3172
- id: act.chatId,
3173
- title: act.title
3174
- };
3175
- case "messageActionPinMessage":
3176
- return {
3177
- type: "message_pinned"
3178
- };
3179
- case "messageActionHistoryClear":
3180
- return {
3181
- type: "history_cleared"
3182
- };
3183
- case "messageActionGameScore":
3184
- return {
3185
- type: "game_score",
3186
- gameId: act.gameId,
3187
- score: act.score
3188
- };
3189
- case "messageActionContactSignUp":
3190
- return {
3191
- type: "contact_joined"
3192
- };
3193
- case "messageActionChatEditTitle":
3194
- return {
3195
- type: "title_changed",
3196
- title: act.title
3197
- };
3198
- case "messageActionChatEditPhoto":
3199
- return {
3200
- type: "photo_changed",
3201
- photo: new Photo$2(act.photo)
3202
- };
3203
- case "messageActionChatDeletePhoto":
3204
- return {
3205
- type: "photo_deleted"
3206
- };
3207
- case "messageActionChatAddUser":
3208
- return {
3209
- type: "users_added",
3210
- users: act.users
3211
- };
3212
- case "messageActionChatDeleteUser":
3213
- if (this.raw.fromId?._ === "peerUser" && act.userId === this.raw.fromId.userId) {
3214
- return {
3215
- type: "user_left"
3216
- };
3217
- }
3218
- return {
3219
- type: "user_removed",
3220
- user: act.userId
3221
- };
3222
- case "messageActionChatJoinedByLink":
3223
- return {
3224
- type: "user_joined_link",
3225
- inviter: act.inviterId
3226
- };
3227
- case "messageActionPaymentSentMe":
3228
- return {
3229
- type: "payment_received",
3230
- currency: act.currency,
3231
- amount: act.totalAmount,
3232
- payload: act.payload,
3233
- info: act.info,
3234
- shippingOptionId: act.shippingOptionId,
3235
- charge: act.charge
3236
- };
3237
- case "messageActionPaymentSent":
3238
- return {
3239
- type: "payment_sent",
3240
- currency: act.currency,
3241
- amount: act.totalAmount
3242
- };
3243
- case "messageActionPhoneCall":
3244
- return {
3245
- type: "call",
3246
- id: act.callId,
3247
- isVideo: Boolean(act.video),
3248
- reason: act.reason ? _callDiscardReasonFromTl(act.reason) : void 0,
3249
- duration: act.duration ?? 0
3250
- };
3251
- case "messageActionScreenshotTaken":
3252
- return {
3253
- type: "screenshot_taken"
3254
- };
3255
- case "messageActionBotAllowed":
3256
- return {
3257
- type: "bot_allowed",
3258
- domain: act.domain
3259
- };
3260
- case "messageActionGeoProximityReached":
3261
- if (act.fromId._ !== "peerUser" || act.toId._ !== "peerUser") {
3262
- return null;
3159
+ class RawDocument extends FileLocation$1 {
3160
+ constructor(raw) {
3161
+ super(
3162
+ {
3163
+ _: "inputDocumentFileLocation",
3164
+ id: raw.id,
3165
+ fileReference: raw.fileReference,
3166
+ accessHash: raw.accessHash,
3167
+ thumbSize: ""
3168
+ },
3169
+ raw.size,
3170
+ raw.dcId
3171
+ );
3172
+ this.raw = raw;
3173
+ this.raw = raw;
3174
+ }
3175
+ /**
3176
+ * Original file name, extracted from the document
3177
+ * attributes.
3178
+ */
3179
+ get fileName() {
3180
+ const attr = this.raw.attributes.find((it) => it._ === "documentAttributeFilename");
3181
+ return attr?.fileName ?? null;
3182
+ }
3183
+ /**
3184
+ * File MIME type, as defined by the sender.
3185
+ */
3186
+ get mimeType() {
3187
+ return this.raw.mimeType;
3188
+ }
3189
+ /**
3190
+ * Date the document was sent
3191
+ */
3192
+ get date() {
3193
+ return new Date(this.raw.date * 1e3);
3194
+ }
3195
+ /**
3196
+ * Available thumbnails, if any.
3197
+ *
3198
+ * If there are no thumbnails, the array will be empty.
3199
+ */
3200
+ get thumbnails() {
3201
+ const arr = [];
3202
+ this.raw.thumbs?.forEach((sz) => arr.push(new Thumbnail$2(this.raw, sz)));
3203
+ this.raw.videoThumbs?.forEach((sz) => arr.push(new Thumbnail$2(this.raw, sz)));
3204
+ return arr;
3205
+ }
3206
+ /**
3207
+ * Get a thumbnail by its type.
3208
+ *
3209
+ * Thumbnail types are described in the
3210
+ * [Telegram docs](https://core.telegram.org/api/files#image-thumbnail-types),
3211
+ * and are also available as static members of {@link Thumbnail} for convenience.
3212
+ *
3213
+ * @param type Thumbnail type
3214
+ */
3215
+ getThumbnail(type) {
3216
+ return this.thumbnails.find((it) => {
3217
+ if (it.raw._ === "videoSizeEmojiMarkup" || it.raw._ === "videoSizeStickerMarkup") {
3218
+ return false;
3263
3219
  }
3264
- return {
3265
- type: "geo_proximity",
3266
- targetId: act.toId.userId,
3267
- userId: act.fromId.userId,
3268
- distance: act.distance
3269
- };
3270
- case "messageActionGroupCall":
3271
- if (act.duration) {
3272
- return {
3273
- type: "group_call_ended",
3274
- call: act.call,
3275
- duration: act.duration
3276
- };
3220
+ return it.raw.type === type;
3221
+ }) ?? null;
3222
+ }
3223
+ /**
3224
+ * Input document TL object generated from this object,
3225
+ * to be used with methods that use it
3226
+ */
3227
+ get inputDocument() {
3228
+ return {
3229
+ _: "inputDocument",
3230
+ id: this.raw.id,
3231
+ accessHash: this.raw.accessHash,
3232
+ fileReference: this.raw.fileReference
3233
+ };
3234
+ }
3235
+ /**
3236
+ * Input media TL object generated from this object,
3237
+ * to be used inside {@link InputMediaLike} and
3238
+ * {@link TelegramClient.sendMedia}
3239
+ */
3240
+ get inputMedia() {
3241
+ return {
3242
+ _: "inputMediaDocument",
3243
+ id: this.inputDocument
3244
+ };
3245
+ }
3246
+ _fileIdType() {
3247
+ return tdFileId.FileType.Document;
3248
+ }
3249
+ /**
3250
+ * Get TDLib and Bot API compatible File ID
3251
+ * representing this document.
3252
+ */
3253
+ get fileId() {
3254
+ return toFileId(getPlatform(), {
3255
+ type: this._fileIdType(),
3256
+ dcId: this.raw.dcId,
3257
+ fileReference: this.raw.fileReference,
3258
+ location: {
3259
+ _: "common",
3260
+ id: this.raw.id,
3261
+ accessHash: this.raw.accessHash
3277
3262
  }
3278
- return {
3279
- type: "group_call_started",
3280
- call: act.call
3281
- };
3282
- case "messageActionGroupCallScheduled":
3283
- return {
3284
- type: "group_call_scheduled",
3285
- call: act.call,
3286
- date: new Date(act.scheduleDate * 1e3)
3287
- };
3288
- case "messageActionInviteToGroupCall":
3289
- return {
3290
- type: "group_call_invite",
3291
- call: act.call,
3292
- userIds: act.users
3293
- };
3294
- case "messageActionSetMessagesTTL":
3295
- return {
3296
- type: "ttl_changed",
3297
- period: act.period
3298
- };
3299
- case "messageActionTopicCreate":
3300
- return {
3301
- type: "topic_created",
3302
- title: act.title,
3303
- iconColor: act.iconColor,
3304
- iconCustomEmoji: act.iconEmojiId
3305
- };
3306
- case "messageActionTopicEdit":
3307
- return {
3308
- type: "topic_edited",
3309
- title: act.title,
3310
- iconCustomEmoji: act.iconEmojiId,
3311
- closed: act.closed,
3312
- hidden: act.hidden
3313
- };
3314
- case "messageActionCustomAction":
3315
- return {
3316
- type: "custom",
3317
- action: act.message
3318
- };
3319
- case "messageActionSetChatTheme":
3320
- return {
3321
- type: "theme_changed",
3322
- emoji: act.emoticon
3323
- };
3324
- case "messageActionChatJoinedByRequest":
3325
- return {
3326
- type: "user_joined_approved"
3327
- };
3328
- case "messageActionWebViewDataSent":
3329
- return {
3330
- type: "webview_sent",
3331
- text: act.text
3332
- };
3333
- case "messageActionWebViewDataSentMe":
3334
- return {
3335
- type: "webview_received",
3336
- text: act.text,
3337
- data: act.data
3338
- };
3339
- case "messageActionGiftPremium":
3340
- return {
3341
- type: "premium_gifted",
3342
- currency: act.currency,
3343
- amount: act.amount.toNumber(),
3344
- months: act.months,
3345
- crypto: act.cryptoAmount ? {
3346
- currency: act.cryptoCurrency,
3347
- amount: act.cryptoAmount.toNumber()
3348
- } : void 0
3349
- };
3350
- case "messageActionSuggestProfilePhoto":
3351
- return {
3352
- type: "photo_suggested",
3353
- photo: new Photo$2(act.photo)
3354
- };
3355
- case "messageActionRequestedPeerSentMe":
3356
- return {
3357
- type: "peer_sent",
3358
- buttonId: act.buttonId,
3359
- peers: act.peers
3360
- };
3361
- case "messageActionRequestedPeer":
3362
- return {
3363
- type: "peer_chosen",
3364
- buttonId: act.buttonId,
3365
- peers: act.peers.map((it) => parsePeer(it, this._peers))
3366
- };
3367
- case "messageActionSetChatWallPaper":
3368
- return {
3369
- type: "wallpaper_changed",
3370
- same: act.same,
3371
- forBoth: act.forBoth,
3372
- wallpaper: act.wallpaper
3373
- };
3374
- case "messageActionGiftCode":
3375
- return {
3376
- type: "gift_code",
3377
- raw: act
3378
- };
3379
- case "messageActionGiveawayLaunch":
3380
- return {
3381
- type: "giveaway_started"
3382
- };
3383
- case "messageActionGiveawayResults":
3384
- return {
3385
- type: "giveaway_ended",
3386
- winners: act.winnersCount,
3387
- undistributed: act.unclaimedCount
3388
- };
3389
- case "messageActionBoostApply":
3390
- return {
3391
- type: "boost_apply",
3392
- count: act.boosts
3393
- };
3394
- case "messageActionPaymentRefunded":
3395
- return {
3396
- type: "payment_refunded",
3397
- currency: act.currency,
3398
- peerId: getMarkedPeerId(act.peer),
3399
- amount: act.totalAmount,
3400
- payload: act.payload,
3401
- charge: act.charge
3402
- };
3403
- case "messageActionGiftStars":
3404
- return {
3405
- type: "stars_gifted",
3406
- isCrypto: Boolean(act.cryptoCurrency),
3407
- currency: act.cryptoCurrency ?? act.currency,
3408
- amount: act.cryptoAmount ?? act.amount,
3409
- stars: act.stars,
3410
- transactionId: act.transactionId
3411
- };
3412
- case "messageActionPrizeStars":
3413
- return {
3414
- type: "stars_prize",
3415
- claimed: !act.unclaimed,
3416
- stars: act.stars,
3417
- transactionId: act.transactionId,
3418
- boostPeer: parsePeer(act.boostPeer, this._peers),
3419
- giveawayMessageId: act.giveawayMsgId
3420
- };
3421
- default:
3422
- return null;
3423
- }
3424
- }
3425
- class MessageForwardInfo {
3426
- constructor(raw, _peers) {
3427
- this.raw = raw;
3428
- this._peers = _peers;
3263
+ });
3429
3264
  }
3430
3265
  /**
3431
- * Date the original message was sent
3266
+ * Get a unique File ID representing this document.
3432
3267
  */
3433
- get date() {
3434
- return new Date(this.raw.date * 1e3);
3268
+ get uniqueFileId() {
3269
+ return toUniqueFileId(getPlatform(), tdFileId.FileType.Document, {
3270
+ _: "common",
3271
+ id: this.raw.id
3272
+ });
3435
3273
  }
3436
- /**
3437
- * Sender of the original message (either user or a channel)
3438
- * or their name (for users with private forwards)
3439
- */
3440
- get sender() {
3441
- if (this.raw.fromName) {
3442
- return {
3443
- type: "anonymous",
3444
- displayName: this.raw.fromName
3445
- };
3446
- }
3447
- if (this.raw.fromId) {
3448
- return parsePeer(this.raw.fromId, this._peers);
3449
- }
3450
- throw new MtTypeAssertionError("MessageForwardInfo", "to have fromId or fromName", "neither");
3274
+ }
3275
+ class Document extends RawDocument {
3276
+ type = "document";
3277
+ }
3278
+ const Document$1 = /* @__PURE__ */ memoizeGetters(Document, ["fileName", "thumbnails", "fileId", "uniqueFileId"]);
3279
+ const Document$2 = /* @__PURE__ */ makeInspectable(Document$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3280
+ class Audio extends RawDocument {
3281
+ constructor(doc, attr) {
3282
+ super(doc);
3283
+ this.attr = attr;
3284
+ }
3285
+ /** Type of the media (for use in a tagged union) */
3286
+ type = "audio";
3287
+ /** Type of the file for File ID generation */
3288
+ _fileIdType() {
3289
+ return tdFileId.FileType.Audio;
3451
3290
  }
3452
3291
  /**
3453
- * For "saved" messages (i.e. messages forwarded to yourself,
3454
- * "Saved Messages"), the peer where the message was originally sent
3292
+ * Duration of the audio in seconds.
3293
+ *
3294
+ * May not be accurate since provided by the sender.
3455
3295
  */
3456
- fromChat() {
3457
- if (!this.raw.savedFromPeer) return null;
3458
- return Chat$2._parseFromPeer(this.raw.savedFromPeer, this._peers);
3296
+ get duration() {
3297
+ return this.attr.duration;
3459
3298
  }
3460
3299
  /**
3461
- * For messages forwarded from channels,
3462
- * identifier of the original message in the channel
3300
+ * Performer of the audio track.
3463
3301
  */
3464
- get fromMessageId() {
3465
- return this.raw.savedFromMsgId ?? null;
3302
+ get performer() {
3303
+ return this.attr.performer ?? null;
3466
3304
  }
3467
3305
  /**
3468
- * For messages forwarded from channels,
3469
- * signature of the post author (if present)
3306
+ * Title of the audio track.
3470
3307
  */
3471
- get signature() {
3472
- return this.raw.postAuthor ?? null;
3308
+ get title() {
3309
+ return this.attr.title ?? null;
3473
3310
  }
3474
3311
  }
3475
- const MessageForwardInfo$1 = /* @__PURE__ */ memoizeGetters(MessageForwardInfo, ["sender", "fromChat"]);
3476
- const MessageForwardInfo$2 = /* @__PURE__ */ makeInspectable(MessageForwardInfo$1);
3477
- class Contact {
3478
- constructor(obj) {
3479
- this.obj = obj;
3312
+ const Audio$1 = /* @__PURE__ */ memoizeGetters(Audio, ["fileName", "thumbnails", "fileId", "uniqueFileId"]);
3313
+ const Audio$2 = /* @__PURE__ */ makeInspectable(Audio$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3314
+ const MASK_POSITION_POINT_TO_TL = {
3315
+ forehead: 0,
3316
+ eyes: 1,
3317
+ mouth: 2,
3318
+ chin: 3
3319
+ };
3320
+ const MASK_POS = ["forehead", "eyes", "mouth", "chin"];
3321
+ class Sticker extends RawDocument {
3322
+ constructor(doc, attr, attr2) {
3323
+ super(doc);
3324
+ this.attr = attr;
3325
+ this.attr2 = attr2;
3480
3326
  }
3481
- type = "contact";
3482
- /**
3483
- * Contact's phone number
3484
- */
3485
- get phoneNumber() {
3486
- return this.obj.phoneNumber;
3327
+ type = "sticker";
3328
+ _fileIdType() {
3329
+ return tdFileId.FileType.Sticker;
3487
3330
  }
3488
3331
  /**
3489
- * Contact's first name
3332
+ * Sticker width in pixels
3490
3333
  */
3491
- get firstName() {
3492
- return this.obj.firstName;
3334
+ get width() {
3335
+ return this.attr2?.w ?? 512;
3493
3336
  }
3494
3337
  /**
3495
- * Contact's last name
3338
+ * Sticker height in pixels
3496
3339
  */
3497
- get lastName() {
3498
- return this.obj.lastName;
3340
+ get height() {
3341
+ return this.attr2?.h ?? 512;
3499
3342
  }
3500
3343
  /**
3501
- * Contact's user ID in Telegram or `0` if not available
3344
+ * Whether this sticker is a premium sticker
3345
+ * (has premium fullscreen animation)
3502
3346
  */
3503
- get userId() {
3504
- return this.obj.userId;
3347
+ get isPremiumSticker() {
3348
+ return Boolean(this.raw.videoThumbs?.some((s) => s._ === "videoSize" && s.type === "f"));
3505
3349
  }
3506
3350
  /**
3507
- * Input media TL object generated from this object,
3508
- * to be used inside {@link InputMediaLike} and
3509
- * {@link TelegramClient.sendMedia}
3351
+ * Whether this sticker is a valid sticker.
3352
+ *
3353
+ * If it is not, then this is probably a WEBP photo
3354
+ * that Telegram treats as a sticker.
3510
3355
  */
3511
- get inputMedia() {
3512
- return {
3513
- ...this.obj,
3514
- _: "inputMediaContact"
3515
- };
3356
+ get isValidSticker() {
3357
+ return this.attr2 !== void 0 && (this.attr2.w === 512 || this.attr2.h === 512);
3516
3358
  }
3517
- }
3518
- const Contact$1 = /* @__PURE__ */ makeInspectable(Contact, void 0, ["inputMedia"]);
3519
- class Dice {
3520
- constructor(obj) {
3521
- this.obj = obj;
3522
- }
3523
- type = "dice";
3524
3359
  /**
3525
- * A simple 6-sided dice.
3360
+ * Primary emoji associated with this sticker,
3361
+ * that is displayed in dialogs list.
3526
3362
  *
3527
- * {@link value} represents its value (1-6)
3528
- */
3529
- static TYPE_DICE = "🎲";
3530
- /**
3531
- * A dart. Telegram dart has 4 rings and middle.
3363
+ * If there is none, empty string is returned.
3532
3364
  *
3533
- * {@link value} represents the position of the dart:
3534
- * ![Dart position graph](https://i.imgur.com/iPBm7HG.png)
3365
+ * **Note:** This only contains at most one emoji.
3366
+ * Some stickers have multiple associated emojis,
3367
+ * but only one is returned here. This is Telegram's
3368
+ * limitation! Use {@link getAllEmojis} instead.
3369
+ *
3370
+ * For custom emojis, this alt should be used as a fallback
3371
+ * text that will be "behind" the custom emoji entity.
3535
3372
  */
3536
- static TYPE_DART = "🎯";
3373
+ get emoji() {
3374
+ return this.attr.alt;
3375
+ }
3537
3376
  /**
3538
- * A basketball thrown into a hoop.
3377
+ * Whether this custom emoji can be used by non-premium users.
3378
+ * `false` if this is not a custom emoji.
3539
3379
  *
3540
- * {@link value} represents the motion of the ball:
3541
- * - 1: simple miss (ball hits right part, bounces to the left)
3542
- * - 2: first hit the ring, then miss
3543
- * - 3: ball gets stuck between the ring and the base
3544
- * - 4: first hit the ring, then score
3545
- * - 5: direct score
3380
+ * > Not sure if there are any such stickers currently.
3546
3381
  */
3547
- static TYPE_BASKETBALL = "🏀";
3382
+ get customEmojiFree() {
3383
+ return this.attr._ === "documentAttributeCustomEmoji" ? this.attr.free ?? false : false;
3384
+ }
3548
3385
  /**
3549
- * A football thrown to the gate.
3550
- *
3551
- * {@link value} represents the motion of the ball:
3552
- * - 1: flies above the top barbell
3553
- * - 2: hits right barbell, then miss
3554
- * - 3: direct score in the middle
3555
- * - 4: hits left barbell, then score, then hits right barbell
3556
- * - 5: score in the top-right corner
3386
+ * If this is a custom emoji, its unique ID
3387
+ * that can be used in {@link TelegramClient#getCustomEmojis}
3557
3388
  */
3558
- static TYPE_FOOTBALL = "⚽️";
3389
+ get customEmojiId() {
3390
+ if (this.attr._ !== "documentAttributeCustomEmoji") {
3391
+ throw new MtArgumentError("This is not a custom emoji");
3392
+ }
3393
+ return this.raw.id;
3394
+ }
3559
3395
  /**
3560
- * A bowling ball thrown to pins.
3561
- *
3562
- * Assuming the following identifiers for the pins:
3563
- * ```
3564
- * 4 5 6
3565
- * 2 3
3566
- * 1
3567
- * ```
3568
- *
3569
- * {@link value} represents the motion of the ball and pins:
3570
- * - 1: the ball touched 6th pin, none are down
3571
- * - 2: the ball hit 4th pin, only 4th pin is down.
3572
- * - 3: the ball hit 1st pin, pins 1, 2, 5 are down, leaving pins 3, 4, 6
3573
- * - 4: the ball hit 1st pin on the right side, all the pins except 2nd and 6th are down
3574
- * - 5: the ball hit 3rd pin and all the pins except 2nd are down.
3575
- * - 6: the ball hit 1st pin and all pins are down
3396
+ * Type of the sticker
3576
3397
  */
3577
- static TYPE_BOWLING = "🎳";
3398
+ get stickerType() {
3399
+ if (this.attr._ === "documentAttributeSticker") {
3400
+ return this.attr.mask ? "mask" : "sticker";
3401
+ } else if (this.attr._ === "documentAttributeCustomEmoji") {
3402
+ return "emoji";
3403
+ }
3404
+ return "sticker";
3405
+ }
3578
3406
  /**
3579
- * A slot machine.
3580
- *
3581
- * {@link value} represents the result of the machine.
3582
- * Value itself is an integer in range `[1, 64]`,
3583
- * and is composed out of several parts.
3584
- *
3585
- * > **Note**: The following information is based on the TDesktop
3586
- * > implementation. These are the relevant files:
3587
- * > - [`chat_helpers/stickers_dice_pack.cpp`](https://github.com/telegramdesktop/tdesktop/blob/dev/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp)
3588
- * > - [`history/view/media/history_view_slot_machine.cpp`](https://github.com/telegramdesktop/tdesktop/blob/dev/Telegram/SourceFiles/history/view/media/history_view_slot_machine.cpp)
3589
- *
3590
- * Unlike other animated dices, this does not have
3591
- * all the possible combinations in the sticker set.
3592
- * Instead, `value` is a specially encoded integer that contains
3593
- * the information about the indexes.
3594
- *
3595
- * There are some base parts of the animations:
3596
- * - 0th sticker is the base background of the machine
3597
- * - 1st sticker is the background of the machine for the "winning" state (i.e. `777`)
3598
- * - 2nd sticker is the frame of the machine, including the handle
3599
- * - 8th sticker is the "idle" state for the left slot
3600
- * - 14th sticker is the "idle" state for the middle slot
3601
- * - 20th sticker is the "idle" state for the right slot
3602
- *
3603
- * The machine result is encoded as 3 concatenated two-bit integers,
3604
- * and the resulting integer is incremented by one.
3605
- *
3606
- * So, to decode the value to its parts, you can use this code:
3607
- * ```typescript
3608
- * const computePartValue = (val: number, idx: number) => ((val - 1) >> (idx * 2)) & 0x03; // 0..3
3609
- * const parts = [
3610
- * computePartValue(msg.media.value, 0),
3611
- * computePartValue(msg.media.value, 1),
3612
- * computePartValue(msg.media.value, 2),
3613
- * ]
3614
- * ```
3615
- *
3616
- * Each part of the value corresponds to a particular slot (i.e. part 0 is left slot,
3617
- * part 1 is middle, part 2 is right). The slot values are as follows:
3618
- * - 0: BAR (displayed as a *BAR* sign on a black background)
3619
- * - 1: BERRIES (displayed as berries, similar to emoji 🍇)
3620
- * - 2: LEMON (displayed as a lemon, similar to emoji 🍋)
3621
- * - 3: SEVEN (displayed as a red digit 7)
3622
- *
3623
- * Therefore, the winning value (i.e. `777`) is represented as `(3 << 4 | 3 << 2 | 3 << 0) + 1 = 64`
3624
- *
3625
- * To determine the needed animation parts, you'll need to apply some shifts.
3626
- * These are the offsets for the individual symbols:
3627
- * - WIN_SEVEN: 0
3628
- * - SEVEN: 1
3629
- * - BAR: 2
3630
- * - BERRIES: 3
3631
- * - LEMON: 4
3632
- *
3633
- * And these are the shifts for each slot:
3634
- * - LEFT: 3
3635
- * - MIDDLE: 9
3636
- * - RIGHT: 15
3637
- *
3638
- * > WIN_SEVEN is the same as SEVEN, but only used if the machine result is `777` (i.e. `value = 64`),
3639
- * > as it contains additional "blinking" animation.
3640
- *
3641
- * The sticker index is computed as follows: `SHIFTS[SLOT] + OFFSETS[SYM]`.
3642
- * For example, berries for the middle slot would be: `SHIFTS[MIDDLE] + OFFSETS[BERRIES] = 9 + 3 = 12`
3643
- *
3644
- * Currently, this sticker set is used for the machine: [SlotMachineAnimated](https://t.me/addstickers/SlotMachineAnimated)
3407
+ * Type of the file representing the sticker
3645
3408
  */
3646
- static TYPE_SLOTS = "🎰";
3409
+ get sourceType() {
3410
+ if (this.attr2?._ === "documentAttributeVideo") {
3411
+ return "video";
3412
+ }
3413
+ return this.mimeType === "application/x-tgsticker" ? "animated" : "static";
3414
+ }
3647
3415
  /**
3648
- * An emoji which was originally sent.
3649
- *
3650
- * See static members of {@link Dice} for a list
3651
- * of possible values
3416
+ * Whether this sticker has an associated public sticker set.
3652
3417
  */
3653
- get emoji() {
3654
- return this.obj.emoticon;
3418
+ get hasStickerSet() {
3419
+ return this.attr.stickerset._ === "inputStickerSetID";
3655
3420
  }
3656
3421
  /**
3657
- * Emoji's interactive value.
3658
- *
3659
- * See what this value represents in the corresponding
3660
- * type's documentation (in {@link Dice} static fields)
3422
+ * Input sticker set that it associated with this sticker, if available.
3661
3423
  */
3662
- get value() {
3663
- return this.obj.value;
3424
+ get inputStickerSet() {
3425
+ return this.attr.stickerset._ === "inputStickerSetEmpty" ? null : this.attr.stickerset;
3664
3426
  }
3665
3427
  /**
3666
- * Input media TL object generated from this object,
3667
- * to be used inside {@link InputMediaLike} and
3668
- * {@link TelegramClient.sendMedia}
3669
- *
3670
- * Note that when you use this media, a new `value`
3671
- * will be generated!
3428
+ * Position where this mask should be placed
3672
3429
  */
3673
- get inputMedia() {
3430
+ get maskPosition() {
3431
+ if (this.attr._ !== "documentAttributeSticker" || !this.attr.maskCoords) {
3432
+ return null;
3433
+ }
3434
+ const raw = this.attr.maskCoords;
3674
3435
  return {
3675
- _: "inputMediaDice",
3676
- emoticon: this.obj.emoticon
3436
+ point: MASK_POS[raw.n],
3437
+ x: raw.x,
3438
+ y: raw.y,
3439
+ scale: raw.zoom
3677
3440
  };
3678
3441
  }
3679
3442
  }
3680
- const Dice$1 = /* @__PURE__ */ makeInspectable(Dice, void 0, ["inputMedia"]);
3681
- class RawDocument extends FileLocation$1 {
3682
- constructor(raw) {
3683
- super(
3684
- {
3685
- _: "inputDocumentFileLocation",
3686
- id: raw.id,
3687
- fileReference: raw.fileReference,
3688
- accessHash: raw.accessHash,
3689
- thumbSize: ""
3690
- },
3691
- raw.size,
3692
- raw.dcId
3693
- );
3694
- this.raw = raw;
3695
- this.raw = raw;
3443
+ const Sticker$1 = /* @__PURE__ */ memoizeGetters(Sticker, ["fileName", "thumbnails", "fileId", "uniqueFileId", "maskPosition"]);
3444
+ const Sticker$2 = /* @__PURE__ */ makeInspectable(Sticker$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3445
+ class Video extends RawDocument {
3446
+ constructor(doc, attr, media2) {
3447
+ super(doc);
3448
+ this.attr = attr;
3449
+ this.media = media2;
3450
+ }
3451
+ type = "video";
3452
+ _fileIdType() {
3453
+ if (this.isRound) return tdFileId.FileType.VideoNote;
3454
+ if (this.isAnimation) return tdFileId.FileType.Animation;
3455
+ return tdFileId.FileType.Video;
3696
3456
  }
3697
3457
  /**
3698
- * Original file name, extracted from the document
3699
- * attributes.
3458
+ * Video width in pixels
3700
3459
  */
3701
- get fileName() {
3702
- const attr = this.raw.attributes.find((it) => it._ === "documentAttributeFilename");
3703
- return attr?.fileName ?? null;
3460
+ get width() {
3461
+ return this.attr.w;
3704
3462
  }
3705
3463
  /**
3706
- * File MIME type, as defined by the sender.
3464
+ * Video height in pixels
3707
3465
  */
3708
- get mimeType() {
3709
- return this.raw.mimeType;
3466
+ get height() {
3467
+ return this.attr.h;
3710
3468
  }
3711
3469
  /**
3712
- * Date the document was sent
3470
+ * Video duration in seconds.
3471
+ *
3472
+ * `0` for legacy GIFs
3713
3473
  */
3714
- get date() {
3715
- return new Date(this.raw.date * 1e3);
3474
+ get duration() {
3475
+ return this.attr._ === "documentAttributeVideo" ? this.attr.duration : 0;
3716
3476
  }
3717
3477
  /**
3718
- * Available thumbnails, if any.
3719
- *
3720
- * If there are no thumbnails, the array will be empty.
3478
+ * Whether this video is an animated GIF
3479
+ * (represented either by actual GIF or a silent MP4 video)
3721
3480
  */
3722
- get thumbnails() {
3723
- const arr = [];
3724
- this.raw.thumbs?.forEach((sz) => arr.push(new Thumbnail$2(this.raw, sz)));
3725
- this.raw.videoThumbs?.forEach((sz) => arr.push(new Thumbnail$2(this.raw, sz)));
3726
- return arr;
3481
+ get isAnimation() {
3482
+ return this.attr._ === "documentAttributeImageSize" || this.raw.attributes.some((it) => it._ === "documentAttributeAnimated");
3727
3483
  }
3728
3484
  /**
3729
- * Get a thumbnail by its type.
3730
- *
3731
- * Thumbnail types are described in the
3732
- * [Telegram docs](https://core.telegram.org/api/files#image-thumbnail-types),
3733
- * and are also available as static members of {@link Thumbnail} for convenience.
3734
- *
3735
- * @param type Thumbnail type
3485
+ * Whether this video is a round video message (aka video note)
3736
3486
  */
3737
- getThumbnail(type) {
3738
- return this.thumbnails.find((it) => {
3739
- if (it.raw._ === "videoSizeEmojiMarkup" || it.raw._ === "videoSizeStickerMarkup") {
3740
- return false;
3741
- }
3742
- return it.raw.type === type;
3743
- }) ?? null;
3487
+ get isRound() {
3488
+ return this.attr._ === "documentAttributeVideo" && Boolean(this.attr.roundMessage);
3744
3489
  }
3745
3490
  /**
3746
- * Input document TL object generated from this object,
3747
- * to be used with methods that use it
3491
+ * Whether this video is a legacy GIF (i.e. its MIME is `image/gif`)
3748
3492
  */
3749
- get inputDocument() {
3750
- return {
3751
- _: "inputDocument",
3752
- id: this.raw.id,
3753
- accessHash: this.raw.accessHash,
3754
- fileReference: this.raw.fileReference
3755
- };
3493
+ get isLegacyGif() {
3494
+ return this.attr._ === "documentAttributeImageSize";
3756
3495
  }
3757
- /**
3758
- * Input media TL object generated from this object,
3759
- * to be used inside {@link InputMediaLike} and
3760
- * {@link TelegramClient.sendMedia}
3761
- */
3762
- get inputMedia() {
3763
- return {
3764
- _: "inputMediaDocument",
3765
- id: this.inputDocument
3766
- };
3496
+ /** Whether this video is hidden with a spoiler */
3497
+ get hasSpoiler() {
3498
+ return this.media?.spoiler ?? false;
3767
3499
  }
3768
- _fileIdType() {
3769
- return tdFileId.FileType.Document;
3500
+ /** For self-destructing videos, TTL in seconds */
3501
+ get ttlSeconds() {
3502
+ return this.media?.ttlSeconds ?? null;
3770
3503
  }
3771
- /**
3772
- * Get TDLib and Bot API compatible File ID
3773
- * representing this document.
3774
- */
3775
- get fileId() {
3776
- return toFileId(getPlatform(), {
3777
- type: this._fileIdType(),
3778
- dcId: this.raw.dcId,
3779
- fileReference: this.raw.fileReference,
3780
- location: {
3781
- _: "common",
3782
- id: this.raw.id,
3783
- accessHash: this.raw.accessHash
3784
- }
3785
- });
3504
+ get videoStartTs() {
3505
+ return this.attr._ === "documentAttributeVideo" ? this.attr.videoStartTs ?? null : null;
3786
3506
  }
3787
- /**
3788
- * Get a unique File ID representing this document.
3789
- */
3790
- get uniqueFileId() {
3791
- return toUniqueFileId(getPlatform(), tdFileId.FileType.Document, {
3792
- _: "common",
3793
- id: this.raw.id
3794
- });
3507
+ get codec() {
3508
+ return this.attr._ === "documentAttributeVideo" ? this.attr.videoCodec ?? null : null;
3795
3509
  }
3796
3510
  }
3797
- class Document extends RawDocument {
3798
- type = "document";
3799
- }
3800
- const Document$1 = /* @__PURE__ */ memoizeGetters(Document, ["fileName", "thumbnails", "fileId", "uniqueFileId"]);
3801
- const Document$2 = /* @__PURE__ */ makeInspectable(Document$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3802
- class Audio extends RawDocument {
3511
+ const Video$1 = /* @__PURE__ */ memoizeGetters(Video, ["fileName", "thumbnails", "fileId", "uniqueFileId", "isAnimation"]);
3512
+ const Video$2 = /* @__PURE__ */ makeInspectable(Video$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3513
+ class Voice extends RawDocument {
3803
3514
  constructor(doc, attr) {
3804
3515
  super(doc);
3805
3516
  this.attr = attr;
3806
3517
  }
3807
- /** Type of the media (for use in a tagged union) */
3808
- type = "audio";
3809
- /** Type of the file for File ID generation */
3518
+ type = "voice";
3810
3519
  _fileIdType() {
3811
- return tdFileId.FileType.Audio;
3520
+ return tdFileId.FileType.VoiceNote;
3812
3521
  }
3813
3522
  /**
3814
- * Duration of the audio in seconds.
3815
- *
3816
- * May not be accurate since provided by the sender.
3523
+ * Duration of the voice note in seconds.
3817
3524
  */
3818
3525
  get duration() {
3819
3526
  return this.attr.duration;
3820
3527
  }
3821
3528
  /**
3822
- * Performer of the audio track.
3529
+ * Voice note's waveform
3530
+ *
3531
+ * Represented with integers in range [0, 31],
3532
+ * usually has length of 100
3823
3533
  */
3824
- get performer() {
3825
- return this.attr.performer ?? null;
3534
+ get waveform() {
3535
+ return decodeWaveform(this.attr.waveform);
3536
+ }
3537
+ }
3538
+ const Voice$1 = /* @__PURE__ */ memoizeGetters(Voice, ["fileName", "thumbnails", "fileId", "uniqueFileId", "waveform"]);
3539
+ const Voice$2 = /* @__PURE__ */ makeInspectable(Voice$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument", "waveform"]);
3540
+ function parseSticker(doc) {
3541
+ const stickerAttr = doc.attributes.find(
3542
+ (a) => a._ === "documentAttributeSticker" || a._ === "documentAttributeCustomEmoji"
3543
+ );
3544
+ if (stickerAttr) {
3545
+ const sz = doc.attributes.find(
3546
+ (it) => it._ === "documentAttributeImageSize" || it._ === "documentAttributeVideo"
3547
+ );
3548
+ return new Sticker$2(doc, stickerAttr, sz);
3549
+ }
3550
+ }
3551
+ function parseDocument(doc, media2) {
3552
+ const sticker2 = parseSticker(doc);
3553
+ if (sticker2) return sticker2;
3554
+ for (const attr of doc.attributes) {
3555
+ switch (attr._) {
3556
+ case "documentAttributeAudio":
3557
+ if (attr.voice) {
3558
+ return new Voice$2(doc, attr);
3559
+ }
3560
+ return new Audio$2(doc, attr);
3561
+ case "documentAttributeVideo":
3562
+ return new Video$2(doc, attr, media2);
3563
+ case "documentAttributeImageSize":
3564
+ if (doc.mimeType === "image/gif") {
3565
+ return new Video$2(doc, attr, media2);
3566
+ }
3567
+ }
3568
+ }
3569
+ return new Document$2(doc);
3570
+ }
3571
+ class StarGift {
3572
+ constructor(raw) {
3573
+ this.raw = raw;
3574
+ }
3575
+ /** ID of the gift */
3576
+ get id() {
3577
+ return this.raw.id;
3578
+ }
3579
+ /** Sticker associated with the gift */
3580
+ get sticker() {
3581
+ assertTypeIs("StarGift#sticker", this.raw.sticker, "document");
3582
+ const parsed = parseDocument(this.raw.sticker);
3583
+ if (parsed.type !== "sticker") {
3584
+ throw new MtTypeAssertionError("StarGift#sticker", "sticker", parsed.type);
3585
+ }
3586
+ return parsed;
3587
+ }
3588
+ /** Amount of stars the gift was purchased for */
3589
+ get purchaseStars() {
3590
+ return this.raw.stars;
3826
3591
  }
3827
3592
  /**
3828
- * Title of the audio track.
3593
+ * Amount of stars the gift can be converted to by the recipient
3829
3594
  */
3830
- get title() {
3831
- return this.attr.title ?? null;
3595
+ get convertStars() {
3596
+ return this.raw.convertStars;
3597
+ }
3598
+ /**
3599
+ * For limited availability gifts,
3600
+ * the number of remaining and total gifts available
3601
+ */
3602
+ get availability() {
3603
+ if (!this.raw.availabilityRemains || !this.raw.availabilityTotal) {
3604
+ return null;
3605
+ }
3606
+ return {
3607
+ remains: this.raw.availabilityRemains,
3608
+ total: this.raw.availabilityTotal
3609
+ };
3610
+ }
3611
+ }
3612
+ const StarGift$1 = /* @__PURE__ */ makeInspectable(StarGift);
3613
+ const StarGift$2 = /* @__PURE__ */ memoizeGetters(StarGift$1, ["sticker"]);
3614
+ class UserStarGift {
3615
+ constructor(raw, peers) {
3616
+ this.raw = raw;
3617
+ this.peers = peers;
3618
+ }
3619
+ /** Whether the sender chose to appear anonymously */
3620
+ get nameHidden() {
3621
+ return this.raw.nameHidden;
3622
+ }
3623
+ /** Whether this gift is not visible on the recipient's profile */
3624
+ get hidden() {
3625
+ return this.raw.unsaved;
3626
+ }
3627
+ /** Sender of the gift, if available */
3628
+ get sender() {
3629
+ return this.raw.fromId ? new User$2(this.peers.user(this.raw.fromId)) : null;
3630
+ }
3631
+ /** Message ID where the gift was sent, if available */
3632
+ get messageId() {
3633
+ return this.raw.msgId ?? null;
3634
+ }
3635
+ /** Date the gift was sent */
3636
+ get date() {
3637
+ return new Date(this.raw.date * 1e3);
3638
+ }
3639
+ /** The gift itself */
3640
+ get gift() {
3641
+ return new StarGift(this.raw.gift);
3642
+ }
3643
+ /** Text attached to the gift */
3644
+ get text() {
3645
+ return this.raw.message ?? null;
3646
+ }
3647
+ /**
3648
+ * If the gift was converted to stars, the amount of stars
3649
+ * it was converted to
3650
+ */
3651
+ get convertStars() {
3652
+ return this.raw.convertStars ?? null;
3653
+ }
3654
+ }
3655
+ const UserStarGift$1 = /* @__PURE__ */ makeInspectable(UserStarGift);
3656
+ const UserStarGift$2 = /* @__PURE__ */ memoizeGetters(UserStarGift$1, ["sender", "gift"]);
3657
+ function _messageActionFromTl(act) {
3658
+ switch (act._) {
3659
+ case "messageActionChatCreate":
3660
+ return {
3661
+ type: "chat_created",
3662
+ title: act.title,
3663
+ users: act.users
3664
+ };
3665
+ case "messageActionChannelCreate":
3666
+ return {
3667
+ type: "channel_created",
3668
+ title: act.title
3669
+ };
3670
+ case "messageActionChatMigrateTo":
3671
+ return {
3672
+ type: "chat_migrate_to",
3673
+ id: act.channelId
3674
+ };
3675
+ case "messageActionChannelMigrateFrom":
3676
+ return {
3677
+ type: "channel_migrate_from",
3678
+ id: act.chatId,
3679
+ title: act.title
3680
+ };
3681
+ case "messageActionPinMessage":
3682
+ return {
3683
+ type: "message_pinned"
3684
+ };
3685
+ case "messageActionHistoryClear":
3686
+ return {
3687
+ type: "history_cleared"
3688
+ };
3689
+ case "messageActionGameScore":
3690
+ return {
3691
+ type: "game_score",
3692
+ gameId: act.gameId,
3693
+ score: act.score
3694
+ };
3695
+ case "messageActionContactSignUp":
3696
+ return {
3697
+ type: "contact_joined"
3698
+ };
3699
+ case "messageActionChatEditTitle":
3700
+ return {
3701
+ type: "title_changed",
3702
+ title: act.title
3703
+ };
3704
+ case "messageActionChatEditPhoto":
3705
+ return {
3706
+ type: "photo_changed",
3707
+ photo: new Photo$2(act.photo)
3708
+ };
3709
+ case "messageActionChatDeletePhoto":
3710
+ return {
3711
+ type: "photo_deleted"
3712
+ };
3713
+ case "messageActionChatAddUser":
3714
+ return {
3715
+ type: "users_added",
3716
+ users: act.users
3717
+ };
3718
+ case "messageActionChatDeleteUser":
3719
+ if (this.raw.fromId?._ === "peerUser" && act.userId === this.raw.fromId.userId) {
3720
+ return {
3721
+ type: "user_left"
3722
+ };
3723
+ }
3724
+ return {
3725
+ type: "user_removed",
3726
+ user: act.userId
3727
+ };
3728
+ case "messageActionChatJoinedByLink":
3729
+ return {
3730
+ type: "user_joined_link",
3731
+ inviter: act.inviterId
3732
+ };
3733
+ case "messageActionPaymentSentMe":
3734
+ return {
3735
+ type: "payment_received",
3736
+ currency: act.currency,
3737
+ amount: act.totalAmount,
3738
+ payload: act.payload,
3739
+ info: act.info,
3740
+ shippingOptionId: act.shippingOptionId,
3741
+ charge: act.charge
3742
+ };
3743
+ case "messageActionPaymentSent":
3744
+ return {
3745
+ type: "payment_sent",
3746
+ currency: act.currency,
3747
+ amount: act.totalAmount
3748
+ };
3749
+ case "messageActionPhoneCall":
3750
+ return {
3751
+ type: "call",
3752
+ id: act.callId,
3753
+ isVideo: Boolean(act.video),
3754
+ reason: act.reason ? _callDiscardReasonFromTl(act.reason) : void 0,
3755
+ duration: act.duration ?? 0
3756
+ };
3757
+ case "messageActionScreenshotTaken":
3758
+ return {
3759
+ type: "screenshot_taken"
3760
+ };
3761
+ case "messageActionBotAllowed":
3762
+ return {
3763
+ type: "bot_allowed",
3764
+ domain: act.domain
3765
+ };
3766
+ case "messageActionGeoProximityReached":
3767
+ if (act.fromId._ !== "peerUser" || act.toId._ !== "peerUser") {
3768
+ return null;
3769
+ }
3770
+ return {
3771
+ type: "geo_proximity",
3772
+ targetId: act.toId.userId,
3773
+ userId: act.fromId.userId,
3774
+ distance: act.distance
3775
+ };
3776
+ case "messageActionGroupCall":
3777
+ if (act.duration) {
3778
+ return {
3779
+ type: "group_call_ended",
3780
+ call: act.call,
3781
+ duration: act.duration
3782
+ };
3783
+ }
3784
+ return {
3785
+ type: "group_call_started",
3786
+ call: act.call
3787
+ };
3788
+ case "messageActionGroupCallScheduled":
3789
+ return {
3790
+ type: "group_call_scheduled",
3791
+ call: act.call,
3792
+ date: new Date(act.scheduleDate * 1e3)
3793
+ };
3794
+ case "messageActionInviteToGroupCall":
3795
+ return {
3796
+ type: "group_call_invite",
3797
+ call: act.call,
3798
+ userIds: act.users
3799
+ };
3800
+ case "messageActionSetMessagesTTL":
3801
+ return {
3802
+ type: "ttl_changed",
3803
+ period: act.period
3804
+ };
3805
+ case "messageActionTopicCreate":
3806
+ return {
3807
+ type: "topic_created",
3808
+ title: act.title,
3809
+ iconColor: act.iconColor,
3810
+ iconCustomEmoji: act.iconEmojiId
3811
+ };
3812
+ case "messageActionTopicEdit":
3813
+ return {
3814
+ type: "topic_edited",
3815
+ title: act.title,
3816
+ iconCustomEmoji: act.iconEmojiId,
3817
+ closed: act.closed,
3818
+ hidden: act.hidden
3819
+ };
3820
+ case "messageActionCustomAction":
3821
+ return {
3822
+ type: "custom",
3823
+ action: act.message
3824
+ };
3825
+ case "messageActionSetChatTheme":
3826
+ return {
3827
+ type: "theme_changed",
3828
+ emoji: act.emoticon
3829
+ };
3830
+ case "messageActionChatJoinedByRequest":
3831
+ return {
3832
+ type: "user_joined_approved"
3833
+ };
3834
+ case "messageActionWebViewDataSent":
3835
+ return {
3836
+ type: "webview_sent",
3837
+ text: act.text
3838
+ };
3839
+ case "messageActionWebViewDataSentMe":
3840
+ return {
3841
+ type: "webview_received",
3842
+ text: act.text,
3843
+ data: act.data
3844
+ };
3845
+ case "messageActionGiftPremium":
3846
+ return {
3847
+ type: "premium_gifted",
3848
+ currency: act.currency,
3849
+ amount: act.amount.toNumber(),
3850
+ months: act.months,
3851
+ crypto: act.cryptoAmount ? {
3852
+ currency: act.cryptoCurrency,
3853
+ amount: act.cryptoAmount.toNumber()
3854
+ } : void 0
3855
+ };
3856
+ case "messageActionSuggestProfilePhoto":
3857
+ return {
3858
+ type: "photo_suggested",
3859
+ photo: new Photo$2(act.photo)
3860
+ };
3861
+ case "messageActionRequestedPeerSentMe":
3862
+ return {
3863
+ type: "peer_sent",
3864
+ buttonId: act.buttonId,
3865
+ peers: act.peers
3866
+ };
3867
+ case "messageActionRequestedPeer":
3868
+ return {
3869
+ type: "peer_chosen",
3870
+ buttonId: act.buttonId,
3871
+ peers: act.peers.map((it) => parsePeer(it, this._peers))
3872
+ };
3873
+ case "messageActionSetChatWallPaper":
3874
+ return {
3875
+ type: "wallpaper_changed",
3876
+ same: act.same,
3877
+ forBoth: act.forBoth,
3878
+ wallpaper: act.wallpaper
3879
+ };
3880
+ case "messageActionGiftCode":
3881
+ return {
3882
+ type: "gift_code",
3883
+ raw: act
3884
+ };
3885
+ case "messageActionGiveawayLaunch":
3886
+ return {
3887
+ type: "giveaway_started"
3888
+ };
3889
+ case "messageActionGiveawayResults":
3890
+ return {
3891
+ type: "giveaway_ended",
3892
+ winners: act.winnersCount,
3893
+ undistributed: act.unclaimedCount
3894
+ };
3895
+ case "messageActionBoostApply":
3896
+ return {
3897
+ type: "boost_apply",
3898
+ count: act.boosts
3899
+ };
3900
+ case "messageActionPaymentRefunded":
3901
+ return {
3902
+ type: "payment_refunded",
3903
+ currency: act.currency,
3904
+ peerId: getMarkedPeerId(act.peer),
3905
+ amount: act.totalAmount,
3906
+ payload: act.payload,
3907
+ charge: act.charge
3908
+ };
3909
+ case "messageActionGiftStars":
3910
+ return {
3911
+ type: "stars_gifted",
3912
+ isCrypto: Boolean(act.cryptoCurrency),
3913
+ currency: act.cryptoCurrency ?? act.currency,
3914
+ amount: act.cryptoAmount ?? act.amount,
3915
+ stars: act.stars,
3916
+ transactionId: act.transactionId
3917
+ };
3918
+ case "messageActionPrizeStars":
3919
+ return {
3920
+ type: "stars_prize",
3921
+ claimed: !act.unclaimed,
3922
+ stars: act.stars,
3923
+ transactionId: act.transactionId,
3924
+ boostPeer: parsePeer(act.boostPeer, this._peers),
3925
+ giveawayMessageId: act.giveawayMsgId
3926
+ };
3927
+ case "messageActionStarGift":
3928
+ return {
3929
+ type: "stars_gift",
3930
+ nameHidden: act.nameHidden,
3931
+ saved: act.saved,
3932
+ converted: act.converted,
3933
+ convertStars: act.convertStars,
3934
+ gift: new StarGift$2(act.gift),
3935
+ message: act.message ?? null
3936
+ };
3937
+ default:
3938
+ return null;
3832
3939
  }
3833
3940
  }
3834
- const Audio$1 = /* @__PURE__ */ memoizeGetters(Audio, ["fileName", "thumbnails", "fileId", "uniqueFileId"]);
3835
- const Audio$2 = /* @__PURE__ */ makeInspectable(Audio$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3836
- const MASK_POSITION_POINT_TO_TL = {
3837
- forehead: 0,
3838
- eyes: 1,
3839
- mouth: 2,
3840
- chin: 3
3841
- };
3842
- const MASK_POS = ["forehead", "eyes", "mouth", "chin"];
3843
- class Sticker extends RawDocument {
3844
- constructor(doc, attr, attr2) {
3845
- super(doc);
3846
- this.attr = attr;
3847
- this.attr2 = attr2;
3848
- }
3849
- type = "sticker";
3850
- _fileIdType() {
3851
- return tdFileId.FileType.Sticker;
3852
- }
3853
- /**
3854
- * Sticker width in pixels
3855
- */
3856
- get width() {
3857
- return this.attr2?.w ?? 512;
3941
+ class MessageForwardInfo {
3942
+ constructor(raw, _peers) {
3943
+ this.raw = raw;
3944
+ this._peers = _peers;
3858
3945
  }
3859
3946
  /**
3860
- * Sticker height in pixels
3947
+ * Date the original message was sent
3861
3948
  */
3862
- get height() {
3863
- return this.attr2?.h ?? 512;
3949
+ get date() {
3950
+ return new Date(this.raw.date * 1e3);
3864
3951
  }
3865
3952
  /**
3866
- * Whether this sticker is a premium sticker
3867
- * (has premium fullscreen animation)
3953
+ * Sender of the original message (either user or a channel)
3954
+ * or their name (for users with private forwards)
3868
3955
  */
3869
- get isPremiumSticker() {
3870
- return Boolean(this.raw.videoThumbs?.some((s) => s._ === "videoSize" && s.type === "f"));
3956
+ get sender() {
3957
+ if (this.raw.fromName) {
3958
+ return {
3959
+ type: "anonymous",
3960
+ displayName: this.raw.fromName
3961
+ };
3962
+ }
3963
+ if (this.raw.fromId) {
3964
+ return parsePeer(this.raw.fromId, this._peers);
3965
+ }
3966
+ throw new MtTypeAssertionError("MessageForwardInfo", "to have fromId or fromName", "neither");
3871
3967
  }
3872
3968
  /**
3873
- * Whether this sticker is a valid sticker.
3874
- *
3875
- * If it is not, then this is probably a WEBP photo
3876
- * that Telegram treats as a sticker.
3969
+ * For "saved" messages (i.e. messages forwarded to yourself,
3970
+ * "Saved Messages"), the peer where the message was originally sent
3877
3971
  */
3878
- get isValidSticker() {
3879
- return this.attr2 !== void 0 && (this.attr2.w === 512 || this.attr2.h === 512);
3972
+ fromChat() {
3973
+ if (!this.raw.savedFromPeer) return null;
3974
+ return Chat$2._parseFromPeer(this.raw.savedFromPeer, this._peers);
3880
3975
  }
3881
3976
  /**
3882
- * Primary emoji associated with this sticker,
3883
- * that is displayed in dialogs list.
3884
- *
3885
- * If there is none, empty string is returned.
3886
- *
3887
- * **Note:** This only contains at most one emoji.
3888
- * Some stickers have multiple associated emojis,
3889
- * but only one is returned here. This is Telegram's
3890
- * limitation! Use {@link getAllEmojis} instead.
3891
- *
3892
- * For custom emojis, this alt should be used as a fallback
3893
- * text that will be "behind" the custom emoji entity.
3977
+ * For messages forwarded from channels,
3978
+ * identifier of the original message in the channel
3894
3979
  */
3895
- get emoji() {
3896
- return this.attr.alt;
3980
+ get fromMessageId() {
3981
+ return this.raw.savedFromMsgId ?? null;
3897
3982
  }
3898
3983
  /**
3899
- * Whether this custom emoji can be used by non-premium users.
3900
- * `false` if this is not a custom emoji.
3901
- *
3902
- * > Not sure if there are any such stickers currently.
3984
+ * For messages forwarded from channels,
3985
+ * signature of the post author (if present)
3903
3986
  */
3904
- get customEmojiFree() {
3905
- return this.attr._ === "documentAttributeCustomEmoji" ? this.attr.free ?? false : false;
3987
+ get signature() {
3988
+ return this.raw.postAuthor ?? null;
3906
3989
  }
3907
- /**
3908
- * If this is a custom emoji, its unique ID
3909
- * that can be used in {@link TelegramClient#getCustomEmojis}
3910
- */
3911
- get customEmojiId() {
3912
- if (this.attr._ !== "documentAttributeCustomEmoji") {
3913
- throw new MtArgumentError("This is not a custom emoji");
3914
- }
3915
- return this.raw.id;
3990
+ }
3991
+ const MessageForwardInfo$1 = /* @__PURE__ */ memoizeGetters(MessageForwardInfo, ["sender", "fromChat"]);
3992
+ const MessageForwardInfo$2 = /* @__PURE__ */ makeInspectable(MessageForwardInfo$1);
3993
+ class Contact {
3994
+ constructor(obj) {
3995
+ this.obj = obj;
3916
3996
  }
3997
+ type = "contact";
3917
3998
  /**
3918
- * Type of the sticker
3999
+ * Contact's phone number
3919
4000
  */
3920
- get stickerType() {
3921
- if (this.attr._ === "documentAttributeSticker") {
3922
- return this.attr.mask ? "mask" : "sticker";
3923
- } else if (this.attr._ === "documentAttributeCustomEmoji") {
3924
- return "emoji";
3925
- }
3926
- return "sticker";
4001
+ get phoneNumber() {
4002
+ return this.obj.phoneNumber;
3927
4003
  }
3928
4004
  /**
3929
- * Type of the file representing the sticker
4005
+ * Contact's first name
3930
4006
  */
3931
- get sourceType() {
3932
- if (this.attr2?._ === "documentAttributeVideo") {
3933
- return "video";
3934
- }
3935
- return this.mimeType === "application/x-tgsticker" ? "animated" : "static";
4007
+ get firstName() {
4008
+ return this.obj.firstName;
3936
4009
  }
3937
4010
  /**
3938
- * Whether this sticker has an associated public sticker set.
4011
+ * Contact's last name
3939
4012
  */
3940
- get hasStickerSet() {
3941
- return this.attr.stickerset._ === "inputStickerSetID";
4013
+ get lastName() {
4014
+ return this.obj.lastName;
3942
4015
  }
3943
4016
  /**
3944
- * Input sticker set that it associated with this sticker, if available.
4017
+ * Contact's user ID in Telegram or `0` if not available
3945
4018
  */
3946
- get inputStickerSet() {
3947
- return this.attr.stickerset._ === "inputStickerSetEmpty" ? null : this.attr.stickerset;
4019
+ get userId() {
4020
+ return this.obj.userId;
3948
4021
  }
3949
4022
  /**
3950
- * Position where this mask should be placed
4023
+ * Input media TL object generated from this object,
4024
+ * to be used inside {@link InputMediaLike} and
4025
+ * {@link TelegramClient.sendMedia}
3951
4026
  */
3952
- get maskPosition() {
3953
- if (this.attr._ !== "documentAttributeSticker" || !this.attr.maskCoords) {
3954
- return null;
3955
- }
3956
- const raw = this.attr.maskCoords;
4027
+ get inputMedia() {
3957
4028
  return {
3958
- point: MASK_POS[raw.n],
3959
- x: raw.x,
3960
- y: raw.y,
3961
- scale: raw.zoom
4029
+ ...this.obj,
4030
+ _: "inputMediaContact"
3962
4031
  };
3963
4032
  }
3964
4033
  }
3965
- const Sticker$1 = /* @__PURE__ */ memoizeGetters(Sticker, ["fileName", "thumbnails", "fileId", "uniqueFileId", "maskPosition"]);
3966
- const Sticker$2 = /* @__PURE__ */ makeInspectable(Sticker$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
3967
- class Video extends RawDocument {
3968
- constructor(doc, attr, media2) {
3969
- super(doc);
3970
- this.attr = attr;
3971
- this.media = media2;
3972
- }
3973
- type = "video";
3974
- _fileIdType() {
3975
- if (this.isRound) return tdFileId.FileType.VideoNote;
3976
- if (this.isAnimation) return tdFileId.FileType.Animation;
3977
- return tdFileId.FileType.Video;
4034
+ const Contact$1 = /* @__PURE__ */ makeInspectable(Contact, void 0, ["inputMedia"]);
4035
+ class Dice {
4036
+ constructor(obj) {
4037
+ this.obj = obj;
3978
4038
  }
4039
+ type = "dice";
3979
4040
  /**
3980
- * Video width in pixels
4041
+ * A simple 6-sided dice.
4042
+ *
4043
+ * {@link value} represents its value (1-6)
3981
4044
  */
3982
- get width() {
3983
- return this.attr.w;
3984
- }
4045
+ static TYPE_DICE = "🎲";
3985
4046
  /**
3986
- * Video height in pixels
4047
+ * A dart. Telegram dart has 4 rings and middle.
4048
+ *
4049
+ * {@link value} represents the position of the dart:
4050
+ * ![Dart position graph](https://i.imgur.com/iPBm7HG.png)
3987
4051
  */
3988
- get height() {
3989
- return this.attr.h;
3990
- }
4052
+ static TYPE_DART = "🎯";
3991
4053
  /**
3992
- * Video duration in seconds.
4054
+ * A basketball thrown into a hoop.
3993
4055
  *
3994
- * `0` for legacy GIFs
4056
+ * {@link value} represents the motion of the ball:
4057
+ * - 1: simple miss (ball hits right part, bounces to the left)
4058
+ * - 2: first hit the ring, then miss
4059
+ * - 3: ball gets stuck between the ring and the base
4060
+ * - 4: first hit the ring, then score
4061
+ * - 5: direct score
3995
4062
  */
3996
- get duration() {
3997
- return this.attr._ === "documentAttributeVideo" ? this.attr.duration : 0;
3998
- }
4063
+ static TYPE_BASKETBALL = "🏀";
3999
4064
  /**
4000
- * Whether this video is an animated GIF
4001
- * (represented either by actual GIF or a silent MP4 video)
4065
+ * A football thrown to the gate.
4066
+ *
4067
+ * {@link value} represents the motion of the ball:
4068
+ * - 1: flies above the top barbell
4069
+ * - 2: hits right barbell, then miss
4070
+ * - 3: direct score in the middle
4071
+ * - 4: hits left barbell, then score, then hits right barbell
4072
+ * - 5: score in the top-right corner
4002
4073
  */
4003
- get isAnimation() {
4004
- return this.attr._ === "documentAttributeImageSize" || this.raw.attributes.some((it) => it._ === "documentAttributeAnimated");
4005
- }
4074
+ static TYPE_FOOTBALL = "⚽️";
4006
4075
  /**
4007
- * Whether this video is a round video message (aka video note)
4076
+ * A bowling ball thrown to pins.
4077
+ *
4078
+ * Assuming the following identifiers for the pins:
4079
+ * ```
4080
+ * 4 5 6
4081
+ * 2 3
4082
+ * 1
4083
+ * ```
4084
+ *
4085
+ * {@link value} represents the motion of the ball and pins:
4086
+ * - 1: the ball touched 6th pin, none are down
4087
+ * - 2: the ball hit 4th pin, only 4th pin is down.
4088
+ * - 3: the ball hit 1st pin, pins 1, 2, 5 are down, leaving pins 3, 4, 6
4089
+ * - 4: the ball hit 1st pin on the right side, all the pins except 2nd and 6th are down
4090
+ * - 5: the ball hit 3rd pin and all the pins except 2nd are down.
4091
+ * - 6: the ball hit 1st pin and all pins are down
4008
4092
  */
4009
- get isRound() {
4010
- return this.attr._ === "documentAttributeVideo" && Boolean(this.attr.roundMessage);
4011
- }
4093
+ static TYPE_BOWLING = "🎳";
4012
4094
  /**
4013
- * Whether this video is a legacy GIF (i.e. its MIME is `image/gif`)
4095
+ * A slot machine.
4096
+ *
4097
+ * {@link value} represents the result of the machine.
4098
+ * Value itself is an integer in range `[1, 64]`,
4099
+ * and is composed out of several parts.
4100
+ *
4101
+ * > **Note**: The following information is based on the TDesktop
4102
+ * > implementation. These are the relevant files:
4103
+ * > - [`chat_helpers/stickers_dice_pack.cpp`](https://github.com/telegramdesktop/tdesktop/blob/dev/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp)
4104
+ * > - [`history/view/media/history_view_slot_machine.cpp`](https://github.com/telegramdesktop/tdesktop/blob/dev/Telegram/SourceFiles/history/view/media/history_view_slot_machine.cpp)
4105
+ *
4106
+ * Unlike other animated dices, this does not have
4107
+ * all the possible combinations in the sticker set.
4108
+ * Instead, `value` is a specially encoded integer that contains
4109
+ * the information about the indexes.
4110
+ *
4111
+ * There are some base parts of the animations:
4112
+ * - 0th sticker is the base background of the machine
4113
+ * - 1st sticker is the background of the machine for the "winning" state (i.e. `777`)
4114
+ * - 2nd sticker is the frame of the machine, including the handle
4115
+ * - 8th sticker is the "idle" state for the left slot
4116
+ * - 14th sticker is the "idle" state for the middle slot
4117
+ * - 20th sticker is the "idle" state for the right slot
4118
+ *
4119
+ * The machine result is encoded as 3 concatenated two-bit integers,
4120
+ * and the resulting integer is incremented by one.
4121
+ *
4122
+ * So, to decode the value to its parts, you can use this code:
4123
+ * ```typescript
4124
+ * const computePartValue = (val: number, idx: number) => ((val - 1) >> (idx * 2)) & 0x03; // 0..3
4125
+ * const parts = [
4126
+ * computePartValue(msg.media.value, 0),
4127
+ * computePartValue(msg.media.value, 1),
4128
+ * computePartValue(msg.media.value, 2),
4129
+ * ]
4130
+ * ```
4131
+ *
4132
+ * Each part of the value corresponds to a particular slot (i.e. part 0 is left slot,
4133
+ * part 1 is middle, part 2 is right). The slot values are as follows:
4134
+ * - 0: BAR (displayed as a *BAR* sign on a black background)
4135
+ * - 1: BERRIES (displayed as berries, similar to emoji 🍇)
4136
+ * - 2: LEMON (displayed as a lemon, similar to emoji 🍋)
4137
+ * - 3: SEVEN (displayed as a red digit 7)
4138
+ *
4139
+ * Therefore, the winning value (i.e. `777`) is represented as `(3 << 4 | 3 << 2 | 3 << 0) + 1 = 64`
4140
+ *
4141
+ * To determine the needed animation parts, you'll need to apply some shifts.
4142
+ * These are the offsets for the individual symbols:
4143
+ * - WIN_SEVEN: 0
4144
+ * - SEVEN: 1
4145
+ * - BAR: 2
4146
+ * - BERRIES: 3
4147
+ * - LEMON: 4
4148
+ *
4149
+ * And these are the shifts for each slot:
4150
+ * - LEFT: 3
4151
+ * - MIDDLE: 9
4152
+ * - RIGHT: 15
4153
+ *
4154
+ * > WIN_SEVEN is the same as SEVEN, but only used if the machine result is `777` (i.e. `value = 64`),
4155
+ * > as it contains additional "blinking" animation.
4156
+ *
4157
+ * The sticker index is computed as follows: `SHIFTS[SLOT] + OFFSETS[SYM]`.
4158
+ * For example, berries for the middle slot would be: `SHIFTS[MIDDLE] + OFFSETS[BERRIES] = 9 + 3 = 12`
4159
+ *
4160
+ * Currently, this sticker set is used for the machine: [SlotMachineAnimated](https://t.me/addstickers/SlotMachineAnimated)
4014
4161
  */
4015
- get isLegacyGif() {
4016
- return this.attr._ === "documentAttributeImageSize";
4017
- }
4018
- /** Whether this video is hidden with a spoiler */
4019
- get hasSpoiler() {
4020
- return this.media?.spoiler ?? false;
4021
- }
4022
- /** For self-destructing videos, TTL in seconds */
4023
- get ttlSeconds() {
4024
- return this.media?.ttlSeconds ?? null;
4025
- }
4026
- get videoStartTs() {
4027
- return this.attr._ === "documentAttributeVideo" ? this.attr.videoStartTs ?? null : null;
4028
- }
4029
- }
4030
- const Video$1 = /* @__PURE__ */ memoizeGetters(Video, ["fileName", "thumbnails", "fileId", "uniqueFileId", "isAnimation"]);
4031
- const Video$2 = /* @__PURE__ */ makeInspectable(Video$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument"]);
4032
- class Voice extends RawDocument {
4033
- constructor(doc, attr) {
4034
- super(doc);
4035
- this.attr = attr;
4036
- }
4037
- type = "voice";
4038
- _fileIdType() {
4039
- return tdFileId.FileType.VoiceNote;
4040
- }
4162
+ static TYPE_SLOTS = "🎰";
4041
4163
  /**
4042
- * Duration of the voice note in seconds.
4164
+ * An emoji which was originally sent.
4165
+ *
4166
+ * See static members of {@link Dice} for a list
4167
+ * of possible values
4043
4168
  */
4044
- get duration() {
4045
- return this.attr.duration;
4169
+ get emoji() {
4170
+ return this.obj.emoticon;
4046
4171
  }
4047
4172
  /**
4048
- * Voice note's waveform
4173
+ * Emoji's interactive value.
4049
4174
  *
4050
- * Represented with integers in range [0, 31],
4051
- * usually has length of 100
4175
+ * See what this value represents in the corresponding
4176
+ * type's documentation (in {@link Dice} static fields)
4052
4177
  */
4053
- get waveform() {
4054
- return decodeWaveform(this.attr.waveform);
4055
- }
4056
- }
4057
- const Voice$1 = /* @__PURE__ */ memoizeGetters(Voice, ["fileName", "thumbnails", "fileId", "uniqueFileId", "waveform"]);
4058
- const Voice$2 = /* @__PURE__ */ makeInspectable(Voice$1, ["fileSize", "dcId"], ["inputMedia", "inputDocument", "waveform"]);
4059
- function parseSticker(doc) {
4060
- const stickerAttr = doc.attributes.find(
4061
- (a) => a._ === "documentAttributeSticker" || a._ === "documentAttributeCustomEmoji"
4062
- );
4063
- if (stickerAttr) {
4064
- const sz = doc.attributes.find(
4065
- (it) => it._ === "documentAttributeImageSize" || it._ === "documentAttributeVideo"
4066
- );
4067
- return new Sticker$2(doc, stickerAttr, sz);
4178
+ get value() {
4179
+ return this.obj.value;
4068
4180
  }
4069
- }
4070
- function parseDocument(doc, media2) {
4071
- const sticker2 = parseSticker(doc);
4072
- if (sticker2) return sticker2;
4073
- for (const attr of doc.attributes) {
4074
- switch (attr._) {
4075
- case "documentAttributeAudio":
4076
- if (attr.voice) {
4077
- return new Voice$2(doc, attr);
4078
- }
4079
- return new Audio$2(doc, attr);
4080
- case "documentAttributeVideo":
4081
- return new Video$2(doc, attr, media2);
4082
- case "documentAttributeImageSize":
4083
- if (doc.mimeType === "image/gif") {
4084
- return new Video$2(doc, attr, media2);
4085
- }
4086
- }
4181
+ /**
4182
+ * Input media TL object generated from this object,
4183
+ * to be used inside {@link InputMediaLike} and
4184
+ * {@link TelegramClient.sendMedia}
4185
+ *
4186
+ * Note that when you use this media, a new `value`
4187
+ * will be generated!
4188
+ */
4189
+ get inputMedia() {
4190
+ return {
4191
+ _: "inputMediaDice",
4192
+ emoticon: this.obj.emoticon
4193
+ };
4087
4194
  }
4088
- return new Document$2(doc);
4089
4195
  }
4196
+ const Dice$1 = /* @__PURE__ */ makeInspectable(Dice, void 0, ["inputMedia"]);
4090
4197
  class Game {
4091
4198
  constructor(game2) {
4092
4199
  this.game = game2;
@@ -6654,6 +6761,7 @@ async function uploadFile(client, params) {
6654
6761
  if (HAS_FILE && file2 instanceof File) {
6655
6762
  fileName = file2.name;
6656
6763
  fileSize = file2.size;
6764
+ fileMime = file2.type;
6657
6765
  file2 = file2.stream();
6658
6766
  }
6659
6767
  if (HAS_URL && file2 instanceof URL) {
@@ -6783,6 +6891,18 @@ async function uploadFile(client, params) {
6783
6891
  if (fileName === void 0) {
6784
6892
  const ext = MIME_TO_EXTENSION[fileMime];
6785
6893
  fileName = ext ? `${DEFAULT_FILE_NAME}.${ext}` : DEFAULT_FILE_NAME;
6894
+ } else if (params.requireExtension) {
6895
+ const extFromMime = MIME_TO_EXTENSION[fileMime];
6896
+ const idx2 = fileName.lastIndexOf(".");
6897
+ const extFromName = idx2 === -1 ? void 0 : fileName.slice(idx2 + 1);
6898
+ if (!extFromName) {
6899
+ if (!extFromMime) {
6900
+ throw new MtArgumentError(`File name does not have an extension, and we cannot guess it from the mime type (${fileMime})`);
6901
+ }
6902
+ fileName = `${fileName}.${extFromMime}`;
6903
+ } else if (extFromMime && extFromName !== extFromMime) {
6904
+ throw new MtArgumentError(`File name has ${extFromName} extension (${fileName}), but the mime type (${fileMime}) expects it to be ${extFromMime}`);
6905
+ }
6786
6906
  }
6787
6907
  let inputFile;
6788
6908
  if (isBig) {
@@ -7022,7 +7142,8 @@ async function _normalizeInputMedia(client, media2, params = {}, uploadMedia = f
7022
7142
  fileName: media2.fileName,
7023
7143
  fileMime: sendMime,
7024
7144
  fileSize: media2.fileSize,
7025
- requireFileSize: media2.type === "photo"
7145
+ requireFileSize: media2.type === "photo",
7146
+ requireExtension: media2.type === "photo"
7026
7147
  });
7027
7148
  inputFile = uploaded.inputFile;
7028
7149
  mime = uploaded.mime;
@@ -8227,18 +8348,6 @@ class StickerSet {
8227
8348
  }
8228
8349
  return "sticker";
8229
8350
  }
8230
- /**
8231
- * Source file type of the stickers in this set
8232
- */
8233
- get sourceType() {
8234
- if (this.brief.animated) {
8235
- return "animated";
8236
- }
8237
- if (this.brief.videos) {
8238
- return "video";
8239
- }
8240
- return "static";
8241
- }
8242
8351
  /**
8243
8352
  * Date when this sticker set was installed
8244
8353
  */
@@ -9776,6 +9885,13 @@ class StarsTransaction {
9776
9885
  messageId: this.raw.giveawayPostId
9777
9886
  };
9778
9887
  }
9888
+ if (this.raw.stargift) {
9889
+ return {
9890
+ type: "star_gift",
9891
+ peer,
9892
+ gift: new StarGift$2(this.raw.stargift)
9893
+ };
9894
+ }
9779
9895
  if (this.raw.msgId) {
9780
9896
  if (this.raw.reaction) {
9781
9897
  return {
@@ -10095,6 +10211,7 @@ export {
10095
10211
  RepliedMessageInfo$2,
10096
10212
  SearchFilters,
10097
10213
  SentCode$1,
10214
+ StarGift$2,
10098
10215
  StarsStatus$2,
10099
10216
  StarsTransaction$2,
10100
10217
  Sticker$2,
@@ -10114,6 +10231,7 @@ export {
10114
10231
  TakeoutSession$1,
10115
10232
  Thumbnail$2,
10116
10233
  User$2,
10234
+ UserStarGift$2,
10117
10235
  Venue$2,
10118
10236
  Video$2,
10119
10237
  Voice$2,