From fdaaeb901acc8b80fb6618efd71b05a7994c67b1 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Wed, 22 Jan 2025 23:28:58 +0100
Subject: [PATCH 01/68] API Layer 198: stargifts stuff, video cover, ...
---
README.md | 2 +-
src/TL.Schema.cs | 343 +++++++++++++++++++++++++------------
src/TL.SchemaFuncs.cs | 197 ++++++++++++++-------
src/TL.Table.cs | 43 +++--
src/WTelegramClient.csproj | 2 +-
5 files changed, 397 insertions(+), 190 deletions(-)
diff --git a/README.md b/README.md
index 929be15..2279602 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 8b721da..749dd20 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -229,7 +229,7 @@ namespace TL
public string vcard;
}
/// New document See
- [TLDef(0x5B38C6C1)]
+ [TLDef(0x037C9330)]
public sealed partial class InputMediaUploadedDocument : InputMedia
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -244,6 +244,8 @@ namespace TL
public DocumentAttribute[] attributes;
/// Attached stickers
[IfFlag(0)] public InputDocument[] stickers;
+ [IfFlag(6)] public InputPhoto video_cover;
+ [IfFlag(7)] public int video_timestamp;
/// Time to live in seconds of self-destructing document
[IfFlag(1)] public int ttl_seconds;
@@ -261,16 +263,22 @@ namespace TL
force_file = 0x10,
/// Whether this media should be hidden behind a spoiler warning
spoiler = 0x20,
+ /// Field has a value
+ has_video_cover = 0x40,
+ /// Field has a value
+ has_video_timestamp = 0x80,
}
}
/// Forwarded document See
- [TLDef(0x33473058)]
+ [TLDef(0xA8763AB5)]
public sealed partial class InputMediaDocument : InputMedia
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// The document to be forwarded.
public InputDocument id;
+ [IfFlag(3)] public InputPhoto video_cover;
+ [IfFlag(4)] public int video_timestamp;
/// Time to live of self-destructing document
[IfFlag(0)] public int ttl_seconds;
/// Text query or emoji that was used by the user to find this sticker or GIF: used to improve search result relevance.
@@ -284,6 +292,10 @@ namespace TL
has_query = 0x2,
/// Whether this media should be hidden behind a spoiler warning
spoiler = 0x4,
+ /// Field has a value
+ has_video_cover = 0x8,
+ /// Field has a value
+ has_video_timestamp = 0x10,
}
}
/// Can be used to send a venue geolocation. See
@@ -323,7 +335,7 @@ namespace TL
}
}
/// Document that will be downloaded by the telegram servers See
- [TLDef(0xFB52DC99)]
+ [TLDef(0x779600F9)]
public sealed partial class InputMediaDocumentExternal : InputMedia
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -332,6 +344,8 @@ namespace TL
public string url;
/// Self-destruct time to live of document
[IfFlag(0)] public int ttl_seconds;
+ [IfFlag(2)] public InputPhoto video_cover;
+ [IfFlag(3)] public int video_timestamp;
[Flags] public enum Flags : uint
{
@@ -339,6 +353,10 @@ namespace TL
has_ttl_seconds = 0x1,
/// Whether this media should be hidden behind a spoiler warning
spoiler = 0x2,
+ /// Field has a value
+ has_video_cover = 0x4,
+ /// Field has a value
+ has_video_timestamp = 0x8,
}
}
/// A game See
@@ -782,7 +800,7 @@ namespace TL
/// Language code of the user
[IfFlag(22)] public string lang_code;
/// Emoji status
- [IfFlag(30)] public EmojiStatus emoji_status;
+ [IfFlag(30)] public EmojiStatusBase emoji_status;
/// Additional usernames.
When updating the local peer database, apply changes to this field only if:
- The min flag is not set OR
- The min flag is set AND
-- The min flag of the locally cached user entry is set.
Changes to this flag (if the above conditions are respected) should invalidate the local cache for this user ID.
[IfFlag(32)] public Username[] usernames;
/// ID of the maximum read story.
When updating the local peer database, do not apply changes to this field if the min flag of the incoming constructor is set.
@@ -1091,7 +1109,7 @@ namespace TL
/// The channel's profile color.
[IfFlag(40)] public PeerColor profile_color;
/// Emoji status
- [IfFlag(41)] public EmojiStatus emoji_status;
+ [IfFlag(41)] public EmojiStatusBase emoji_status;
/// Boost level.
Changes to this flag should invalidate the local cache for this channel/supergroup ID, see here » for more info.
[IfFlag(42)] public int level;
/// Expiration date of the Telegram Star subscription » the current user has bought to gain access to this channel.
@@ -1363,7 +1381,7 @@ namespace TL
public override int ReactionsLimit => reactions_limit;
}
/// Full info about a channel, supergroup or gigagroup. See
- [TLDef(0x9FF3B858)]
+ [TLDef(0x52D6806B)]
public sealed partial class ChannelFull : ChatFullBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1453,6 +1471,7 @@ namespace TL
/// Custom emoji stickerset associated to the current supergroup, set using Channels_SetEmojiStickers after reaching the appropriate boost level, see here » for more info.
[IfFlag(42)] public StickerSet emojiset;
[IfFlag(49)] public BotVerification bot_verification;
+ [IfFlag(50)] public int stargifts_count;
[Flags] public enum Flags : uint
{
@@ -1558,6 +1577,9 @@ namespace TL
paid_reactions_available = 0x10000,
/// Field has a value
has_bot_verification = 0x20000,
+ /// Field has a value
+ has_stargifts_count = 0x40000,
+ stargifts_available = 0x80000,
}
/// ID of the channel
@@ -2001,7 +2023,7 @@ namespace TL
[TLDef(0x9F84F49E)]
public sealed partial class MessageMediaUnsupported : MessageMedia { }
/// Document (video, audio, voice, sticker, any media type except photo) See
- [TLDef(0xDD570BD5)]
+ [TLDef(0x52D8CCD9)]
public sealed partial class MessageMediaDocument : MessageMedia
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -2010,6 +2032,8 @@ namespace TL
[IfFlag(0)] public DocumentBase document;
/// Videos only, contains alternative qualities of the video.
[IfFlag(5)] public DocumentBase[] alt_documents;
+ [IfFlag(9)] public PhotoBase video_cover;
+ [IfFlag(10)] public int video_timestamp;
/// Time to live of self-destructing document
[IfFlag(2)] public int ttl_seconds;
@@ -2031,6 +2055,10 @@ namespace TL
round = 0x80,
/// Whether this is a voice message.
voice = 0x100,
+ /// Field has a value
+ has_video_cover = 0x200,
+ /// Field has a value
+ has_video_timestamp = 0x400,
}
}
/// Preview of webpage See
@@ -2842,7 +2870,7 @@ namespace TL
}
}
/// You received a gift, see here » for more info. See
- [TLDef(0xD8F4F0A7)]
+ [TLDef(0x4717E8A4)]
public sealed partial class MessageActionStarGift : MessageAction
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -2855,6 +2883,9 @@ namespace TL
[IfFlag(4)] public long convert_stars;
[IfFlag(5)] public int upgrade_msg_id;
[IfFlag(8)] public long upgrade_stars;
+ [IfFlag(11)] public Peer from_id;
+ [IfFlag(12)] public Peer peer;
+ [IfFlag(12)] public long saved_id;
[Flags] public enum Flags : uint
{
@@ -2873,16 +2904,23 @@ namespace TL
has_upgrade_stars = 0x100,
refunded = 0x200,
can_upgrade = 0x400,
+ /// Field has a value
+ has_from_id = 0x800,
+ /// Fields and have a value
+ has_peer = 0x1000,
}
}
/// See
- [TLDef(0x26077B99)]
+ [TLDef(0xACDFCB81)]
public sealed partial class MessageActionStarGiftUnique : MessageAction
{
public Flags flags;
public StarGiftBase gift;
[IfFlag(3)] public int can_export_at;
[IfFlag(4)] public long transfer_stars;
+ [IfFlag(6)] public Peer from_id;
+ [IfFlag(7)] public Peer peer;
+ [IfFlag(7)] public long saved_id;
[Flags] public enum Flags : uint
{
@@ -2892,6 +2930,8 @@ namespace TL
has_can_export_at = 0x8,
has_transfer_stars = 0x10,
refunded = 0x20,
+ has_from_id = 0x40,
+ has_peer = 0x80,
}
}
@@ -5288,7 +5328,7 @@ namespace TL
public sealed partial class UpdateUserEmojiStatus : UpdateUser
{
/// New emoji status
- public EmojiStatus emoji_status;
+ public EmojiStatusBase emoji_status;
}
/// The list of recent emoji statuses has changed See
[TLDef(0x30F443DB)]
@@ -12010,9 +12050,9 @@ namespace TL
public sealed partial class ChannelAdminLogEventActionChangeEmojiStatus : ChannelAdminLogEventAction
{
/// Previous emoji status
- public EmojiStatus prev_value;
+ public EmojiStatusBase prev_value;
/// New emoji status
- public EmojiStatus new_value;
+ public EmojiStatusBase new_value;
}
/// The supergroup's custom emoji stickerset was changed. See
[TLDef(0x46D840AB)]
@@ -13952,6 +13992,12 @@ namespace TL
text_color = 0x2,
}
}
+ /// See
+ [TLDef(0xCF6F6DB8)]
+ public sealed partial class WebPageAttributeUniqueStarGift : WebPageAttribute
+ {
+ public StarGiftBase gift;
+ }
/// How users voted in a poll See
[TLDef(0x4899484E)]
@@ -14423,7 +14469,7 @@ namespace TL
keep_archived_folders = 0x4,
/// If this flag is set, the key will also apply to the ability to use Messages_GetOutboxReadDate on messages sent to us.
Meaning, users that cannot see our exact last online date due to the current value of the key will receive a 403 USER_PRIVACY_RESTRICTED error when invoking Messages_GetOutboxReadDate to fetch the exact read date of a message they sent to us.
The .read_dates_private flag will be set for users that have this flag enabled.
hide_read_marks = 0x8,
- /// If set, only users that have a premium account, are in our contact list, or already have a private chat with us can write to us; a 403 PRIVACY_PREMIUM_REQUIRED error will be emitted otherwise.
The .contact_require_premium flag will be set for users that have this flag enabled.
To check whether we can write to a user with this flag enabled, if we haven't yet cached all the required information (for example we don't have the or history of all users while displaying the chat list in the sharing UI) the Users_GetIsPremiumRequiredToContact method may be invoked, passing the list of users currently visible in the UI, returning a list of booleans that directly specify whether we can or cannot write to each user.
Premium users only, non-Premium users will receive a PREMIUM_ACCOUNT_REQUIRED error when trying to enable this flag.
+ /// If set, only users that have a premium account, are in our contact list, or already have a private chat with us can write to us; a 403 PRIVACY_PREMIUM_REQUIRED error will be emitted otherwise.
The .contact_require_premium flag will be set for users that have this flag enabled.
To check whether we can write to a user with this flag enabled, if we haven't yet cached all the required information (for example we don't have the or history of all users while displaying the chat list in the sharing UI) the Users_GetIsPremiumRequiredToContact method may be invoked, passing the list of users currently visible in the UI, returning a list of booleans that directly specify whether we can or cannot write to each user.
This option may be enabled by both non-Premium and Premium users only if the new_noncontact_peers_require_premium_without_ownpremium client configuration flag » is equal to true, otherwise it may be enabled only by Premium users and non-Premium users will receive a PREMIUM_ACCOUNT_REQUIRED error when trying to enable this flag.
new_noncontact_peers_require_premium = 0x10,
}
}
@@ -15779,13 +15825,12 @@ namespace TL
public string hash;
}
/// Used to buy a Telegram Star Gift, see here » for more info. See
- [TLDef(0x25D8C1D8)]
+ [TLDef(0xE8625E92)]
public sealed partial class InputInvoiceStarGift : InputInvoice
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
- /// Identifier of the user that will receive the gift
- public InputUserBase user_id;
+ public InputPeer peer;
/// Identifier of the gift, from .id
public long gift_id;
/// Optional message, attached with the gift.
The maximum length for this field is specified in the stargifts_message_length_max client configuration value ».
@@ -15801,11 +15846,11 @@ namespace TL
}
}
/// See
- [TLDef(0x5EBE7262)]
+ [TLDef(0x4D818D5D)]
public sealed partial class InputInvoiceStarGiftUpgrade : InputInvoice
{
public Flags flags;
- public int msg_id;
+ public InputSavedStarGift stargift;
[Flags] public enum Flags : uint
{
@@ -15813,11 +15858,11 @@ namespace TL
}
}
/// See
- [TLDef(0xAE3BA9ED)]
+ [TLDef(0x4A5F5BD9)]
public sealed partial class InputInvoiceStarGiftTransfer : InputInvoice
{
- public int msg_id;
- public InputUserBase to_id;
+ public InputSavedStarGift stargift;
+ public InputPeer to_id;
}
/// Exported invoice deep link See
@@ -16060,20 +16105,66 @@ namespace TL
public string title;
}
- /// An emoji status See
+ /// Emoji status See Derived classes: ,
/// a value means emojiStatusEmpty
- [TLDef(0x929B619D)]
- public partial class EmojiStatus : IObject
+ public abstract partial class EmojiStatusBase : IObject
{
+ public virtual DateTime Until => default;
+ }
+ /// An emoji status See
+ [TLDef(0xE7FF068A)]
+ public sealed partial class EmojiStatus : EmojiStatusBase
+ {
+ public Flags flags;
/// Custom emoji document ID
public long document_id;
+ [IfFlag(0)] public DateTime until;
+
+ [Flags] public enum Flags : uint
+ {
+ /// Field has a value
+ has_until = 0x1,
+ }
+
+ public override DateTime Until => until;
}
- /// An emoji status valid until the specified date See
- [TLDef(0xFA30A8C7, inheritBefore = true)]
- public sealed partial class EmojiStatusUntil : EmojiStatus
+ /// See
+ [TLDef(0x7184603B)]
+ public sealed partial class EmojiStatusCollectible : EmojiStatusBase
{
- /// This status is valid until this date
- public DateTime until;
+ public Flags flags;
+ public long collectible_id;
+ public long document_id;
+ public string title;
+ public string slug;
+ public long pattern_document_id;
+ public int center_color;
+ public int edge_color;
+ public int pattern_color;
+ public int text_color;
+ [IfFlag(0)] public DateTime until;
+
+ [Flags] public enum Flags : uint
+ {
+ has_until = 0x1,
+ }
+
+ public override DateTime Until => until;
+ }
+ /// See
+ [TLDef(0x07141DBF)]
+ public sealed partial class InputEmojiStatusCollectible : EmojiStatusBase
+ {
+ public Flags flags;
+ public long collectible_id;
+ [IfFlag(0)] public DateTime until;
+
+ [Flags] public enum Flags : uint
+ {
+ has_until = 0x1,
+ }
+
+ public override DateTime Until => until;
}
/// A list of emoji statuses See
@@ -16084,7 +16175,7 @@ namespace TL
/// Hash used for caching, for more info click here
public long hash;
/// Emoji statuses
- public EmojiStatus[] statuses;
+ public EmojiStatusBase[] statuses;
}
/// Message reaction See Derived classes: , ,
@@ -17473,6 +17564,13 @@ namespace TL
/// ARGB background color.
public int color;
}
+ /// See
+ [TLDef(0x5787686D)]
+ public sealed partial class MediaAreaStarGift : MediaArea
+ {
+ public MediaAreaCoordinates coordinates;
+ public string slug;
+ }
/// Stories associated to a peer See
[TLDef(0x9A35E999)]
@@ -19744,17 +19842,28 @@ namespace TL
public override int AvailabilityTotal => availability_total;
}
/// See
- [TLDef(0x6A1407CD)]
+ [TLDef(0xF2FE7E4A)]
public sealed partial class StarGiftUnique : StarGiftBase
{
+ public Flags flags;
public long id;
public string title;
+ public string slug;
public int num;
- public long owner_id;
+ [IfFlag(0)] public Peer owner_id;
+ [IfFlag(1)] public string owner_name;
+ [IfFlag(2)] public string owner_address;
public StarGiftAttribute[] attributes;
public int availability_issued;
public int availability_total;
+ [Flags] public enum Flags : uint
+ {
+ has_owner_id = 0x1,
+ has_owner_name = 0x2,
+ has_owner_address = 0x4,
+ }
+
public override long ID => id;
public override int AvailabilityTotal => availability_total;
}
@@ -19770,75 +19879,6 @@ namespace TL
public StarGiftBase[] gifts;
}
- /// Represents a gift, displayed on a user's profile page. See
- [TLDef(0x325835E1)]
- public sealed partial class UserStarGift : IObject
- {
- /// Extra bits of information, use flags.HasFlag(...) to test for those
- public Flags flags;
- /// Sender of the gift (may be empty for anonymous senders; will always be set if this gift was sent to us).
- [IfFlag(1)] public long from_id;
- /// When was this gift sent.
- public DateTime date;
- /// The gift.
- public StarGiftBase gift;
- /// Message attached to the gift by the sender.
- [IfFlag(2)] public TextWithEntities message;
- /// Only visible to the receiver of the gift, contains the ID of the with the in the chat with from_id.
- [IfFlag(3)] public int msg_id;
- /// The receiver of this gift may convert it to this many Telegram Stars, instead of displaying it on their profile page.
convert_stars will be equal to the buying price of the gift only if the gift was bought using recently bought Telegram Stars, otherwise it will be less than stars.
- [IfFlag(4)] public long convert_stars;
- [IfFlag(6)] public long upgrade_stars;
- [IfFlag(7)] public int can_export_at;
- [IfFlag(8)] public long transfer_stars;
-
- [Flags] public enum Flags : uint
- {
- /// If set, from_id will not be visible to users (it will still be visible to the receiver of the gift).
- name_hidden = 0x1,
- /// Field has a value
- has_from_id = 0x2,
- /// Field has a value
- has_message = 0x4,
- /// Field has a value
- has_msg_id = 0x8,
- /// Field has a value
- has_convert_stars = 0x10,
- /// If set, indicates this is a gift sent by from_id, received by the current user and currently hidden from our profile page.
- unsaved = 0x20,
- /// Field has a value
- has_upgrade_stars = 0x40,
- /// Field has a value
- has_can_export_at = 0x80,
- /// Field has a value
- has_transfer_stars = 0x100,
- refunded = 0x200,
- can_upgrade = 0x400,
- }
- }
-
- /// Gifts displayed on a user's profile. See
- [TLDef(0x6B65B517)]
- public sealed partial class Payments_UserStarGifts : IObject
- {
- /// Extra bits of information, use flags.HasFlag(...) to test for those
- public Flags flags;
- /// Total number of gifts displayed on the profile.
- public int count;
- /// The gifts.
- public UserStarGift[] gifts;
- /// Offset for pagination.
- [IfFlag(0)] public string next_offset;
- /// Users mentioned in the gifts vector.
- public Dictionary users;
-
- [Flags] public enum Flags : uint
- {
- /// Field has a value
- has_next_offset = 0x1,
- }
- }
-
/// Report menu option See
[TLDef(0x7903E3D9)]
public sealed partial class MessageReportOption : IObject
@@ -19951,7 +19991,7 @@ namespace TL
[IfFlag(0)] public int duration_months;
/// Point in time (Unix timestamp) when the affiliate program will be closed (optional, if not set the affiliate program isn't scheduled to be closed)
[IfFlag(1)] public DateTime end_date;
- /// The amount of daily revenue per user in Telegram Stars of the bot that created the affiliate program
+ /// The amount of daily revenue per user in Telegram Stars of the bot that created the affiliate program.
To obtain the approximated revenue per referred user, multiply this value by commission_permille and divide by 1000.
[IfFlag(2)] public StarsAmount daily_revenue_per_user;
[Flags] public enum Flags : uint
@@ -20131,12 +20171,12 @@ namespace TL
public int rarity_permille;
}
/// See
- [TLDef(0xC02C4F4B)]
+ [TLDef(0xE0BFF26C)]
public sealed partial class StarGiftAttributeOriginalDetails : StarGiftAttribute
{
public Flags flags;
- [IfFlag(0)] public long sender_id;
- public long recipient_id;
+ [IfFlag(0)] public Peer sender_id;
+ public Peer recipient_id;
public DateTime date;
[IfFlag(1)] public TextWithEntities message;
@@ -20166,4 +20206,97 @@ namespace TL
{
public int count;
}
+
+ /// See
+ [TLDef(0xCAA2F60B)]
+ public sealed partial class Payments_UniqueStarGift : IObject
+ {
+ public StarGiftBase gift;
+ public Dictionary users;
+ }
+
+ /// See
+ [TLDef(0xB53E8B21)]
+ public sealed partial class Messages_WebPagePreview : IObject
+ {
+ public MessageMedia media;
+ public Dictionary users;
+ }
+
+ /// See
+ [TLDef(0x6056DBA5)]
+ public sealed partial class SavedStarGift : IObject
+ {
+ public Flags flags;
+ [IfFlag(1)] public Peer from_id;
+ public DateTime date;
+ public StarGiftBase gift;
+ [IfFlag(2)] public TextWithEntities message;
+ [IfFlag(3)] public int msg_id;
+ [IfFlag(11)] public long saved_id;
+ [IfFlag(4)] public long convert_stars;
+ [IfFlag(6)] public long upgrade_stars;
+ [IfFlag(7)] public int can_export_at;
+ [IfFlag(8)] public long transfer_stars;
+
+ [Flags] public enum Flags : uint
+ {
+ name_hidden = 0x1,
+ has_from_id = 0x2,
+ has_message = 0x4,
+ has_msg_id = 0x8,
+ has_convert_stars = 0x10,
+ unsaved = 0x20,
+ has_upgrade_stars = 0x40,
+ has_can_export_at = 0x80,
+ has_transfer_stars = 0x100,
+ refunded = 0x200,
+ can_upgrade = 0x400,
+ has_saved_id = 0x800,
+ }
+ }
+
+ /// See
+ [TLDef(0x95F389B1)]
+ public sealed partial class Payments_SavedStarGifts : IObject, IPeerResolver
+ {
+ public Flags flags;
+ public int count;
+ [IfFlag(1)] public bool chat_notifications_enabled;
+ public SavedStarGift[] gifts;
+ [IfFlag(0)] public string next_offset;
+ public Dictionary chats;
+ public Dictionary users;
+
+ [Flags] public enum Flags : uint
+ {
+ has_next_offset = 0x1,
+ has_chat_notifications_enabled = 0x2,
+ }
+ /// returns a or for the given Peer
+ public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
+ }
+
+ /// See
+ public abstract partial class InputSavedStarGift : IObject { }
+ /// See
+ [TLDef(0x69279795)]
+ public sealed partial class InputSavedStarGiftUser : InputSavedStarGift
+ {
+ public int msg_id;
+ }
+ /// See
+ [TLDef(0xF101AA7F)]
+ public sealed partial class InputSavedStarGiftChat : InputSavedStarGift
+ {
+ public InputPeer peer;
+ public long saved_id;
+ }
+
+ /// See
+ [TLDef(0x84AA3A9C)]
+ public sealed partial class Payments_StarGiftWithdrawalUrl : IObject
+ {
+ public string url;
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 1bad50b..5f025de 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1107,7 +1107,7 @@ namespace TL
/// Set an emoji status See Possible codes: 400 (details)
/// Emoji status to set
- public static Task Account_UpdateEmojiStatus(this Client client, EmojiStatus emoji_status)
+ public static Task Account_UpdateEmojiStatus(this Client client, EmojiStatusBase emoji_status)
=> client.Invoke(new Account_UpdateEmojiStatus
{
emoji_status = emoji_status,
@@ -1417,6 +1417,14 @@ namespace TL
settings = settings,
});
+ /// See
+ /// a null value means account.emojiStatusesNotModified
+ public static Task Account_GetCollectibleEmojiStatuses(this Client client, long hash = default)
+ => client.Invoke(new Account_GetCollectibleEmojiStatuses
+ {
+ hash = hash,
+ });
+
/// Returns basic user info according to their identifiers. See [bots: ✓] Possible codes: 400 (details)
/// List of user identifiers
public static Task Users_GetUsers(this Client client, params InputUserBase[] id)
@@ -1932,10 +1940,10 @@ namespace TL
/// Scheduled message date for scheduled messages
/// Forward the messages as the specified peer
/// Add the messages to the specified quick reply shortcut », instead.
- public static Task Messages_ForwardMessages(this Client client, InputPeer from_peer, int[] id, long[] random_id, InputPeer to_peer, int? top_msg_id = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, bool silent = false, bool background = false, bool with_my_score = false, bool drop_author = false, bool drop_media_captions = false, bool noforwards = false, bool allow_paid_floodskip = false)
+ public static Task Messages_ForwardMessages(this Client client, InputPeer from_peer, int[] id, long[] random_id, InputPeer to_peer, int? top_msg_id = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, int? video_timestamp = null, bool silent = false, bool background = false, bool with_my_score = false, bool drop_author = false, bool drop_media_captions = false, bool noforwards = false, bool allow_paid_floodskip = false)
=> client.Invoke(new Messages_ForwardMessages
{
- flags = (Messages_ForwardMessages.Flags)((top_msg_id != null ? 0x200 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (with_my_score ? 0x100 : 0) | (drop_author ? 0x800 : 0) | (drop_media_captions ? 0x1000 : 0) | (noforwards ? 0x4000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
+ flags = (Messages_ForwardMessages.Flags)((top_msg_id != null ? 0x200 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (video_timestamp != null ? 0x100000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (with_my_score ? 0x100 : 0) | (drop_author ? 0x800 : 0) | (drop_media_captions ? 0x1000 : 0) | (noforwards ? 0x4000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
from_peer = from_peer,
id = id,
random_id = random_id,
@@ -1944,6 +1952,7 @@ namespace TL
schedule_date = schedule_date ?? default,
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
+ video_timestamp = video_timestamp ?? default,
});
/// Report a new incoming chat for spam, if the of the chat allow us to do that See Possible codes: 400 (details)
@@ -2202,8 +2211,7 @@ namespace TL
/// Get preview of webpage See Possible codes: 400 (details)
/// Message from which to extract the preview
/// Message entities for styled text
- /// a null value means messageMediaEmpty
- public static Task Messages_GetWebPagePreview(this Client client, string message, MessageEntity[] entities = null)
+ public static Task Messages_GetWebPagePreview(this Client client, string message, MessageEntity[] entities = null)
=> client.Invoke(new Messages_GetWebPagePreview
{
flags = (Messages_GetWebPagePreview.Flags)(entities != null ? 0x8 : 0),
@@ -5488,7 +5496,7 @@ namespace TL
/// Set an emoji status for a channel or supergroup. See Possible codes: 400 (details)
/// The channel/supergroup, must have at least channel_emoji_status_level_min/group_emoji_status_level_min boosts.
/// Emoji status to set
- public static Task Channels_UpdateEmojiStatus(this Client client, InputChannelBase channel, EmojiStatus emoji_status)
+ public static Task Channels_UpdateEmojiStatus(this Client client, InputChannelBase channel, EmojiStatusBase emoji_status)
=> client.Invoke(new Channels_UpdateEmojiStatus
{
channel = channel,
@@ -5787,7 +5795,7 @@ namespace TL
/// Change the emoji status of a user (invoked by bots, see here » for more info on the full flow) See [bots: ✓] Possible codes: 400 (details)
/// The user whose emoji status should be changed
/// The emoji status
- public static Task Bots_UpdateUserEmojiStatus(this Client client, InputUserBase user_id, EmojiStatus emoji_status)
+ public static Task Bots_UpdateUserEmojiStatus(this Client client, InputUserBase user_id, EmojiStatusBase emoji_status)
=> client.Invoke(new Bots_UpdateUserEmojiStatus
{
user_id = user_id,
@@ -5849,7 +5857,6 @@ namespace TL
public static Task Bots_GetBotRecommendations(this Client client, InputUserBase bot)
=> client.Invoke(new Bots_GetBotRecommendations
{
- flags = 0,
bot = bot,
});
@@ -6162,34 +6169,20 @@ namespace TL
hash = hash,
});
- /// Get the gifts » pinned on a specific user's profile. See Possible codes: 400 (details)
- /// Identifier of the user (can be the current user to fetch all gifts received by the current user).
- /// Offset for pagination, taken from (initially empty).
- /// Maximum number of results to return, see pagination
- public static Task Payments_GetUserStarGifts(this Client client, InputUserBase user_id, string offset, int limit = int.MaxValue)
- => client.Invoke(new Payments_GetUserStarGifts
- {
- user_id = user_id,
- offset = offset,
- limit = limit,
- });
-
/// Display or remove a received gift » from our profile. See Possible codes: 400 (details)
/// If set, hides the gift from our profile.
- /// The ID of the with the .
- public static Task Payments_SaveStarGift(this Client client, int msg_id, bool unsave = false)
+ public static Task Payments_SaveStarGift(this Client client, InputSavedStarGift stargift, bool unsave = false)
=> client.Invoke(new Payments_SaveStarGift
{
flags = (Payments_SaveStarGift.Flags)(unsave ? 0x1 : 0),
- msg_id = msg_id,
+ stargift = stargift,
});
/// Convert a received gift » into Telegram Stars: this will permanently destroy the gift, converting it into .convert_stars Telegram Stars, added to the user's balance. See Possible codes: 400 (details)
- /// The ID of the with the .
- public static Task Payments_ConvertStarGift(this Client client, int msg_id)
+ public static Task Payments_ConvertStarGift(this Client client, InputSavedStarGift stargift)
=> client.Invoke(new Payments_ConvertStarGift
{
- msg_id = msg_id,
+ stargift = stargift,
});
/// Cancel a bot subscription See Possible codes: 400 (details)
@@ -6274,26 +6267,59 @@ namespace TL
});
/// See
- public static Task Payments_UpgradeStarGift(this Client client, int msg_id, bool keep_original_details = false)
+ public static Task Payments_UpgradeStarGift(this Client client, InputSavedStarGift stargift, bool keep_original_details = false)
=> client.Invoke(new Payments_UpgradeStarGift
{
flags = (Payments_UpgradeStarGift.Flags)(keep_original_details ? 0x1 : 0),
- msg_id = msg_id,
+ stargift = stargift,
});
/// See
- public static Task Payments_TransferStarGift(this Client client, int msg_id, InputUserBase to_id)
+ public static Task Payments_TransferStarGift(this Client client, InputSavedStarGift stargift, InputPeer to_id)
=> client.Invoke(new Payments_TransferStarGift
{
- msg_id = msg_id,
+ stargift = stargift,
to_id = to_id,
});
- /// See
- public static Task Payments_GetUserStarGift(this Client client, params int[] msg_id)
- => client.Invoke(new Payments_GetUserStarGift
+ /// See
+ public static Task Payments_GetUniqueStarGift(this Client client, string slug)
+ => client.Invoke(new Payments_GetUniqueStarGift
{
- msg_id = msg_id,
+ slug = slug,
+ });
+
+ /// See
+ public static Task Payments_GetSavedStarGifts(this Client client, InputPeer peer, string offset, int limit = int.MaxValue, bool exclude_unsaved = false, bool exclude_saved = false, bool exclude_unlimited = false, bool exclude_limited = false, bool exclude_unique = false, bool sort_by_value = false)
+ => client.Invoke(new Payments_GetSavedStarGifts
+ {
+ flags = (Payments_GetSavedStarGifts.Flags)((exclude_unsaved ? 0x1 : 0) | (exclude_saved ? 0x2 : 0) | (exclude_unlimited ? 0x4 : 0) | (exclude_limited ? 0x8 : 0) | (exclude_unique ? 0x10 : 0) | (sort_by_value ? 0x20 : 0)),
+ peer = peer,
+ offset = offset,
+ limit = limit,
+ });
+
+ /// See
+ public static Task Payments_GetSavedStarGift(this Client client, params InputSavedStarGift[] stargift)
+ => client.Invoke(new Payments_GetSavedStarGift
+ {
+ stargift = stargift,
+ });
+
+ /// See
+ public static Task Payments_GetStarGiftWithdrawalUrl(this Client client, InputSavedStarGift stargift, InputCheckPasswordSRP password)
+ => client.Invoke(new Payments_GetStarGiftWithdrawalUrl
+ {
+ stargift = stargift,
+ password = password,
+ });
+
+ /// See
+ public static Task Payments_ToggleChatStarGiftNotifications(this Client client, InputPeer peer, bool enabled = false)
+ => client.Invoke(new Payments_ToggleChatStarGiftNotifications
+ {
+ flags = (Payments_ToggleChatStarGiftNotifications.Flags)(enabled ? 0x1 : 0),
+ peer = peer,
});
/// Create a stickerset. See [bots: ✓] Possible codes: 400 (details)
@@ -8352,7 +8378,7 @@ namespace TL.Methods
[TLDef(0xFBD3DE6B)]
public sealed partial class Account_UpdateEmojiStatus : IMethod
{
- public EmojiStatus emoji_status;
+ public EmojiStatusBase emoji_status;
}
[TLDef(0xD6753386)]
@@ -8615,6 +8641,12 @@ namespace TL.Methods
public ReactionsNotifySettings settings;
}
+ [TLDef(0x2E7B4543)]
+ public sealed partial class Account_GetCollectibleEmojiStatuses : IMethod
+ {
+ public long hash;
+ }
+
[TLDef(0x0D91A548)]
public sealed partial class Users_GetUsers : IMethod
{
@@ -9050,7 +9082,7 @@ namespace TL.Methods
}
}
- [TLDef(0xD5039208)]
+ [TLDef(0x6D74DA08)]
public sealed partial class Messages_ForwardMessages : IMethod
{
public Flags flags;
@@ -9062,6 +9094,7 @@ namespace TL.Methods
[IfFlag(10)] public DateTime schedule_date;
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
+ [IfFlag(20)] public int video_timestamp;
[Flags] public enum Flags : uint
{
@@ -9076,6 +9109,7 @@ namespace TL.Methods
noforwards = 0x4000,
has_quick_reply_shortcut = 0x20000,
allow_paid_floodskip = 0x80000,
+ has_video_timestamp = 0x100000,
}
}
@@ -9278,8 +9312,8 @@ namespace TL.Methods
public long hash;
}
- [TLDef(0x8B68B0CC)]
- public sealed partial class Messages_GetWebPagePreview : IMethod
+ [TLDef(0x570D6F6F)]
+ public sealed partial class Messages_GetWebPagePreview : IMethod
{
public Flags flags;
public string message;
@@ -12012,7 +12046,7 @@ namespace TL.Methods
public sealed partial class Channels_UpdateEmojiStatus : IMethod
{
public InputChannelBase channel;
- public EmojiStatus emoji_status;
+ public EmojiStatusBase emoji_status;
}
[TLDef(0xAD399CEE)]
@@ -12231,7 +12265,7 @@ namespace TL.Methods
public sealed partial class Bots_UpdateUserEmojiStatus : IMethod
{
public InputUserBase user_id;
- public EmojiStatus emoji_status;
+ public EmojiStatusBase emoji_status;
}
[TLDef(0x06DE6392)]
@@ -12282,15 +12316,10 @@ namespace TL.Methods
}
}
- [TLDef(0x2855BE61)]
+ [TLDef(0xA1B70815)]
public sealed partial class Bots_GetBotRecommendations : IMethod
{
- public Flags flags;
public InputUserBase bot;
-
- [Flags] public enum Flags : uint
- {
- }
}
[TLDef(0x37148DBB)]
@@ -12560,19 +12589,11 @@ namespace TL.Methods
public int hash;
}
- [TLDef(0x5E72C7E1)]
- public sealed partial class Payments_GetUserStarGifts : IMethod
- {
- public InputUserBase user_id;
- public string offset;
- public int limit;
- }
-
- [TLDef(0x92FD2AAE)]
+ [TLDef(0x2A2A697C)]
public sealed partial class Payments_SaveStarGift : IMethod
{
public Flags flags;
- public int msg_id;
+ public InputSavedStarGift stargift;
[Flags] public enum Flags : uint
{
@@ -12580,10 +12601,10 @@ namespace TL.Methods
}
}
- [TLDef(0x72770C83)]
+ [TLDef(0x74BF076B)]
public sealed partial class Payments_ConvertStarGift : IMethod
{
- public int msg_id;
+ public InputSavedStarGift stargift;
}
[TLDef(0x6DFA0622)]
@@ -12662,11 +12683,11 @@ namespace TL.Methods
public long gift_id;
}
- [TLDef(0xCF4F0781)]
+ [TLDef(0xAED6E4F5)]
public sealed partial class Payments_UpgradeStarGift : IMethod
{
public Flags flags;
- public int msg_id;
+ public InputSavedStarGift stargift;
[Flags] public enum Flags : uint
{
@@ -12674,17 +12695,61 @@ namespace TL.Methods
}
}
- [TLDef(0x333FB526)]
+ [TLDef(0x7F18176A)]
public sealed partial class Payments_TransferStarGift : IMethod
{
- public int msg_id;
- public InputUserBase to_id;
+ public InputSavedStarGift stargift;
+ public InputPeer to_id;
}
- [TLDef(0xB502E4A5)]
- public sealed partial class Payments_GetUserStarGift : IMethod
+ [TLDef(0xA1974D72)]
+ public sealed partial class Payments_GetUniqueStarGift : IMethod
{
- public int[] msg_id;
+ public string slug;
+ }
+
+ [TLDef(0x23830DE9)]
+ public sealed partial class Payments_GetSavedStarGifts : IMethod
+ {
+ public Flags flags;
+ public InputPeer peer;
+ public string offset;
+ public int limit;
+
+ [Flags] public enum Flags : uint
+ {
+ exclude_unsaved = 0x1,
+ exclude_saved = 0x2,
+ exclude_unlimited = 0x4,
+ exclude_limited = 0x8,
+ exclude_unique = 0x10,
+ sort_by_value = 0x20,
+ }
+ }
+
+ [TLDef(0xB455A106)]
+ public sealed partial class Payments_GetSavedStarGift : IMethod
+ {
+ public InputSavedStarGift[] stargift;
+ }
+
+ [TLDef(0xD06E93A8)]
+ public sealed partial class Payments_GetStarGiftWithdrawalUrl : IMethod
+ {
+ public InputSavedStarGift stargift;
+ public InputCheckPasswordSRP password;
+ }
+
+ [TLDef(0x60EAEFA1)]
+ public sealed partial class Payments_ToggleChatStarGiftNotifications : IMethod
+ {
+ public Flags flags;
+ public InputPeer peer;
+
+ [Flags] public enum Flags : uint
+ {
+ enabled = 0x1,
+ }
}
[TLDef(0x9021AB67)]
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 9ff74e4..b3f254a 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 196; // fetched 02/01/2025 13:18:52
+ public const int Version = 198; // fetched 22/01/2025 22:22:20
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -90,11 +90,11 @@ namespace TL
[0xB3BA0635] = typeof(InputMediaPhoto),
[0xF9C44144] = typeof(InputMediaGeoPoint),
[0xF8AB7DFB] = typeof(InputMediaContact),
- [0x5B38C6C1] = typeof(InputMediaUploadedDocument),
- [0x33473058] = typeof(InputMediaDocument),
+ [0x037C9330] = typeof(InputMediaUploadedDocument),
+ [0xA8763AB5] = typeof(InputMediaDocument),
[0xC13D1C11] = typeof(InputMediaVenue),
[0xE5BBFE1A] = typeof(InputMediaPhotoExternal),
- [0xFB52DC99] = typeof(InputMediaDocumentExternal),
+ [0x779600F9] = typeof(InputMediaDocumentExternal),
[0xD33F43F3] = typeof(InputMediaGame),
[0x405FEF0D] = typeof(InputMediaInvoice),
[0x971FA843] = typeof(InputMediaGeoLive),
@@ -139,7 +139,7 @@ namespace TL
[0xE00998B7] = typeof(Channel),
[0x17D493D5] = typeof(ChannelForbidden),
[0x2633421B] = typeof(ChatFull),
- [0x9FF3B858] = typeof(ChannelFull),
+ [0x52D6806B] = typeof(ChannelFull),
[0xC02D4007] = typeof(ChatParticipant),
[0xE46BCEE4] = typeof(ChatParticipantCreator),
[0xA0933F5B] = typeof(ChatParticipantAdmin),
@@ -155,7 +155,7 @@ namespace TL
[0x56E0D474] = typeof(MessageMediaGeo),
[0x70322949] = typeof(MessageMediaContact),
[0x9F84F49E] = typeof(MessageMediaUnsupported),
- [0xDD570BD5] = typeof(MessageMediaDocument),
+ [0x52D8CCD9] = typeof(MessageMediaDocument),
[0xDDF10C3B] = typeof(MessageMediaWebPage),
[0x2EC0533F] = typeof(MessageMediaVenue),
[0xFDB19008] = typeof(MessageMediaGame),
@@ -213,8 +213,8 @@ namespace TL
[0x41B3E202] = typeof(MessageActionPaymentRefunded),
[0x45D5B021] = typeof(MessageActionGiftStars),
[0xB00C47A2] = typeof(MessageActionPrizeStars),
- [0xD8F4F0A7] = typeof(MessageActionStarGift),
- [0x26077B99] = typeof(MessageActionStarGiftUnique),
+ [0x4717E8A4] = typeof(MessageActionStarGift),
+ [0xACDFCB81] = typeof(MessageActionStarGiftUnique),
[0xD58A08C6] = typeof(Dialog),
[0x71BD134C] = typeof(DialogFolder),
[0x2331B22D] = typeof(PhotoEmpty),
@@ -989,6 +989,7 @@ namespace TL
[0x54B56617] = typeof(WebPageAttributeTheme),
[0x2E94C3E7] = typeof(WebPageAttributeStory),
[0x50CC03D3] = typeof(WebPageAttributeStickerSet),
+ [0xCF6F6DB8] = typeof(WebPageAttributeUniqueStarGift),
[0x4899484E] = typeof(Messages_VotesList),
[0xF568028A] = typeof(BankCardOpenUrl),
[0x3E24E573] = typeof(Payments_BankCardData),
@@ -1102,9 +1103,9 @@ namespace TL
[0x98986C0D] = typeof(InputInvoicePremiumGiftCode),
[0x65F00CE3] = typeof(InputInvoiceStars),
[0x34E793F1] = typeof(InputInvoiceChatInviteSubscription),
- [0x25D8C1D8] = typeof(InputInvoiceStarGift),
- [0x5EBE7262] = typeof(InputInvoiceStarGiftUpgrade),
- [0xAE3BA9ED] = typeof(InputInvoiceStarGiftTransfer),
+ [0xE8625E92] = typeof(InputInvoiceStarGift),
+ [0x4D818D5D] = typeof(InputInvoiceStarGiftUpgrade),
+ [0x4A5F5BD9] = typeof(InputInvoiceStarGiftTransfer),
[0xAED0CBD9] = typeof(Payments_ExportedInvoice),
[0xCFB9D957] = typeof(Messages_TranscribedAudio),
[0x5334759C] = typeof(Help_PremiumPromo),
@@ -1118,8 +1119,9 @@ namespace TL
[0x74C34319] = typeof(PremiumGiftOption),
[0x88F8F21B] = typeof(PaymentFormMethod),
[0x2DE11AAE] = null,//EmojiStatusEmpty
- [0x929B619D] = typeof(EmojiStatus),
- [0xFA30A8C7] = typeof(EmojiStatusUntil),
+ [0xE7FF068A] = typeof(EmojiStatus),
+ [0x7184603B] = typeof(EmojiStatusCollectible),
+ [0x07141DBF] = typeof(InputEmojiStatusCollectible),
[0xD08CE645] = null,//Account_EmojiStatusesNotModified
[0x90C467D1] = typeof(Account_EmojiStatuses),
[0x79F5D419] = null,//ReactionEmpty
@@ -1210,6 +1212,7 @@ namespace TL
[0x2271F2BF] = typeof(InputMediaAreaChannelPost),
[0x37381085] = typeof(MediaAreaUrl),
[0x49A6549C] = typeof(MediaAreaWeather),
+ [0x5787686D] = typeof(MediaAreaStarGift),
[0x9A35E999] = typeof(PeerStories),
[0xCAE68768] = typeof(Stories_PeerStories),
[0xFD5E12BD] = typeof(Messages_WebPage),
@@ -1341,11 +1344,9 @@ namespace TL
[0x94CE852A] = typeof(StarsGiveawayOption),
[0x54236209] = typeof(StarsGiveawayWinnersOption),
[0x02CC73C8] = typeof(StarGift),
- [0x6A1407CD] = typeof(StarGiftUnique),
+ [0xF2FE7E4A] = typeof(StarGiftUnique),
[0xA388A368] = null,//Payments_StarGiftsNotModified
[0x901689EA] = typeof(Payments_StarGifts),
- [0x325835E1] = typeof(UserStarGift),
- [0x6B65B517] = typeof(Payments_UserStarGifts),
[0x7903E3D9] = typeof(MessageReportOption),
[0xF0E4E0B6] = typeof(ReportResultChooseOption),
[0x6F09AC31] = typeof(ReportResultAddComment),
@@ -1365,10 +1366,17 @@ namespace TL
[0x39D99013] = typeof(StarGiftAttributeModel),
[0x13ACFF19] = typeof(StarGiftAttributePattern),
[0x94271762] = typeof(StarGiftAttributeBackdrop),
- [0xC02C4F4B] = typeof(StarGiftAttributeOriginalDetails),
+ [0xE0BFF26C] = typeof(StarGiftAttributeOriginalDetails),
[0x167BD90B] = typeof(Payments_StarGiftUpgradePreview),
[0x62D706B8] = typeof(Users_Users),
[0x315A4974] = typeof(Users_UsersSlice),
+ [0xCAA2F60B] = typeof(Payments_UniqueStarGift),
+ [0xB53E8B21] = typeof(Messages_WebPagePreview),
+ [0x6056DBA5] = typeof(SavedStarGift),
+ [0x95F389B1] = typeof(Payments_SavedStarGifts),
+ [0x69279795] = typeof(InputSavedStarGiftUser),
+ [0xF101AA7F] = typeof(InputSavedStarGiftChat),
+ [0x84AA3A9C] = typeof(Payments_StarGiftWithdrawalUrl),
// from TL.Secret:
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
[0x020DF5D0] = typeof(Layer101.MessageEntityBlockquote),
@@ -1488,6 +1496,7 @@ namespace TL
[typeof(ChatReactions)] = 0xEAFC32BC, //chatReactionsNone
[typeof(Messages_Reactions)] = 0xB06FDBDF, //messages.reactionsNotModified
// from TL.Secret:
+ [typeof(EmojiStatusBase)] = 0x2DE11AAE, //emojiStatusEmpty
[typeof(EmojiList)] = 0x481EADFA, //emojiListNotModified
[typeof(Messages_EmojiGroups)] = 0x6FB4AD87, //messages.emojiGroupsNotModified
[typeof(Help_AppConfig)] = 0x7CDE641D, //help.appConfigNotModified
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index ff8487a..819a3c0 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 196
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 198
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From e5953994a76748109c85e25db79021a891304fb2 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Fri, 24 Jan 2025 00:41:48 +0100
Subject: [PATCH 02/68] property Title on ForumTopicBase
---
.github/dev.yml | 2 +-
src/TL.Xtended.cs | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/dev.yml b/.github/dev.yml
index 97a9eb5..fefd177 100644
--- a/.github/dev.yml
+++ b/.github/dev.yml
@@ -1,7 +1,7 @@
pr: none
trigger: [ master ]
-name: 4.2.7-dev.$(Rev:r)
+name: 4.2.9-dev.$(Rev:r)
pool:
vmImage: ubuntu-latest
diff --git a/src/TL.Xtended.cs b/src/TL.Xtended.cs
index ef2701f..d06b07b 100644
--- a/src/TL.Xtended.cs
+++ b/src/TL.Xtended.cs
@@ -761,6 +761,9 @@ namespace TL
partial class MessageReplyHeader { public int TopicID => flags.HasFlag(Flags.forum_topic) ? flags.HasFlag(Flags.has_reply_to_top_id) ? reply_to_top_id : reply_to_msg_id : 0; }
partial class GroupCallBase { public static implicit operator InputGroupCall(GroupCallBase call) => new() { id = call.ID, access_hash = call.AccessHash }; }
+ partial class ForumTopicBase { public virtual string Title => null; }
+ partial class ForumTopic { public override string Title => title; }
+
partial class RequestedPeer { public abstract long ID { get; } }
partial class RequestedPeerUser { public override long ID => user_id; }
partial class RequestedPeerChat { public override long ID => chat_id; }
From e6dde325380b489f7d5f1e78eef07efbd888e42c Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Tue, 28 Jan 2025 13:46:06 +0100
Subject: [PATCH 03/68] Fix Messages_GetAllChats to include only your chats
---
README.md | 2 +-
src/Client.Helpers.cs | 6 +++++-
src/WTelegramClient.csproj | 2 +-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 2279602..d43c617 100644
--- a/README.md
+++ b/README.md
@@ -206,4 +206,4 @@ the [Examples codes](https://wiz0u.github.io/WTelegramClient/EXAMPLES) and still
If you like this library, you can [buy me a coffee](https://buymeacoffee.com/wizou) ❤ This will help the project keep going.
-© 2024 Olivier Marcoux
+© 2021-2025 Olivier Marcoux
diff --git a/src/Client.Helpers.cs b/src/Client.Helpers.cs
index 69d3b22..25124ea 100644
--- a/src/Client.Helpers.cs
+++ b/src/Client.Helpers.cs
@@ -504,7 +504,11 @@ namespace WTelegram
public async Task Messages_GetAllChats()
{
var dialogs = await Messages_GetAllDialogs();
- return new Messages_Chats { chats = dialogs.chats };
+ var result = new Messages_Chats { chats = [] };
+ foreach (var dialog in dialogs.dialogs)
+ if (dialog.Peer is (PeerChat or PeerChannel) and { ID: var id })
+ result.chats[id] = dialogs.chats[id];
+ return result;
}
/// Returns the current user dialog list. Possible codes: 400 (details)
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 819a3c0..5cd6031 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -17,7 +17,7 @@
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
- Copyright © Olivier Marcoux 2021-2024
+ Copyright © Olivier Marcoux 2021-2025
MIT
https://wiz0u.github.io/WTelegramClient
logo.png
From edc6019f2ea3dac74582dae1647b70ec7448e0b1 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 30 Jan 2025 02:22:05 +0100
Subject: [PATCH 04/68] Better support for HTML &entities; in HtmlText
---
src/Services.cs | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/Services.cs b/src/Services.cs
index 4ef4379..99ce13b 100644
--- a/src/Services.cs
+++ b/src/Services.cs
@@ -373,9 +373,10 @@ namespace TL
char c = sb[offset];
if (c == '&')
{
- for (end = offset + 1; end < sb.Length; end++)
- if (sb[end] == ';') break;
- if (end >= sb.Length) break;
+ end = offset + 1;
+ if (end < sb.Length && sb[end] == '#') end++;
+ while (end < sb.Length && sb[end] is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '0' and <= '9') end++;
+ if (end >= sb.Length || sb[end] != ';') break;
var html = HttpUtility.HtmlDecode(sb.ToString(offset, end - offset + 1));
if (html.Length == 1)
{
@@ -421,7 +422,7 @@ namespace TL
}
else if (tag.StartsWith("a href=\"") && tag[^1] == '"')
{
- tag = tag[8..^1];
+ tag = HttpUtility.HtmlDecode(tag[8..^1]);
if (tag.StartsWith("tg://user?id=") && long.TryParse(tag[13..], out var user_id) && users?.GetValueOrDefault(user_id)?.access_hash is long hash)
entities.Add(new InputMessageEntityMentionName { offset = offset, length = -1, user_id = new InputUser(user_id, hash) });
else
@@ -494,7 +495,7 @@ namespace TL
if (tag[0] == 'a')
{
if (nextEntity is MessageEntityTextUrl metu)
- tag = $"";
+ tag = $"";
else if (nextEntity is MessageEntityMentionName memn)
tag = $"";
else if (nextEntity is InputMessageEntityMentionName imemn)
From 1fab219ef6c5102e7ed7f1ecf9cc588145a33385 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Fri, 31 Jan 2025 20:39:42 +0100
Subject: [PATCH 05/68] Added EmojiStatusBase.DocumentId helper
---
src/TL.Xtended.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/TL.Xtended.cs b/src/TL.Xtended.cs
index d06b07b..7b36f1d 100644
--- a/src/TL.Xtended.cs
+++ b/src/TL.Xtended.cs
@@ -761,6 +761,10 @@ namespace TL
partial class MessageReplyHeader { public int TopicID => flags.HasFlag(Flags.forum_topic) ? flags.HasFlag(Flags.has_reply_to_top_id) ? reply_to_top_id : reply_to_msg_id : 0; }
partial class GroupCallBase { public static implicit operator InputGroupCall(GroupCallBase call) => new() { id = call.ID, access_hash = call.AccessHash }; }
+ partial class EmojiStatusBase { public virtual long DocumentId => 0; }
+ partial class EmojiStatus { public override long DocumentId => document_id; }
+ partial class EmojiStatusCollectible{ public override long DocumentId => document_id; }
+
partial class ForumTopicBase { public virtual string Title => null; }
partial class ForumTopic { public override string Title => title; }
From b626c6c644921b46d140987afd9192a10be36eaf Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 13 Feb 2025 14:12:04 +0100
Subject: [PATCH 06/68] API Layer 199: reCAPTCHA, PaidReactionPrivacy
---
.github/dev.yml | 2 +-
.github/release.yml | 2 +-
README.md | 2 +-
src/TL.Schema.cs | 28 ++++++++++++++++++-----
src/TL.SchemaFuncs.cs | 46 ++++++++++++++++++++++++++++----------
src/TL.Table.cs | 10 ++++++---
src/WTelegramClient.csproj | 2 +-
7 files changed, 67 insertions(+), 25 deletions(-)
diff --git a/.github/dev.yml b/.github/dev.yml
index fefd177..e8a3729 100644
--- a/.github/dev.yml
+++ b/.github/dev.yml
@@ -1,7 +1,7 @@
pr: none
trigger: [ master ]
-name: 4.2.9-dev.$(Rev:r)
+name: 4.3.1-dev.$(Rev:r)
pool:
vmImage: ubuntu-latest
diff --git a/.github/release.yml b/.github/release.yml
index de79b3b..e4ca17f 100644
--- a/.github/release.yml
+++ b/.github/release.yml
@@ -1,7 +1,7 @@
pr: none
trigger: none
-name: 4.2.$(Rev:r)
+name: 4.3.$(Rev:r)
pool:
vmImage: ubuntu-latest
diff --git a/README.md b/README.md
index d43c617..12f7892 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 749dd20..3d612af 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -257,7 +257,7 @@ namespace TL
has_ttl_seconds = 0x2,
/// Field has a value
has_thumb = 0x4,
- /// Whether the specified document is a video file with no audio tracks (a GIF animation (even as MPEG4), for example)
+ /// Whether to send the file as a video even if it doesn't have an audio track (i.e. if set, the attribute will not be set even for videos without audio)
nosound_video = 0x8,
/// Force the media file to be uploaded as document
force_file = 0x10,
@@ -5756,11 +5756,11 @@ namespace TL
public override (long, int, int) GetMBox() => (-1, qts, 1);
}
/// Contains the current default paid reaction privacy, see here » for more info. See
- [TLDef(0x51CA7AEC)]
+ [TLDef(0x8B725FCE)]
public sealed partial class UpdatePaidReactionPrivacy : Update
{
/// Whether paid reaction privacy is enabled or disabled.
- public bool private_;
+ public PaidReactionPrivacy private_;
}
/// Updates state. See
@@ -7118,7 +7118,7 @@ namespace TL
[IfFlag(2)] public int preload_prefix_size;
/// Floating point UNIX timestamp in seconds, indicating the frame of the video that should be used as static preview and thumbnail.
[IfFlag(4)] public double video_start_ts;
- /// Codec used for the video, i.e. "h264", "h265", or "av1"
+ /// Codec used for the video, i.e. “h264”, “h265”, or “av1”
[IfFlag(5)] public string video_codec;
[Flags] public enum Flags : uint
@@ -7129,7 +7129,7 @@ namespace TL
supports_streaming = 0x2,
/// Field has a value
has_preload_prefix_size = 0x4,
- /// Whether the specified document is a video file with no audio tracks (a GIF animation (even as MPEG4), for example)
+ /// Whether the specified document is a video file with no audio tracks
nosound = 0x8,
/// Field has a value
has_video_start_ts = 0x10,
@@ -7361,6 +7361,7 @@ namespace TL
has_attributes = 0x1000,
/// Whether the size of the media in the preview can be changed.
has_large_media = 0x2000,
+ video_cover_photo = 0x4000,
}
/// Preview ID
@@ -19842,7 +19843,7 @@ namespace TL
public override int AvailabilityTotal => availability_total;
}
/// See
- [TLDef(0xF2FE7E4A)]
+ [TLDef(0x5C62D151)]
public sealed partial class StarGiftUnique : StarGiftBase
{
public Flags flags;
@@ -19856,12 +19857,14 @@ namespace TL
public StarGiftAttribute[] attributes;
public int availability_issued;
public int availability_total;
+ [IfFlag(3)] public string gift_address;
[Flags] public enum Flags : uint
{
has_owner_id = 0x1,
has_owner_name = 0x2,
has_owner_address = 0x4,
+ has_gift_address = 0x8,
}
public override long ID => id;
@@ -20299,4 +20302,17 @@ namespace TL
{
public string url;
}
+
+ /// See
+ /// a value means paidReactionPrivacyDefault
+ public abstract partial class PaidReactionPrivacy : IObject { }
+ /// See
+ [TLDef(0x1F0C1AD9)]
+ public sealed partial class PaidReactionPrivacyAnonymous : PaidReactionPrivacy { }
+ /// See
+ [TLDef(0xDC6CFCF0)]
+ public sealed partial class PaidReactionPrivacyPeer : PaidReactionPrivacy
+ {
+ public InputPeer peer;
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 5f025de..296b6c7 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -126,6 +126,14 @@ namespace TL
query = query,
});
+ /// See
+ public static Task InvokeWithReCaptcha(this Client client, string token, IMethod query)
+ => client.Invoke(new InvokeWithReCaptcha
+ {
+ token = token,
+ query = query,
+ });
+
/// Send the verification code for login See Possible codes: 400,406,500 (details)
/// Phone number in international format
/// Application identifier (see App configuration)
@@ -4336,28 +4344,28 @@ namespace TL
platform = platform,
});
- /// Sends one or more paid Telegram Star reactions », transferring Telegram Stars » to a channel's balance. See Possible codes: 400 (details)
+ /// Sends one or more paid Telegram Star reactions », transferring Telegram Stars » to a channel's balance. See Possible codes: 400 (details)
/// The channel
/// The message to react to
/// The number of stars to send (each will increment the reaction counter by one).
/// Unique client message ID required to prevent message resending You can use
- /// Each post with star reactions has a leaderboard with the top senders, but users can opt out of appearing there if they prefer more privacy.
If the user explicitly chose to make their paid reaction(s) private, pass to Messages_SendPaidReaction.private.
If the user explicitly chose to make their paid reaction(s) private, pass to Messages_SendPaidReaction.private.
If the user did not make any explicit choice about the privacy of their paid reaction(s) (i.e. when reacting by clicking on an existing star reaction on a message), do not populate the Messages_SendPaidReaction.private flag.
- public static Task Messages_SendPaidReaction(this Client client, InputPeer peer, int msg_id, int count, long random_id, bool? private_ = default)
+ /// Each post with star reactions has a leaderboard with the top senders, but users can opt out of appearing there if they prefer more privacy.
If the user explicitly chose to make their paid reaction(s) private, pass to Messages_SendPaidReaction.private.
If the user explicitly chose to make their paid reaction(s) not private, pass to Messages_SendPaidReaction.private.
If the user did not make any explicit choice about the privacy of their paid reaction(s) (i.e. when reacting by clicking on an existing star reaction on a message), do not populate the Messages_SendPaidReaction.private flag.
+ public static Task Messages_SendPaidReaction(this Client client, InputPeer peer, int msg_id, int count, long random_id, PaidReactionPrivacy private_ = null)
=> client.Invoke(new Messages_SendPaidReaction
{
- flags = (Messages_SendPaidReaction.Flags)(private_ != default ? 0x1 : 0),
+ flags = (Messages_SendPaidReaction.Flags)(private_ != null ? 0x1 : 0),
peer = peer,
msg_id = msg_id,
count = count,
random_id = random_id,
- private_ = private_ ?? default,
+ private_ = private_,
});
/// Changes the privacy of already sent paid reactions on a specific message. See Possible codes: 400 (details)
/// The channel
/// The ID of the message to which we sent the paid reactions
/// If true, makes the current anonymous in the top sender leaderboard for this message; otherwise, does the opposite.
- public static Task Messages_TogglePaidReactionPrivacy(this Client client, InputPeer peer, int msg_id, bool private_)
+ public static Task Messages_TogglePaidReactionPrivacy(this Client client, InputPeer peer, int msg_id, PaidReactionPrivacy private_)
=> client.Invoke(new Messages_TogglePaidReactionPrivacy
{
peer = peer,
@@ -5253,9 +5261,10 @@ namespace TL
/// Obtains a list of peers that can be used to send messages in a specific group See Possible codes: 400 (details)
/// The group where we intend to send messages
- public static Task Channels_GetSendAs(this Client client, InputPeer peer)
+ public static Task Channels_GetSendAs(this Client client, InputPeer peer, bool for_paid_reactions = false)
=> client.Invoke(new Channels_GetSendAs
{
+ flags = (Channels_GetSendAs.Flags)(for_paid_reactions ? 0x1 : 0),
peer = peer,
});
@@ -7612,6 +7621,13 @@ namespace TL.Methods
public IMethod query;
}
+ [TLDef(0xADBB0F94)]
+ public sealed partial class InvokeWithReCaptcha : IMethod
+ {
+ public string token;
+ public IMethod query;
+ }
+
[TLDef(0xA677244F)]
public sealed partial class Auth_SendCode : IMethod
{
@@ -11132,7 +11148,7 @@ namespace TL.Methods
}
}
- [TLDef(0x9DD6A67B)]
+ [TLDef(0x58BBCB50)]
public sealed partial class Messages_SendPaidReaction : IMethod
{
public Flags flags;
@@ -11140,7 +11156,7 @@ namespace TL.Methods
public int msg_id;
public int count;
public long random_id;
- [IfFlag(0)] public bool private_;
+ [IfFlag(0)] public PaidReactionPrivacy private_;
[Flags] public enum Flags : uint
{
@@ -11148,12 +11164,12 @@ namespace TL.Methods
}
}
- [TLDef(0x849AD397)]
+ [TLDef(0x435885B5)]
public sealed partial class Messages_TogglePaidReactionPrivacy : IMethod
{
public InputPeer peer;
public int msg_id;
- public bool private_;
+ public PaidReactionPrivacy private_;
}
[TLDef(0x472455AA)]
@@ -11840,10 +11856,16 @@ namespace TL.Methods
public InputChannelBase channel;
}
- [TLDef(0x0DC770EE)]
+ [TLDef(0xE785A43F)]
public sealed partial class Channels_GetSendAs : IMethod
{
+ public Flags flags;
public InputPeer peer;
+
+ [Flags] public enum Flags : uint
+ {
+ for_paid_reactions = 0x1,
+ }
}
[TLDef(0x367544DB)]
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index b3f254a..742ecad 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 198; // fetched 22/01/2025 22:22:20
+ public const int Version = 199; // fetched 13/02/2025 13:06:03
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -419,7 +419,7 @@ namespace TL
[0x1EA2FDA7] = typeof(UpdateBusinessBotCallbackQuery),
[0xA584B019] = typeof(UpdateStarsRevenueStatus),
[0x283BD312] = typeof(UpdateBotPurchasedPaidMedia),
- [0x51CA7AEC] = typeof(UpdatePaidReactionPrivacy),
+ [0x8B725FCE] = typeof(UpdatePaidReactionPrivacy),
[0xA56C2A3E] = typeof(Updates_State),
[0x5D75A138] = typeof(Updates_DifferenceEmpty),
[0x00F49CA0] = typeof(Updates_Difference),
@@ -1344,7 +1344,7 @@ namespace TL
[0x94CE852A] = typeof(StarsGiveawayOption),
[0x54236209] = typeof(StarsGiveawayWinnersOption),
[0x02CC73C8] = typeof(StarGift),
- [0xF2FE7E4A] = typeof(StarGiftUnique),
+ [0x5C62D151] = typeof(StarGiftUnique),
[0xA388A368] = null,//Payments_StarGiftsNotModified
[0x901689EA] = typeof(Payments_StarGifts),
[0x7903E3D9] = typeof(MessageReportOption),
@@ -1377,6 +1377,9 @@ namespace TL
[0x69279795] = typeof(InputSavedStarGiftUser),
[0xF101AA7F] = typeof(InputSavedStarGiftChat),
[0x84AA3A9C] = typeof(Payments_StarGiftWithdrawalUrl),
+ [0x206AD49E] = null,//PaidReactionPrivacyDefault
+ [0x1F0C1AD9] = typeof(PaidReactionPrivacyAnonymous),
+ [0xDC6CFCF0] = typeof(PaidReactionPrivacyPeer),
// from TL.Secret:
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
[0x020DF5D0] = typeof(Layer101.MessageEntityBlockquote),
@@ -1507,6 +1510,7 @@ namespace TL
[typeof(Messages_QuickReplies)] = 0x5F91EB5B, //messages.quickRepliesNotModified
[typeof(Messages_AvailableEffects)] = 0xD1ED9A5B, //messages.availableEffectsNotModified
[typeof(Payments_StarGifts)] = 0xA388A368, //payments.starGiftsNotModified
+ [typeof(PaidReactionPrivacy)] = 0x206AD49E, //paidReactionPrivacyDefault
[typeof(DecryptedMessageMedia)] = 0x089F5C4A, //decryptedMessageMediaEmpty
};
}
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 5cd6031..79692c1 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 198
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 199
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From e67a688baa5c6a0a6ea7b331280ee25dcb2b50b5 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Mon, 3 Mar 2025 02:02:06 +0100
Subject: [PATCH 07/68] Building with Github Actions
---
.github/dev.yml | 9 ++++--
.github/workflows/autolock.yml | 2 +-
.github/workflows/dev.yml | 53 ++++++++++++++++++++++++++++++++
.github/workflows/release.yml | 56 ++++++++++++++++++++++++++++++++++
src/Client.cs | 1 +
src/TlsStream.cs | 6 ++--
src/WTelegramClient.csproj | 4 +--
7 files changed, 122 insertions(+), 9 deletions(-)
create mode 100644 .github/workflows/dev.yml
create mode 100644 .github/workflows/release.yml
diff --git a/.github/dev.yml b/.github/dev.yml
index e8a3729..6206e8e 100644
--- a/.github/dev.yml
+++ b/.github/dev.yml
@@ -1,7 +1,11 @@
pr: none
-trigger: [ master ]
+trigger:
+ branches:
+ include: [ master ]
+ paths:
+ exclude: [ '.github', '*.md', 'Examples' ]
-name: 4.3.1-dev.$(Rev:r)
+name: 4.3.2-dev.$(Rev:r)
pool:
vmImage: ubuntu-latest
@@ -57,4 +61,3 @@ stages:
"message": "{ \"commitId\": \"$(Build.SourceVersion)\", \"buildNumber\": \"$(Build.BuildNumber)\", \"teamProjectName\": \"$(System.TeamProject)\", \"commitMessage\": \"$(Release_Notes)\" }"
}
waitForCompletion: 'false'
-
\ No newline at end of file
diff --git a/.github/workflows/autolock.yml b/.github/workflows/autolock.yml
index 0bd8a20..9a676bc 100644
--- a/.github/workflows/autolock.yml
+++ b/.github/workflows/autolock.yml
@@ -2,7 +2,7 @@ name: 'Auto-Lock Issues'
on:
schedule:
- - cron: '17 2 * * *'
+ - cron: '17 2 * * 1'
workflow_dispatch:
permissions:
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
new file mode 100644
index 0000000..6130d21
--- /dev/null
+++ b/.github/workflows/dev.yml
@@ -0,0 +1,53 @@
+name: Dev build
+
+on:
+ push:
+ branches: [ master ]
+ paths-ignore: [ '.**', 'Examples/**', '**.md' ]
+
+env:
+ PROJECT_PATH: src/WTelegramClient.csproj
+ CONFIGURATION: Release
+ RELEASE_NOTES: ${{ github.event.head_commit.message }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 100
+ - name: Determine version
+ run: |
+ git fetch --depth=100 --tags
+ DESCR_TAG=$(git describe --tags)
+ COMMITS=${DESCR_TAG#*-}
+ COMMITS=${COMMITS%-*}
+ LAST_TAG=${DESCR_TAG%%-*}
+ NEXT_VERSION=${LAST_TAG%.*}.$((${LAST_TAG##*.} + 1))-dev.$COMMITS
+ RELEASE_VERSION=${{vars.RELEASE_VERSION}}-dev.$COMMITS
+ if [[ "$RELEASE_VERSION" > "$NEXT_VERSION" ]] then VERSION=$RELEASE_VERSION; else VERSION=$NEXT_VERSION; fi
+ echo Last tag: $LAST_TAG · Next version: $NEXT_VERSION · Release version: $RELEASE_VERSION · Build version: $VERSION
+ echo "VERSION=$VERSION" >> $GITHUB_ENV
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - name: Pack
+ run: dotnet pack $PROJECT_PATH --configuration $CONFIGURATION -p:Version=$VERSION "-p:ReleaseNotes=\"$RELEASE_NOTES\"" --output packages
+ # - name: Upload artifact
+ # uses: actions/upload-artifact@v4
+ # with:
+ # name: packages
+ # path: packages/*.nupkg
+ - name: Nuget push
+ run: dotnet nuget push packages/*.nupkg --api-key ${{secrets.NUGETAPIKEY}} --skip-duplicate --source https://api.nuget.org/v3/index.json
+ - name: Deployment Notification
+ env:
+ JSON: |
+ {
+ "status": "success", "complete": true, "commitMessage": ${{ toJSON(github.event.head_commit.message) }},
+ "message": "{ \"commitId\": \"${{ github.event.head_commit.id }}\", \"buildNumber\": \"${{ env.VERSION }}\", \"teamProjectName\": \"${{ github.event.repository.name }}\"}"
+ }
+ run: |
+ curl -X POST -H "Content-Type: application/json" -d "$JSON" ${{ secrets.DEPLOYED_WEBHOOK }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..5d1519e
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,56 @@
+name: Release build
+
+on:
+ workflow_dispatch:
+ inputs:
+ release_notes:
+ description: 'Release notes'
+ required: true
+ version:
+ description: "Release version (leave empty for automatic versioning)"
+
+run-name: '📌 Release build ${{ inputs.version }}'
+
+env:
+ PROJECT_PATH: src/WTelegramClient.csproj
+ CONFIGURATION: Release
+ RELEASE_NOTES: ${{ inputs.release_notes }}
+ VERSION: ${{ inputs.version }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write # For git tag
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 100
+ - name: Determine version
+ if: ${{ env.VERSION == '' }}
+ run: |
+ git fetch --depth=100 --tags
+ DESCR_TAG=$(git describe --tags)
+ LAST_TAG=${DESCR_TAG%%-*}
+ NEXT_VERSION=${LAST_TAG%.*}.$((${LAST_TAG##*.} + 1))
+ RELEASE_VERSION=${{vars.RELEASE_VERSION}}
+ if [[ "$RELEASE_VERSION" > "$NEXT_VERSION" ]] then VERSION=$RELEASE_VERSION; else VERSION=$NEXT_VERSION; fi
+ echo Last tag: $LAST_TAG · Next version: $NEXT_VERSION · Release version: $RELEASE_VERSION · Build version: $VERSION
+ echo "VERSION=$VERSION" >> $GITHUB_ENV
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - name: Pack
+ run: dotnet pack $PROJECT_PATH --configuration $CONFIGURATION -p:Version=$VERSION "-p:ReleaseNotes=\"$RELEASE_NOTES\"" --output packages
+ # - name: Upload artifact
+ # uses: actions/upload-artifact@v4
+ # with:
+ # name: packages
+ # path: packages/*.nupkg
+ - name: Nuget push
+ run: dotnet nuget push packages/*.nupkg --api-key ${{secrets.NUGETAPIKEY}} --skip-duplicate --source https://api.nuget.org/v3/index.json
+ - name: Git tag
+ run: |
+ git tag $VERSION
+ git push --tags
diff --git a/src/Client.cs b/src/Client.cs
index fead981..fa172e6 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -292,6 +292,7 @@ namespace WTelegram
/// ID of the Data Center (use negative values for media_only)
/// Connect immediately
/// Client connected to the selected DC
+ /// ⚠️ You shouldn't have to use this method unless you know what you're doing
public async Task GetClientForDC(int dcId, bool connect = true)
{
if (_dcSession.DataCenter?.id == dcId) return this;
diff --git a/src/TlsStream.cs b/src/TlsStream.cs
index 3adc277..4e6ff30 100644
--- a/src/TlsStream.cs
+++ b/src/TlsStream.cs
@@ -100,7 +100,7 @@ namespace WTelegram
static readonly byte[] TlsClientHello3 = [
// 0x00, 0x00, len { len { 0x00 len { domain } } } len is 16-bit big-endian length of the following block of data
0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x4A, 0x4A,/*=grease(4)*/ 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+ 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x4A, 0x4A/*=grease(4)*/, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
0x00, 0x0d, 0x00, 0x12, 0x00, 0x10, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01,
0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
@@ -108,9 +108,9 @@ namespace WTelegram
0x00, 0x17, 0x00, 0x00,
0x00, 0x1b, 0x00, 0x03, 0x02, 0x00, 0x02,
0x00, 0x23, 0x00, 0x00,
- 0x00, 0x2b, 0x00, 0x07, 0x06, 0x6A, 0x6A,/*=grease(6) */ 0x03, 0x04, 0x03, 0x03,
+ 0x00, 0x2b, 0x00, 0x07, 0x06, 0x6A, 0x6A/*=grease(6)*/, 0x03, 0x04, 0x03, 0x03,
0x00, 0x2d, 0x00, 0x02, 0x01, 0x01,
- 0x00, 0x33, 0x00, 0x2b, 0x00, 0x29, 0x4A, 0x4A,/*=grease(4) */ 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x20, /* random[32] */
+ 0x00, 0x33, 0x00, 0x2b, 0x00, 0x29, 0x4A, 0x4A/*=grease(4)*/, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x20, /* random[32] */
0x44, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x68, 0x32,
0xff, 0x01, 0x00, 0x01, 0x00,
];
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 79692c1..b54e320 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -33,8 +33,8 @@ $(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%
-
-
+
+
From 1ecd7047eff47111c5ffe5f2abc1ba0e74819657 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Sat, 8 Mar 2025 00:21:50 +0100
Subject: [PATCH 08/68] API Layer 200: Paid messages, details on chat partner,
...
---
README.md | 2 +-
src/TL.Schema.cs | 124 ++++++++++++++++++++++++++-----------
src/TL.SchemaFuncs.cs | 119 ++++++++++++++++++++++++++++-------
src/TL.Table.cs | 23 ++++---
src/WTelegramClient.csproj | 2 +-
5 files changed, 201 insertions(+), 69 deletions(-)
diff --git a/README.md b/README.md
index 12f7892..47419e1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 3d612af..5caaf90 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -768,7 +768,7 @@ namespace TL
public long id;
}
/// Indicates info about a certain user. See
- [TLDef(0x4B46C37E)]
+ [TLDef(0x020B1422)]
public sealed partial class User : UserBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -812,6 +812,7 @@ namespace TL
/// Monthly Active Users (MAU) of this bot (may be absent for small bots).
[IfFlag(44)] public int bot_active_users;
[IfFlag(46)] public long bot_verification_icon;
+ [IfFlag(47)] public long send_paid_messages_stars;
[Flags] public enum Flags : uint
{
@@ -901,6 +902,8 @@ namespace TL
bot_has_main_app = 0x2000,
/// Field has a value
has_bot_verification_icon = 0x4000,
+ /// Field has a value
+ has_send_paid_messages_stars = 0x8000,
}
}
@@ -1071,7 +1074,7 @@ namespace TL
public override string Title => title;
}
/// Channel/supergroup info See
- [TLDef(0xE00998B7)]
+ [TLDef(0x7482147E)]
public sealed partial class Channel : ChatBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1115,6 +1118,7 @@ namespace TL
/// Expiration date of the Telegram Star subscription » the current user has bought to gain access to this channel.
[IfFlag(43)] public DateTime subscription_until_date;
[IfFlag(45)] public long bot_verification_icon;
+ [IfFlag(46)] public long send_paid_messages_stars;
[Flags] public enum Flags : uint
{
@@ -1198,6 +1202,8 @@ namespace TL
signature_profiles = 0x1000,
/// Field has a value
has_bot_verification_icon = 0x2000,
+ /// Field has a value
+ has_send_paid_messages_stars = 0x4000,
}
/// ID of the channel, see here » for more info
@@ -1580,6 +1586,7 @@ namespace TL
/// Field has a value
has_stargifts_count = 0x40000,
stargifts_available = 0x80000,
+ paid_messages_available = 0x100000,
}
/// ID of the channel
@@ -1757,7 +1764,7 @@ namespace TL
public override Peer Peer => peer_id;
}
/// A message See
- [TLDef(0x96FDBBE9)]
+ [TLDef(0xEABCDD4D)]
public sealed partial class Message : MessageBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1817,6 +1824,7 @@ namespace TL
/// Represents a fact-check ».
[IfFlag(35)] public FactCheck factcheck;
[IfFlag(37)] public DateTime report_delivery_until_date;
+ [IfFlag(38)] public long paid_message_stars;
[Flags] public enum Flags : uint
{
@@ -1894,6 +1902,8 @@ namespace TL
video_processing_pending = 0x10,
/// Field has a value
has_report_delivery_until_date = 0x20,
+ /// Field has a value
+ has_paid_message_stars = 0x40,
}
/// ID of the message
@@ -2742,12 +2752,14 @@ namespace TL
via_giveaway = 0x1,
/// Field has a value
has_boost_peer = 0x2,
- /// If set, the link was not redeemed yet.
- unclaimed = 0x4,
+ /// Fields and have a value
+ has_currency = 0x4,
/// Fields and have a value
has_crypto_currency = 0x8,
/// Field has a value
has_message = 0x10,
+ /// If set, the link was not redeemed yet.
+ unclaimed = 0x20,
}
}
/// A giveaway was started. See
@@ -3392,7 +3404,7 @@ namespace TL
}
/// List of actions that are possible when interacting with this user, to be shown as suggested actions in the chat action bar », see here » for more info. See
- [TLDef(0xACD66C5E)]
+ [TLDef(0xF47741F7)]
public sealed partial class PeerSettings : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -3407,6 +3419,11 @@ namespace TL
[IfFlag(13)] public long business_bot_id;
/// Contains a deep link », used to open a management menu in the business bot. This flag is set if and only if business_bot_id is set.
[IfFlag(13)] public string business_bot_manage_url;
+ [IfFlag(14)] public long charge_paid_message_stars;
+ [IfFlag(15)] public string registration_month;
+ [IfFlag(16)] public string phone_country;
+ [IfFlag(17)] public DateTime name_change_date;
+ [IfFlag(18)] public DateTime photo_change_date;
[Flags] public enum Flags : uint
{
@@ -3438,6 +3455,16 @@ namespace TL
business_bot_can_reply = 0x1000,
/// Fields and have a value
has_business_bot_id = 0x2000,
+ /// Field has a value
+ has_charge_paid_message_stars = 0x4000,
+ /// Field has a value
+ has_registration_month = 0x8000,
+ /// Field has a value
+ has_phone_country = 0x10000,
+ /// Field has a value
+ has_name_change_date = 0x20000,
+ /// Field has a value
+ has_photo_change_date = 0x40000,
}
}
@@ -3538,7 +3565,7 @@ namespace TL
}
/// Extended user info See
- [TLDef(0x4D975BBC)]
+ [TLDef(0xD2234EA0)]
public sealed partial class UserFull : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -3577,8 +3604,6 @@ namespace TL
[IfFlag(17)] public ChatAdminRights bot_group_admin_rights;
/// A suggested set of administrator rights for the bot, to be shown when adding the bot as admin to a channel, see here for more info on how to handle them ».
[IfFlag(18)] public ChatAdminRights bot_broadcast_admin_rights;
- /// Telegram Premium subscriptions gift options
- [IfFlag(19)] public PremiumGiftOption[] premium_gifts;
/// Wallpaper to use in the private chat with the user.
[IfFlag(24)] public WallPaperBase wallpaper;
/// Active stories »
@@ -3604,6 +3629,7 @@ namespace TL
/// This bot has an active referral program »
[IfFlag(43)] public StarRefProgram starref_program;
[IfFlag(44)] public BotVerification bot_verification;
+ [IfFlag(46)] public long send_paid_messages_stars;
[Flags] public enum Flags : uint
{
@@ -3639,8 +3665,6 @@ namespace TL
has_bot_group_admin_rights = 0x20000,
/// Field has a value
has_bot_broadcast_admin_rights = 0x40000,
- /// Field has a value
- has_premium_gifts = 0x80000,
/// Whether this user doesn't allow sending voice messages in a private chat with them
voice_messages_forbidden = 0x100000,
/// Field has a value
@@ -3693,6 +3717,8 @@ namespace TL
has_starref_program = 0x800,
/// Field has a value
has_bot_verification = 0x1000,
+ /// Field has a value
+ has_send_paid_messages_stars = 0x4000,
}
}
@@ -6904,6 +6930,8 @@ namespace TL
Birthday = 0xD65A11CC,
///Whether received gifts will be automatically displayed on our profile
StarGiftsAutoSave = 0xE1732341,
+ ///See
+ NoPaidMessages = 0xBDC597B4,
}
/// Privacy keys together with privacy rules » indicate what can or can't someone do and are specified by a constructor, and its input counterpart . See
@@ -6933,6 +6961,8 @@ namespace TL
Birthday = 0x2000A518,
///Whether received gifts will be automatically displayed on our profile
StarGiftsAutoSave = 0x2CA4FDF8,
+ ///See
+ NoPaidMessages = 0x17D348D2,
}
/// Privacy rules indicate who can or can't do something and are specified by a , and its input counterpart . See Derived classes: , , , , , , , , , , ,
@@ -14454,11 +14484,12 @@ namespace TL
}
/// Global privacy settings See
- [TLDef(0x734C4CCB)]
+ [TLDef(0xC9D8DF1C)]
public sealed partial class GlobalPrivacySettings : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
+ [IfFlag(5)] public long noncontact_peers_paid_stars;
[Flags] public enum Flags : uint
{
@@ -14472,6 +14503,8 @@ namespace TL
hide_read_marks = 0x8,
/// If set, only users that have a premium account, are in our contact list, or already have a private chat with us can write to us; a 403 PRIVACY_PREMIUM_REQUIRED error will be emitted otherwise.
The .contact_require_premium flag will be set for users that have this flag enabled.
To check whether we can write to a user with this flag enabled, if we haven't yet cached all the required information (for example we don't have the or history of all users while displaying the chat list in the sharing UI) the Users_GetIsPremiumRequiredToContact method may be invoked, passing the list of users currently visible in the UI, returning a list of booleans that directly specify whether we can or cannot write to each user.
This option may be enabled by both non-Premium and Premium users only if the new_noncontact_peers_require_premium_without_ownpremium client configuration flag » is equal to true, otherwise it may be enabled only by Premium users and non-Premium users will receive a PREMIUM_ACCOUNT_REQUIRED error when trying to enable this flag.
new_noncontact_peers_require_premium = 0x10,
+ /// Field has a value
+ has_noncontact_peers_paid_stars = 0x20,
}
}
@@ -15865,6 +15898,20 @@ namespace TL
public InputSavedStarGift stargift;
public InputPeer to_id;
}
+ /// See
+ [TLDef(0xDABAB2EF)]
+ public sealed partial class InputInvoicePremiumGiftStars : InputInvoice
+ {
+ public Flags flags;
+ public InputUserBase user_id;
+ public int months;
+ [IfFlag(0)] public TextWithEntities message;
+
+ [Flags] public enum Flags : uint
+ {
+ has_message = 0x1,
+ }
+ }
/// Exported invoice deep link See
[TLDef(0xAED0CBD9)]
@@ -16072,30 +16119,6 @@ namespace TL
}
}
- /// Telegram Premium gift option See
- [TLDef(0x74C34319)]
- public sealed partial class PremiumGiftOption : IObject
- {
- /// Extra bits of information, use flags.HasFlag(...) to test for those
- public Flags flags;
- /// Duration of gifted Telegram Premium subscription
- public int months;
- /// Three-letter ISO 4217 currency code
- public string currency;
- /// Price of the product in the smallest units of the currency (integer, not float/double). For example, for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies).
- public long amount;
- /// An invoice deep link » to an invoice for in-app payment, using the official Premium bot; may be empty if direct payment isn't available.
- public string bot_url;
- /// An identifier for the App Store/Play Store product associated with the Premium gift.
- [IfFlag(0)] public string store_product;
-
- [Flags] public enum Flags : uint
- {
- /// Field has a value
- has_store_product = 0x1,
- }
- }
-
/// Represents an additional payment method See
[TLDef(0x88F8F21B)]
public sealed partial class PaymentFormMethod : IObject
@@ -19349,7 +19372,7 @@ namespace TL
}
/// Represents a Telegram Stars transaction ». See
- [TLDef(0x64DFC926)]
+ [TLDef(0xA39FD94A)]
public sealed partial class StarsTransaction : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -19392,6 +19415,8 @@ namespace TL
[IfFlag(17)] public Peer starref_peer;
/// For transactions made by referred users, the amount of Telegram Stars received by the affiliate, can be negative for refunds.
[IfFlag(17)] public StarsAmount starref_amount;
+ [IfFlag(19)] public int paid_messages;
+ [IfFlag(20)] public int premium_gift_months;
[Flags] public enum Flags : uint
{
@@ -19432,6 +19457,10 @@ namespace TL
/// Fields and have a value
has_starref_peer = 0x20000,
stargift_upgrade = 0x40000,
+ /// Field has a value
+ has_paid_messages = 0x80000,
+ /// Field has a value
+ has_premium_gift_months = 0x100000,
}
}
@@ -20256,6 +20285,7 @@ namespace TL
refunded = 0x200,
can_upgrade = 0x400,
has_saved_id = 0x800,
+ pinned_to_top = 0x1000,
}
}
@@ -20315,4 +20345,24 @@ namespace TL
{
public InputPeer peer;
}
+
+ /// See
+ [TLDef(0x1E109708)]
+ public sealed partial class Account_PaidMessagesRevenue : IObject
+ {
+ public long stars_amount;
+ }
+
+ /// See
+ /// a value means requirementToContactEmpty
+ public abstract partial class RequirementToContact : IObject { }
+ /// See
+ [TLDef(0xE581E4E9)]
+ public sealed partial class RequirementToContactPremium : RequirementToContact { }
+ /// See
+ [TLDef(0xB4F67E93)]
+ public sealed partial class RequirementToContactPaidMessages : RequirementToContact
+ {
+ public long stars_amount;
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 296b6c7..004175d 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1433,6 +1433,21 @@ namespace TL
hash = hash,
});
+ /// See
+ public static Task Account_AddNoPaidMessagesException(this Client client, InputUserBase user_id, bool refund_charged = false)
+ => client.Invoke(new Account_AddNoPaidMessagesException
+ {
+ flags = (Account_AddNoPaidMessagesException.Flags)(refund_charged ? 0x1 : 0),
+ user_id = user_id,
+ });
+
+ /// See
+ public static Task Account_GetPaidMessagesRevenue(this Client client, InputUserBase user_id)
+ => client.Invoke(new Account_GetPaidMessagesRevenue
+ {
+ user_id = user_id,
+ });
+
/// Returns basic user info according to their identifiers. See [bots: ✓] Possible codes: 400 (details)
/// List of user identifiers
public static Task Users_GetUsers(this Client client, params InputUserBase[] id)
@@ -1459,10 +1474,9 @@ namespace TL
errors = errors,
});
- /// Check whether we can write to the specified user (this method can only be called by non-Premium users), see here » for more info on the full flow. See
- /// Users to fetch info about.
- public static Task Users_GetIsPremiumRequiredToContact(this Client client, params InputUserBase[] id)
- => client.Invoke(new Users_GetIsPremiumRequiredToContact
+ /// See
+ public static Task Users_GetRequirementsToContact(this Client client, params InputUserBase[] id)
+ => client.Invoke(new Users_GetRequirementsToContact
{
id = id,
});
@@ -1880,10 +1894,10 @@ namespace TL
/// Send this message as the specified peer
/// Add the message to the specified quick reply shortcut », instead.
/// Specifies a message effect » to use for the message.
- public static Task Messages_SendMessage(this Client client, InputPeer peer, string message, long random_id, InputReplyTo reply_to = null, ReplyMarkup reply_markup = null, MessageEntity[] entities = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? effect = null, bool no_webpage = false, bool silent = false, bool background = false, bool clear_draft = false, bool noforwards = false, bool update_stickersets_order = false, bool invert_media = false, bool allow_paid_floodskip = false)
+ public static Task Messages_SendMessage(this Client client, InputPeer peer, string message, long random_id, InputReplyTo reply_to = null, ReplyMarkup reply_markup = null, MessageEntity[] entities = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? effect = null, long? allow_paid_stars = null, bool no_webpage = false, bool silent = false, bool background = false, bool clear_draft = false, bool noforwards = false, bool update_stickersets_order = false, bool invert_media = false, bool allow_paid_floodskip = false)
=> client.Invoke(new Messages_SendMessage
{
- flags = (Messages_SendMessage.Flags)((reply_to != null ? 0x1 : 0) | (reply_markup != null ? 0x4 : 0) | (entities != null ? 0x8 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (effect != null ? 0x40000 : 0) | (no_webpage ? 0x2 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (noforwards ? 0x4000 : 0) | (update_stickersets_order ? 0x8000 : 0) | (invert_media ? 0x10000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
+ flags = (Messages_SendMessage.Flags)((reply_to != null ? 0x1 : 0) | (reply_markup != null ? 0x4 : 0) | (entities != null ? 0x8 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (effect != null ? 0x40000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (no_webpage ? 0x2 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (noforwards ? 0x4000 : 0) | (update_stickersets_order ? 0x8000 : 0) | (invert_media ? 0x10000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
peer = peer,
reply_to = reply_to,
message = message,
@@ -1894,6 +1908,7 @@ namespace TL
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
effect = effect ?? default,
+ allow_paid_stars = allow_paid_stars ?? default,
});
/// Send a media See [bots: ✓] Possible codes: 400,403,406,420,500 (details)
@@ -1915,10 +1930,10 @@ namespace TL
/// Send this message as the specified peer
/// Add the message to the specified quick reply shortcut », instead.
/// Specifies a message effect » to use for the message.
- public static Task Messages_SendMedia(this Client client, InputPeer peer, InputMedia media, string message, long random_id, InputReplyTo reply_to = null, ReplyMarkup reply_markup = null, MessageEntity[] entities = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? effect = null, bool silent = false, bool background = false, bool clear_draft = false, bool noforwards = false, bool update_stickersets_order = false, bool invert_media = false, bool allow_paid_floodskip = false)
+ public static Task Messages_SendMedia(this Client client, InputPeer peer, InputMedia media, string message, long random_id, InputReplyTo reply_to = null, ReplyMarkup reply_markup = null, MessageEntity[] entities = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? effect = null, long? allow_paid_stars = null, bool silent = false, bool background = false, bool clear_draft = false, bool noforwards = false, bool update_stickersets_order = false, bool invert_media = false, bool allow_paid_floodskip = false)
=> client.Invoke(new Messages_SendMedia
{
- flags = (Messages_SendMedia.Flags)((reply_to != null ? 0x1 : 0) | (reply_markup != null ? 0x4 : 0) | (entities != null ? 0x8 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (effect != null ? 0x40000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (noforwards ? 0x4000 : 0) | (update_stickersets_order ? 0x8000 : 0) | (invert_media ? 0x10000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
+ flags = (Messages_SendMedia.Flags)((reply_to != null ? 0x1 : 0) | (reply_markup != null ? 0x4 : 0) | (entities != null ? 0x8 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (effect != null ? 0x40000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (noforwards ? 0x4000 : 0) | (update_stickersets_order ? 0x8000 : 0) | (invert_media ? 0x10000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
peer = peer,
reply_to = reply_to,
media = media,
@@ -1930,6 +1945,7 @@ namespace TL
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
effect = effect ?? default,
+ allow_paid_stars = allow_paid_stars ?? default,
});
/// Forwards messages by their IDs. See [bots: ✓] Possible codes: 400,403,406,420,500 (details)
@@ -1948,10 +1964,10 @@ namespace TL
/// Scheduled message date for scheduled messages
/// Forward the messages as the specified peer
/// Add the messages to the specified quick reply shortcut », instead.
- public static Task Messages_ForwardMessages(this Client client, InputPeer from_peer, int[] id, long[] random_id, InputPeer to_peer, int? top_msg_id = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, int? video_timestamp = null, bool silent = false, bool background = false, bool with_my_score = false, bool drop_author = false, bool drop_media_captions = false, bool noforwards = false, bool allow_paid_floodskip = false)
+ public static Task Messages_ForwardMessages(this Client client, InputPeer from_peer, int[] id, long[] random_id, InputPeer to_peer, int? top_msg_id = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, int? video_timestamp = null, long? allow_paid_stars = null, bool silent = false, bool background = false, bool with_my_score = false, bool drop_author = false, bool drop_media_captions = false, bool noforwards = false, bool allow_paid_floodskip = false)
=> client.Invoke(new Messages_ForwardMessages
{
- flags = (Messages_ForwardMessages.Flags)((top_msg_id != null ? 0x200 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (video_timestamp != null ? 0x100000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (with_my_score ? 0x100 : 0) | (drop_author ? 0x800 : 0) | (drop_media_captions ? 0x1000 : 0) | (noforwards ? 0x4000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
+ flags = (Messages_ForwardMessages.Flags)((top_msg_id != null ? 0x200 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (video_timestamp != null ? 0x100000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (with_my_score ? 0x100 : 0) | (drop_author ? 0x800 : 0) | (drop_media_captions ? 0x1000 : 0) | (noforwards ? 0x4000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
from_peer = from_peer,
id = id,
random_id = random_id,
@@ -1961,6 +1977,7 @@ namespace TL
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
video_timestamp = video_timestamp ?? default,
+ allow_paid_stars = allow_paid_stars ?? default,
});
/// Report a new incoming chat for spam, if the of the chat allow us to do that See Possible codes: 400 (details)
@@ -2458,10 +2475,10 @@ namespace TL
/// Scheduled message date for scheduled messages
/// Send this message as the specified peer
/// Add the message to the specified quick reply shortcut », instead.
- public static Task Messages_SendInlineBotResult(this Client client, InputPeer peer, long random_id, long query_id, string id, InputReplyTo reply_to = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, bool silent = false, bool background = false, bool clear_draft = false, bool hide_via = false)
+ public static Task Messages_SendInlineBotResult(this Client client, InputPeer peer, long random_id, long query_id, string id, InputReplyTo reply_to = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? allow_paid_stars = null, bool silent = false, bool background = false, bool clear_draft = false, bool hide_via = false)
=> client.Invoke(new Messages_SendInlineBotResult
{
- flags = (Messages_SendInlineBotResult.Flags)((reply_to != null ? 0x1 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (hide_via ? 0x800 : 0)),
+ flags = (Messages_SendInlineBotResult.Flags)((reply_to != null ? 0x1 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (hide_via ? 0x800 : 0)),
peer = peer,
reply_to = reply_to,
random_id = random_id,
@@ -2470,6 +2487,7 @@ namespace TL
schedule_date = schedule_date ?? default,
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
+ allow_paid_stars = allow_paid_stars ?? default,
});
/// Find out if a media message's caption can be edited See Possible codes: 400,403 (details)
@@ -2905,10 +2923,10 @@ namespace TL
/// Send this message as the specified peer
/// Add the message to the specified quick reply shortcut », instead.
/// Specifies a message effect » to use for the message.
- public static Task Messages_SendMultiMedia(this Client client, InputPeer peer, InputSingleMedia[] multi_media, InputReplyTo reply_to = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? effect = null, bool silent = false, bool background = false, bool clear_draft = false, bool noforwards = false, bool update_stickersets_order = false, bool invert_media = false, bool allow_paid_floodskip = false)
+ public static Task Messages_SendMultiMedia(this Client client, InputPeer peer, InputSingleMedia[] multi_media, InputReplyTo reply_to = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, long? effect = null, long? allow_paid_stars = null, bool silent = false, bool background = false, bool clear_draft = false, bool noforwards = false, bool update_stickersets_order = false, bool invert_media = false, bool allow_paid_floodskip = false)
=> client.Invoke(new Messages_SendMultiMedia
{
- flags = (Messages_SendMultiMedia.Flags)((reply_to != null ? 0x1 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (effect != null ? 0x40000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (noforwards ? 0x4000 : 0) | (update_stickersets_order ? 0x8000 : 0) | (invert_media ? 0x10000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
+ flags = (Messages_SendMultiMedia.Flags)((reply_to != null ? 0x1 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (effect != null ? 0x40000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (clear_draft ? 0x80 : 0) | (noforwards ? 0x4000 : 0) | (update_stickersets_order ? 0x8000 : 0) | (invert_media ? 0x10000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
peer = peer,
reply_to = reply_to,
multi_media = multi_media,
@@ -2916,6 +2934,7 @@ namespace TL
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
effect = effect ?? default,
+ allow_paid_stars = allow_paid_stars ?? default,
});
/// Upload encrypted file and associate it to a secret chat See Possible codes: 400 (details)
@@ -5558,6 +5577,14 @@ namespace TL
limit = limit,
});
+ /// See
+ public static Task Channels_UpdatePaidMessagesPrice(this Client client, InputChannelBase channel, long send_paid_messages_stars)
+ => client.Invoke(new Channels_UpdatePaidMessagesPrice
+ {
+ channel = channel,
+ send_paid_messages_stars = send_paid_messages_stars,
+ });
+
/// Sends a custom request; for bots only See [bots: ✓] Possible codes: 400,403 (details)
/// The method name
/// JSON-serialized method parameters
@@ -6331,6 +6358,14 @@ namespace TL
peer = peer,
});
+ /// See
+ public static Task Payments_ToggleStarGiftsPinnedToTop(this Client client, InputPeer peer, params InputSavedStarGift[] stargift)
+ => client.Invoke(new Payments_ToggleStarGiftsPinnedToTop
+ {
+ peer = peer,
+ stargift = stargift,
+ });
+
/// Create a stickerset. See [bots: ✓] Possible codes: 400 (details)
/// Whether this is a mask stickerset
/// Whether this is a custom emoji stickerset.
@@ -8663,6 +8698,24 @@ namespace TL.Methods
public long hash;
}
+ [TLDef(0x6F688AA7)]
+ public sealed partial class Account_AddNoPaidMessagesException : IMethod
+ {
+ public Flags flags;
+ public InputUserBase user_id;
+
+ [Flags] public enum Flags : uint
+ {
+ refund_charged = 0x1,
+ }
+ }
+
+ [TLDef(0xF1266F38)]
+ public sealed partial class Account_GetPaidMessagesRevenue : IMethod
+ {
+ public InputUserBase user_id;
+ }
+
[TLDef(0x0D91A548)]
public sealed partial class Users_GetUsers : IMethod
{
@@ -8682,8 +8735,8 @@ namespace TL.Methods
public SecureValueErrorBase[] errors;
}
- [TLDef(0xA622AA10)]
- public sealed partial class Users_GetIsPremiumRequiredToContact : IMethod
+ [TLDef(0xD89A83A3)]
+ public sealed partial class Users_GetRequirementsToContact : IMethod
{
public InputUserBase[] id;
}
@@ -9028,7 +9081,7 @@ namespace TL.Methods
}
}
- [TLDef(0x983F9745)]
+ [TLDef(0xFBF2340A)]
public sealed partial class Messages_SendMessage : IMethod
{
public Flags flags;
@@ -9042,6 +9095,7 @@ namespace TL.Methods
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(18)] public long effect;
+ [IfFlag(21)] public long allow_paid_stars;
[Flags] public enum Flags : uint
{
@@ -9060,10 +9114,11 @@ namespace TL.Methods
has_quick_reply_shortcut = 0x20000,
has_effect = 0x40000,
allow_paid_floodskip = 0x80000,
+ has_allow_paid_stars = 0x200000,
}
}
- [TLDef(0x7852834E)]
+ [TLDef(0xA550CD78)]
public sealed partial class Messages_SendMedia : IMethod
{
public Flags flags;
@@ -9078,6 +9133,7 @@ namespace TL.Methods
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(18)] public long effect;
+ [IfFlag(21)] public long allow_paid_stars;
[Flags] public enum Flags : uint
{
@@ -9095,10 +9151,11 @@ namespace TL.Methods
has_quick_reply_shortcut = 0x20000,
has_effect = 0x40000,
allow_paid_floodskip = 0x80000,
+ has_allow_paid_stars = 0x200000,
}
}
- [TLDef(0x6D74DA08)]
+ [TLDef(0xBB9FA475)]
public sealed partial class Messages_ForwardMessages : IMethod
{
public Flags flags;
@@ -9111,6 +9168,7 @@ namespace TL.Methods
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(20)] public int video_timestamp;
+ [IfFlag(21)] public long allow_paid_stars;
[Flags] public enum Flags : uint
{
@@ -9126,6 +9184,7 @@ namespace TL.Methods
has_quick_reply_shortcut = 0x20000,
allow_paid_floodskip = 0x80000,
has_video_timestamp = 0x100000,
+ has_allow_paid_stars = 0x200000,
}
}
@@ -9519,7 +9578,7 @@ namespace TL.Methods
}
}
- [TLDef(0x3EBEE86A)]
+ [TLDef(0xC0CF7646)]
public sealed partial class Messages_SendInlineBotResult : IMethod
{
public Flags flags;
@@ -9531,6 +9590,7 @@ namespace TL.Methods
[IfFlag(10)] public DateTime schedule_date;
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
+ [IfFlag(21)] public long allow_paid_stars;
[Flags] public enum Flags : uint
{
@@ -9542,6 +9602,7 @@ namespace TL.Methods
hide_via = 0x800,
has_send_as = 0x2000,
has_quick_reply_shortcut = 0x20000,
+ has_allow_paid_stars = 0x200000,
}
}
@@ -9933,7 +9994,7 @@ namespace TL.Methods
public long hash;
}
- [TLDef(0x37B74355)]
+ [TLDef(0x1BF89D74)]
public sealed partial class Messages_SendMultiMedia : IMethod
{
public Flags flags;
@@ -9944,6 +10005,7 @@ namespace TL.Methods
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(18)] public long effect;
+ [IfFlag(21)] public long allow_paid_stars;
[Flags] public enum Flags : uint
{
@@ -9959,6 +10021,7 @@ namespace TL.Methods
has_quick_reply_shortcut = 0x20000,
has_effect = 0x40000,
allow_paid_floodskip = 0x80000,
+ has_allow_paid_stars = 0x200000,
}
}
@@ -12102,6 +12165,13 @@ namespace TL.Methods
public int limit;
}
+ [TLDef(0xFC84653F)]
+ public sealed partial class Channels_UpdatePaidMessagesPrice : IMethod
+ {
+ public InputChannelBase channel;
+ public long send_paid_messages_stars;
+ }
+
[TLDef(0xAA2769ED)]
public sealed partial class Bots_SendCustomRequest : IMethod
{
@@ -12774,6 +12844,13 @@ namespace TL.Methods
}
}
+ [TLDef(0x1513E7B0)]
+ public sealed partial class Payments_ToggleStarGiftsPinnedToTop : IMethod
+ {
+ public InputPeer peer;
+ public InputSavedStarGift[] stargift;
+ }
+
[TLDef(0x9021AB67)]
public sealed partial class Stickers_CreateStickerSet : IMethod
{
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 742ecad..1b55bf1 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 199; // fetched 13/02/2025 13:06:03
+ public const int Version = 200; // fetched 07/03/2025 23:09:37
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -124,7 +124,7 @@ namespace TL
[0x36C6019A] = typeof(PeerChat),
[0xA2A5371E] = typeof(PeerChannel),
[0xD3BC4B7A] = typeof(UserEmpty),
- [0x4B46C37E] = typeof(User),
+ [0x020B1422] = typeof(User),
[0x4F11BAE1] = null,//UserProfilePhotoEmpty
[0x82D1F706] = typeof(UserProfilePhoto),
[0x09D05049] = null,//UserStatusEmpty
@@ -136,7 +136,7 @@ namespace TL
[0x29562865] = typeof(ChatEmpty),
[0x41CBF256] = typeof(Chat),
[0x6592A1A7] = typeof(ChatForbidden),
- [0xE00998B7] = typeof(Channel),
+ [0x7482147E] = typeof(Channel),
[0x17D493D5] = typeof(ChannelForbidden),
[0x2633421B] = typeof(ChatFull),
[0x52D6806B] = typeof(ChannelFull),
@@ -148,7 +148,7 @@ namespace TL
[0x37C1011C] = null,//ChatPhotoEmpty
[0x1C6E1C11] = typeof(ChatPhoto),
[0x90A6CA84] = typeof(MessageEmpty),
- [0x96FDBBE9] = typeof(Message),
+ [0xEABCDD4D] = typeof(Message),
[0xD3D28540] = typeof(MessageService),
[0x3DED6320] = null,//MessageMediaEmpty
[0x695150D7] = typeof(MessageMediaPhoto),
@@ -239,10 +239,10 @@ namespace TL
[0x5C467992] = typeof(InputNotifyForumTopic),
[0xCACB6AE2] = typeof(InputPeerNotifySettings),
[0x99622C0C] = typeof(PeerNotifySettings),
- [0xACD66C5E] = typeof(PeerSettings),
+ [0xF47741F7] = typeof(PeerSettings),
[0xA437C3ED] = typeof(WallPaper),
[0xE0804116] = typeof(WallPaperNoFile),
- [0x4D975BBC] = typeof(UserFull),
+ [0xD2234EA0] = typeof(UserFull),
[0x145ADE0B] = typeof(Contact),
[0xC13E3C50] = typeof(ImportedContact),
[0x16D9703B] = typeof(ContactStatus),
@@ -1013,7 +1013,7 @@ namespace TL
[0xD7584C87] = typeof(StatsGroupTopAdmin),
[0x535F779D] = typeof(StatsGroupTopInviter),
[0xEF7FF916] = typeof(Stats_MegagroupStats),
- [0x734C4CCB] = typeof(GlobalPrivacySettings),
+ [0xC9D8DF1C] = typeof(GlobalPrivacySettings),
[0x4203C5EF] = typeof(Help_CountryCode),
[0xC3878E23] = typeof(Help_Country),
[0x93CC1F32] = null,//Help_CountriesListNotModified
@@ -1106,6 +1106,7 @@ namespace TL
[0xE8625E92] = typeof(InputInvoiceStarGift),
[0x4D818D5D] = typeof(InputInvoiceStarGiftUpgrade),
[0x4A5F5BD9] = typeof(InputInvoiceStarGiftTransfer),
+ [0xDABAB2EF] = typeof(InputInvoicePremiumGiftStars),
[0xAED0CBD9] = typeof(Payments_ExportedInvoice),
[0xCFB9D957] = typeof(Messages_TranscribedAudio),
[0x5334759C] = typeof(Help_PremiumPromo),
@@ -1116,7 +1117,6 @@ namespace TL
[0xDDDD0F56] = typeof(InputStorePaymentStarsTopup),
[0x1D741EF7] = typeof(InputStorePaymentStarsGift),
[0x751F08FA] = typeof(InputStorePaymentStarsGiveaway),
- [0x74C34319] = typeof(PremiumGiftOption),
[0x88F8F21B] = typeof(PaymentFormMethod),
[0x2DE11AAE] = null,//EmojiStatusEmpty
[0xE7FF068A] = typeof(EmojiStatus),
@@ -1324,7 +1324,7 @@ namespace TL
[0x60682812] = typeof(StarsTransactionPeerAds),
[0xF9677AAD] = typeof(StarsTransactionPeerAPI),
[0x0BD915C0] = typeof(StarsTopupOption),
- [0x64DFC926] = typeof(StarsTransaction),
+ [0xA39FD94A] = typeof(StarsTransaction),
[0x6C9CE8ED] = typeof(Payments_StarsStatus),
[0xE87ACBC0] = typeof(FoundStory),
[0xE2DE7737] = typeof(Stories_FoundStories),
@@ -1380,6 +1380,10 @@ namespace TL
[0x206AD49E] = null,//PaidReactionPrivacyDefault
[0x1F0C1AD9] = typeof(PaidReactionPrivacyAnonymous),
[0xDC6CFCF0] = typeof(PaidReactionPrivacyPeer),
+ [0x1E109708] = typeof(Account_PaidMessagesRevenue),
+ [0x050A9839] = null,//RequirementToContactEmpty
+ [0xE581E4E9] = typeof(RequirementToContactPremium),
+ [0xB4F67E93] = typeof(RequirementToContactPaidMessages),
// from TL.Secret:
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
[0x020DF5D0] = typeof(Layer101.MessageEntityBlockquote),
@@ -1511,6 +1515,7 @@ namespace TL
[typeof(Messages_AvailableEffects)] = 0xD1ED9A5B, //messages.availableEffectsNotModified
[typeof(Payments_StarGifts)] = 0xA388A368, //payments.starGiftsNotModified
[typeof(PaidReactionPrivacy)] = 0x206AD49E, //paidReactionPrivacyDefault
+ [typeof(RequirementToContact)] = 0x050A9839, //requirementToContactEmpty
[typeof(DecryptedMessageMedia)] = 0x089F5C4A, //decryptedMessageMediaEmpty
};
}
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index b54e320..dd5cdd1 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 199
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 200
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From 0867c044fa55e0d1fdeb1c20e6392a454f08d893 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Wed, 12 Mar 2025 02:17:36 +0100
Subject: [PATCH 09/68] Handle CONNECTION_NOT_INITED
---
.github/workflows/dev.yml | 2 +-
src/Client.cs | 44 ++++++++++++++++++++++++---------------
2 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index 6130d21..a30001c 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -47,7 +47,7 @@ jobs:
JSON: |
{
"status": "success", "complete": true, "commitMessage": ${{ toJSON(github.event.head_commit.message) }},
- "message": "{ \"commitId\": \"${{ github.event.head_commit.id }}\", \"buildNumber\": \"${{ env.VERSION }}\", \"teamProjectName\": \"${{ github.event.repository.name }}\"}"
+ "message": "{ \"commitId\": \"${{ github.sha }}\", \"buildNumber\": \"${{ env.VERSION }}\", \"repoName\": \"${{ github.repository }}\"}"
}
run: |
curl -X POST -H "Content-Type: application/json" -d "$JSON" ${{ secrets.DEPLOYED_WEBHOOK }}
diff --git a/src/Client.cs b/src/Client.cs
index fa172e6..2dc60d6 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -985,23 +985,7 @@ namespace WTelegram
else
{
if (_dcSession.Layer != 0 && _dcSession.Layer != Layer.Version) _dcSession.Renew();
- var initParams = JSONValue.FromJsonElement(System.Text.Json.JsonDocument.Parse(Config("init_params")).RootElement);
- TLConfig = await this.InvokeWithLayer(Layer.Version,
- new TL.Methods.InitConnection
- {
- flags = TL.Methods.InitConnection.Flags.has_params,
- api_id = _session.ApiId,
- device_model = Config("device_model"),
- system_version = Config("system_version"),
- app_version = Config("app_version"),
- system_lang_code = Config("system_lang_code"),
- lang_pack = Config("lang_pack"),
- lang_code = Config("lang_code"),
- params_ = initParams,
- query = new TL.Methods.Help_GetConfig()
- });
- _dcSession.Layer = Layer.Version;
- _session.DcOptions = TLConfig.dc_options;
+ await InitConnection();
if (_dcSession.DataCenter == null)
{
_dcSession.DataCenter = _session.DcOptions.Where(dc => dc.id == TLConfig.this_dc)
@@ -1022,6 +1006,27 @@ namespace WTelegram
Helpers.Log(2, $"Connected to {(TLConfig.test_mode ? "Test DC" : "DC")} {TLConfig.this_dc}... {TLConfig.flags & (Config.Flags)~0x18E00U}");
}
+ private async Task InitConnection()
+ {
+ var initParams = JSONValue.FromJsonElement(System.Text.Json.JsonDocument.Parse(Config("init_params")).RootElement);
+ TLConfig = await this.InvokeWithLayer(Layer.Version,
+ new TL.Methods.InitConnection
+ {
+ flags = TL.Methods.InitConnection.Flags.has_params,
+ api_id = _session.ApiId,
+ device_model = Config("device_model"),
+ system_version = Config("system_version"),
+ app_version = Config("app_version"),
+ system_lang_code = Config("system_lang_code"),
+ lang_pack = Config("lang_pack"),
+ lang_code = Config("lang_code"),
+ params_ = initParams,
+ query = new TL.Methods.Help_GetConfig()
+ });
+ _dcSession.Layer = Layer.Version;
+ _session.DcOptions = TLConfig.dc_options;
+ }
+
private async Task KeepAlive(CancellationToken ct)
{
int ping_id = _random.Next();
@@ -1615,6 +1620,11 @@ namespace WTelegram
got503 = true;
goto retry;
}
+ else if (code == 400 && message == "CONNECTION_NOT_INITED")
+ {
+ await InitConnection();
+ goto retry;
+ }
else if (code == 500 && message == "AUTH_RESTART")
{
_session.UserId = 0; // force a full login authorization flow, next time
From e6a4b802e719880a74f9d7ed615c793426b30c6b Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Sun, 23 Mar 2025 03:10:04 +0100
Subject: [PATCH 10/68] Html/Markdown: prune entities of length=0 (fix
wiz0u/WTelegramBot#6)
---
src/Services.cs | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/Services.cs b/src/Services.cs
index 99ce13b..d62b877 100644
--- a/src/Services.cs
+++ b/src/Services.cs
@@ -458,11 +458,13 @@ namespace TL
{
int newlen = sb.Length;
while (--newlen >= 0 && char.IsWhiteSpace(sb[newlen]));
- if (++newlen == sb.Length) return;
- sb.Length = newlen;
- foreach (var entity in entities)
- if (entity.offset + entity.length > newlen)
- entity.length = newlen - entity.offset;
+ if (++newlen != sb.Length) sb.Length = newlen;
+ for (int i = 0; i < entities.Count; i++)
+ {
+ var entity = entities[i];
+ if (entity.offset + entity.length > newlen) entity.length = newlen - entity.offset;
+ if (entity.length == 0) entities.RemoveAt(i--);
+ }
}
/// Converts the (plain text + entities) format used by Telegram messages into an HTML-formatted text
From 3f1d4eba921e0b0944d68f446588d9b5a993081e Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 27 Mar 2025 00:59:57 +0100
Subject: [PATCH 11/68] API Layer 201: Paid msg service messages, Gifts
settings, Business bot rights, sentCodePayment, sponsored peers ...
---
README.md | 2 +-
src/TL.Schema.cs | 134 ++++++++++++++++++++++++++++++++++---
src/TL.SchemaFuncs.cs | 77 +++++++++++----------
src/TL.Table.cs | 21 ++++--
src/WTelegramClient.csproj | 2 +-
5 files changed, 185 insertions(+), 51 deletions(-)
diff --git a/README.md b/README.md
index 47419e1..32a183d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 5caaf90..9a1af73 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -2946,6 +2946,19 @@ namespace TL
has_peer = 0x80,
}
}
+ /// See
+ [TLDef(0xAC1F1FCD)]
+ public sealed partial class MessageActionPaidMessagesRefunded : MessageAction
+ {
+ public int count;
+ public long stars;
+ }
+ /// See
+ [TLDef(0xBCD71419)]
+ public sealed partial class MessageActionPaidMessagesPrice : MessageAction
+ {
+ public long stars;
+ }
/// Chat info. See Derived classes: ,
public abstract partial class DialogBase : IObject
@@ -3225,6 +3238,13 @@ namespace TL
/// Authorization info
public Auth_AuthorizationBase authorization;
}
+ /// See
+ [TLDef(0xD7CEF980)]
+ public sealed partial class Auth_SentCodePaymentRequired : Auth_SentCodeBase
+ {
+ public string store_product;
+ public string phone_code_hash;
+ }
/// Object contains info on user authorization. See Derived classes: ,
public abstract partial class Auth_AuthorizationBase : IObject { }
@@ -3565,7 +3585,7 @@ namespace TL
}
/// Extended user info See
- [TLDef(0xD2234EA0)]
+ [TLDef(0x99E78045)]
public sealed partial class UserFull : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -3630,6 +3650,7 @@ namespace TL
[IfFlag(43)] public StarRefProgram starref_program;
[IfFlag(44)] public BotVerification bot_verification;
[IfFlag(46)] public long send_paid_messages_stars;
+ [IfFlag(47)] public DisallowedGiftsSettings disallowed_gifts;
[Flags] public enum Flags : uint
{
@@ -3719,6 +3740,9 @@ namespace TL
has_bot_verification = 0x1000,
/// Field has a value
has_send_paid_messages_stars = 0x4000,
+ /// Field has a value
+ has_disallowed_gifts = 0x8000,
+ display_gifts_button = 0x10000,
}
}
@@ -5788,6 +5812,12 @@ namespace TL
/// Whether paid reaction privacy is enabled or disabled.
public PaidReactionPrivacy private_;
}
+ /// See
+ [TLDef(0x504AA18F)]
+ public sealed partial class UpdateSentPhoneCode : Update
+ {
+ public Auth_SentCodeBase sent_code;
+ }
/// Updates state. See
[TLDef(0xA56C2A3E)]
@@ -14484,12 +14514,13 @@ namespace TL
}
/// Global privacy settings See
- [TLDef(0xC9D8DF1C)]
+ [TLDef(0xFE41B34F)]
public sealed partial class GlobalPrivacySettings : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[IfFlag(5)] public long noncontact_peers_paid_stars;
+ [IfFlag(6)] public DisallowedGiftsSettings disallowed_gifts;
[Flags] public enum Flags : uint
{
@@ -14505,6 +14536,9 @@ namespace TL
new_noncontact_peers_require_premium = 0x10,
/// Field has a value
has_noncontact_peers_paid_stars = 0x20,
+ /// Field has a value
+ has_disallowed_gifts = 0x40,
+ display_gifts_button = 0x80,
}
}
@@ -16118,6 +16152,21 @@ namespace TL
has_prize_description = 0x10,
}
}
+ /// See
+ [TLDef(0x9BB2636D)]
+ public sealed partial class InputStorePaymentAuthCode : InputStorePaymentPurpose
+ {
+ public Flags flags;
+ public string phone_number;
+ public string phone_code_hash;
+ public string currency;
+ public long amount;
+
+ [Flags] public enum Flags : uint
+ {
+ restore = 0x1,
+ }
+ }
/// Represents an additional payment method See
[TLDef(0x88F8F21B)]
@@ -18644,7 +18693,7 @@ namespace TL
}
/// Contains info about a connected business bot ». See
- [TLDef(0xBD068601)]
+ [TLDef(0xCD64636C)]
public sealed partial class ConnectedBot : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -18653,11 +18702,10 @@ namespace TL
public long bot_id;
/// Specifies the private chats that a connected business bot » may receive messages and interact with.
public BusinessBotRecipients recipients;
+ public BusinessBotRights rights;
[Flags] public enum Flags : uint
{
- /// Whether the the bot can reply to messages it receives through the connection
- can_reply = 0x1,
}
}
@@ -18708,7 +18756,7 @@ namespace TL
}
/// Contains info about a bot business connection. See
- [TLDef(0x896433B4)]
+ [TLDef(0x8F34B2F5)]
public sealed partial class BotBusinessConnection : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -18721,13 +18769,14 @@ namespace TL
public int dc_id;
/// When was the connection created.
public DateTime date;
+ [IfFlag(2)] public BusinessBotRights rights;
[Flags] public enum Flags : uint
{
- /// Whether the bot can reply on behalf of the user to messages it receives through the business connection
- can_reply = 0x1,
/// Whether this business connection is currently disabled
disabled = 0x2,
+ /// Field has a value
+ has_rights = 0x4,
}
}
@@ -20365,4 +20414,73 @@ namespace TL
{
public long stars_amount;
}
+
+ /// See
+ [TLDef(0xA0624CF7)]
+ public sealed partial class BusinessBotRights : IObject
+ {
+ public Flags flags;
+
+ [Flags] public enum Flags : uint
+ {
+ reply = 0x1,
+ read_messages = 0x2,
+ delete_sent_messages = 0x4,
+ delete_received_messages = 0x8,
+ edit_name = 0x10,
+ edit_bio = 0x20,
+ edit_profile_photo = 0x40,
+ edit_username = 0x80,
+ view_gifts = 0x100,
+ sell_gifts = 0x200,
+ change_gift_settings = 0x400,
+ transfer_and_upgrade_gifts = 0x800,
+ transfer_stars = 0x1000,
+ manage_stories = 0x2000,
+ }
+ }
+
+ /// See
+ [TLDef(0x71F276C4)]
+ public sealed partial class DisallowedGiftsSettings : IObject
+ {
+ public Flags flags;
+
+ [Flags] public enum Flags : uint
+ {
+ disallow_unlimited_stargifts = 0x1,
+ disallow_limited_stargifts = 0x2,
+ disallow_unique_stargifts = 0x4,
+ disallow_premium_gifts = 0x8,
+ }
+ }
+
+ /// See
+ [TLDef(0xC69708D3)]
+ public sealed partial class SponsoredPeer : IObject
+ {
+ public Flags flags;
+ public byte[] random_id;
+ public Peer peer;
+ [IfFlag(0)] public string sponsor_info;
+ [IfFlag(1)] public string additional_info;
+
+ [Flags] public enum Flags : uint
+ {
+ has_sponsor_info = 0x1,
+ has_additional_info = 0x2,
+ }
+ }
+
+ /// See
+ /// a value means contacts.sponsoredPeersEmpty
+ [TLDef(0xEB032884)]
+ public sealed partial class Contacts_SponsoredPeers : IObject, IPeerResolver
+ {
+ public SponsoredPeer[] peers;
+ public Dictionary chats;
+ public Dictionary users;
+ /// returns a or for the given Peer
+ public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 004175d..aa0b3db 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1293,14 +1293,14 @@ namespace TL
});
/// Connect a business bot » to the current account, or to change the current connection settings. See Possible codes: 400,403 (details)
- /// Whether the bot can reply to messages it receives from us, on behalf of us using the business connection.
/// Whether to fully disconnect the bot from the current account.
/// The bot to connect or disconnect
/// Configuration for the business connection
- public static Task Account_UpdateConnectedBot(this Client client, InputUserBase bot, InputBusinessBotRecipients recipients, bool can_reply = false, bool deleted = false)
+ public static Task Account_UpdateConnectedBot(this Client client, InputUserBase bot, InputBusinessBotRecipients recipients, BusinessBotRights rights = null, bool deleted = false)
=> client.Invoke(new Account_UpdateConnectedBot
{
- flags = (Account_UpdateConnectedBot.Flags)((can_reply ? 0x1 : 0) | (deleted ? 0x2 : 0)),
+ flags = (Account_UpdateConnectedBot.Flags)((rights != null ? 0x1 : 0) | (deleted ? 0x2 : 0)),
+ rights = rights,
bot = bot,
recipients = recipients,
});
@@ -1730,6 +1730,14 @@ namespace TL
{
});
+ /// See
+ /// a null value means contacts.sponsoredPeersEmpty
+ public static Task Contacts_GetSponsoredPeers(this Client client, string q)
+ => client.Invoke(new Contacts_GetSponsoredPeers
+ {
+ q = q,
+ });
+
/// ⚠ This method is only for basic Chat. See Terminology in the README to understand what this means
Search for a similar method name starting with Channels_ if you're dealing with a Returns the list of messages by their IDs. See [bots: ✓]
/// Message ID list
public static Task Messages_GetMessages(this Client client, params InputMessage[] id)
@@ -2424,7 +2432,7 @@ namespace TL
unsave = unsave,
});
- /// Query an inline bot See Possible codes: 400,406,-503 (details)
+ /// Query an inline bot See Possible codes: -503,400,406 (details)
/// The bot to query
/// The currently opened chat
/// The geolocation, if requested
@@ -2544,7 +2552,7 @@ namespace TL
entities = entities,
});
- /// Press an inline callback button and get a callback answer from the bot See Possible codes: 400,-503 (details)
+ /// Press an inline callback button and get a callback answer from the bot See Possible codes: -503,400 (details)
/// Whether this is a "play game" button
/// Where was the inline keyboard sent
/// ID of the Message with the inline keyboard
@@ -4399,36 +4407,30 @@ namespace TL
});
/// Mark a specific sponsored message » as read See
- /// The channel/bot where the ad is located
/// The ad's unique ID.
- public static Task Messages_ViewSponsoredMessage(this Client client, InputPeer peer, byte[] random_id)
+ public static Task Messages_ViewSponsoredMessage(this Client client, byte[] random_id)
=> client.Invoke(new Messages_ViewSponsoredMessage
{
- peer = peer,
random_id = random_id,
});
/// Informs the server that the user has interacted with a sponsored message in one of the ways listed here ». See
/// The user clicked on the media
/// The user expanded the video to full screen, and then clicked on it.
- /// The channel/bot where the ad is located
/// The ad's unique ID.
- public static Task Messages_ClickSponsoredMessage(this Client client, InputPeer peer, byte[] random_id, bool media = false, bool fullscreen = false)
+ public static Task Messages_ClickSponsoredMessage(this Client client, byte[] random_id, bool media = false, bool fullscreen = false)
=> client.Invoke(new Messages_ClickSponsoredMessage
{
flags = (Messages_ClickSponsoredMessage.Flags)((media ? 0x1 : 0) | (fullscreen ? 0x2 : 0)),
- peer = peer,
random_id = random_id,
});
/// Report a sponsored message », see here » for more info on the full flow. See
- /// The channel/bot where the ad is located
/// The ad's unique ID.
/// Chosen report option, initially an empty string, see here » for more info on the full flow.
- public static Task Messages_ReportSponsoredMessage(this Client client, InputPeer peer, byte[] random_id, byte[] option)
+ public static Task Messages_ReportSponsoredMessage(this Client client, byte[] random_id, byte[] option)
=> client.Invoke(new Messages_ReportSponsoredMessage
{
- peer = peer,
random_id = random_id,
option = option,
});
@@ -5999,14 +6001,6 @@ namespace TL
purpose = purpose,
});
- /// Checks whether Telegram Premium purchase is possible. Must be called before in-store Premium purchase, official apps only. See Possible codes: 406 (details)
- /// Payment purpose
- public static Task Payments_CanPurchasePremium(this Client client, InputStorePaymentPurpose purpose)
- => client.Invoke(new Payments_CanPurchasePremium
- {
- purpose = purpose,
- });
-
/// Obtain a list of Telegram Premium giveaway/gift code » options. See
/// The channel that will start the giveaway
public static Task Payments_GetPremiumGiftCodeOptions(this Client client, InputPeer boost_peer = null)
@@ -6366,6 +6360,13 @@ namespace TL
stargift = stargift,
});
+ /// See
+ public static Task Payments_CanPurchaseStore(this Client client, InputStorePaymentPurpose purpose)
+ => client.Invoke(new Payments_CanPurchaseStore
+ {
+ purpose = purpose,
+ });
+
/// Create a stickerset. See [bots: ✓] Possible codes: 400 (details)
/// Whether this is a mask stickerset
/// Whether this is a custom emoji stickerset.
@@ -8583,16 +8584,17 @@ namespace TL.Methods
}
}
- [TLDef(0x43D8521D)]
+ [TLDef(0x66A08C7E)]
public sealed partial class Account_UpdateConnectedBot : IMethod
{
public Flags flags;
+ [IfFlag(0)] public BusinessBotRights rights;
public InputUserBase bot;
public InputBusinessBotRecipients recipients;
[Flags] public enum Flags : uint
{
- can_reply = 0x1,
+ has_rights = 0x1,
deleted = 0x2,
}
}
@@ -8958,6 +8960,12 @@ namespace TL.Methods
[TLDef(0xDAEDA864)]
public sealed partial class Contacts_GetBirthdays : IMethod { }
+ [TLDef(0xB6C8C393)]
+ public sealed partial class Contacts_GetSponsoredPeers : IMethod
+ {
+ public string q;
+ }
+
[TLDef(0x63C66506)]
public sealed partial class Messages_GetMessages : IMethod
{
@@ -11238,18 +11246,16 @@ namespace TL.Methods
[TLDef(0x472455AA)]
public sealed partial class Messages_GetPaidReactionPrivacy : IMethod { }
- [TLDef(0x673AD8F1)]
+ [TLDef(0x269E3643)]
public sealed partial class Messages_ViewSponsoredMessage : IMethod
{
- public InputPeer peer;
public byte[] random_id;
}
- [TLDef(0x0F093465)]
+ [TLDef(0x8235057E)]
public sealed partial class Messages_ClickSponsoredMessage : IMethod
{
public Flags flags;
- public InputPeer peer;
public byte[] random_id;
[Flags] public enum Flags : uint
@@ -11259,10 +11265,9 @@ namespace TL.Methods
}
}
- [TLDef(0x1AF3DBB8)]
+ [TLDef(0x12CBF0C4)]
public sealed partial class Messages_ReportSponsoredMessage : IMethod
{
- public InputPeer peer;
public byte[] random_id;
public byte[] option;
}
@@ -12507,12 +12512,6 @@ namespace TL.Methods
public InputStorePaymentPurpose purpose;
}
- [TLDef(0x9FC19EB6)]
- public sealed partial class Payments_CanPurchasePremium : IMethod
- {
- public InputStorePaymentPurpose purpose;
- }
-
[TLDef(0x2757BA54)]
public sealed partial class Payments_GetPremiumGiftCodeOptions : IMethod
{
@@ -12851,6 +12850,12 @@ namespace TL.Methods
public InputSavedStarGift[] stargift;
}
+ [TLDef(0x4FDC5EA7)]
+ public sealed partial class Payments_CanPurchaseStore : IMethod
+ {
+ public InputStorePaymentPurpose purpose;
+ }
+
[TLDef(0x9021AB67)]
public sealed partial class Stickers_CreateStickerSet : IMethod
{
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 1b55bf1..e441650 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 200; // fetched 07/03/2025 23:09:37
+ public const int Version = 201; // fetched 26/03/2025 23:35:58
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -215,6 +215,8 @@ namespace TL
[0xB00C47A2] = typeof(MessageActionPrizeStars),
[0x4717E8A4] = typeof(MessageActionStarGift),
[0xACDFCB81] = typeof(MessageActionStarGiftUnique),
+ [0xAC1F1FCD] = typeof(MessageActionPaidMessagesRefunded),
+ [0xBCD71419] = typeof(MessageActionPaidMessagesPrice),
[0xD58A08C6] = typeof(Dialog),
[0x71BD134C] = typeof(DialogFolder),
[0x2331B22D] = typeof(PhotoEmpty),
@@ -229,6 +231,7 @@ namespace TL
[0xB2A2F663] = typeof(GeoPoint),
[0x5E002502] = typeof(Auth_SentCode),
[0x2390FE44] = typeof(Auth_SentCodeSuccess),
+ [0xD7CEF980] = typeof(Auth_SentCodePaymentRequired),
[0x2EA2C0D4] = typeof(Auth_Authorization),
[0x44747E9A] = typeof(Auth_AuthorizationSignUpRequired),
[0xB434E2B8] = typeof(Auth_ExportedAuthorization),
@@ -242,7 +245,7 @@ namespace TL
[0xF47741F7] = typeof(PeerSettings),
[0xA437C3ED] = typeof(WallPaper),
[0xE0804116] = typeof(WallPaperNoFile),
- [0xD2234EA0] = typeof(UserFull),
+ [0x99E78045] = typeof(UserFull),
[0x145ADE0B] = typeof(Contact),
[0xC13E3C50] = typeof(ImportedContact),
[0x16D9703B] = typeof(ContactStatus),
@@ -420,6 +423,7 @@ namespace TL
[0xA584B019] = typeof(UpdateStarsRevenueStatus),
[0x283BD312] = typeof(UpdateBotPurchasedPaidMedia),
[0x8B725FCE] = typeof(UpdatePaidReactionPrivacy),
+ [0x504AA18F] = typeof(UpdateSentPhoneCode),
[0xA56C2A3E] = typeof(Updates_State),
[0x5D75A138] = typeof(Updates_DifferenceEmpty),
[0x00F49CA0] = typeof(Updates_Difference),
@@ -1013,7 +1017,7 @@ namespace TL
[0xD7584C87] = typeof(StatsGroupTopAdmin),
[0x535F779D] = typeof(StatsGroupTopInviter),
[0xEF7FF916] = typeof(Stats_MegagroupStats),
- [0xC9D8DF1C] = typeof(GlobalPrivacySettings),
+ [0xFE41B34F] = typeof(GlobalPrivacySettings),
[0x4203C5EF] = typeof(Help_CountryCode),
[0xC3878E23] = typeof(Help_Country),
[0x93CC1F32] = null,//Help_CountriesListNotModified
@@ -1117,6 +1121,7 @@ namespace TL
[0xDDDD0F56] = typeof(InputStorePaymentStarsTopup),
[0x1D741EF7] = typeof(InputStorePaymentStarsGift),
[0x751F08FA] = typeof(InputStorePaymentStarsGiveaway),
+ [0x9BB2636D] = typeof(InputStorePaymentAuthCode),
[0x88F8F21B] = typeof(PaymentFormMethod),
[0x2DE11AAE] = null,//EmojiStatusEmpty
[0xE7FF068A] = typeof(EmojiStatus),
@@ -1275,11 +1280,11 @@ namespace TL
[0x01190CF1] = typeof(InputQuickReplyShortcutId),
[0xC68D6695] = typeof(Messages_QuickReplies),
[0x5F91EB5B] = null,//Messages_QuickRepliesNotModified
- [0xBD068601] = typeof(ConnectedBot),
+ [0xCD64636C] = typeof(ConnectedBot),
[0x17D7F87B] = typeof(Account_ConnectedBots),
[0x2AD93719] = typeof(Messages_DialogFilters),
[0x6C8E1E06] = typeof(Birthday),
- [0x896433B4] = typeof(BotBusinessConnection),
+ [0x8F34B2F5] = typeof(BotBusinessConnection),
[0x09C469CD] = typeof(InputBusinessIntro),
[0x5A0A066D] = typeof(BusinessIntro),
[0xFAFF629D] = typeof(Messages_MyStickers),
@@ -1384,6 +1389,11 @@ namespace TL
[0x050A9839] = null,//RequirementToContactEmpty
[0xE581E4E9] = typeof(RequirementToContactPremium),
[0xB4F67E93] = typeof(RequirementToContactPaidMessages),
+ [0xA0624CF7] = typeof(BusinessBotRights),
+ [0x71F276C4] = typeof(DisallowedGiftsSettings),
+ [0xC69708D3] = typeof(SponsoredPeer),
+ [0xEA32B4B1] = null,//Contacts_SponsoredPeersEmpty
+ [0xEB032884] = typeof(Contacts_SponsoredPeers),
// from TL.Secret:
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
[0x020DF5D0] = typeof(Layer101.MessageEntityBlockquote),
@@ -1516,6 +1526,7 @@ namespace TL
[typeof(Payments_StarGifts)] = 0xA388A368, //payments.starGiftsNotModified
[typeof(PaidReactionPrivacy)] = 0x206AD49E, //paidReactionPrivacyDefault
[typeof(RequirementToContact)] = 0x050A9839, //requirementToContactEmpty
+ [typeof(Contacts_SponsoredPeers)] = 0xEA32B4B1, //contacts.sponsoredPeersEmpty
[typeof(DecryptedMessageMedia)] = 0x089F5C4A, //decryptedMessageMediaEmpty
};
}
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index dd5cdd1..1debd31 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 200
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 201
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From f495f59bc88c1d690a673b117e10205163bf1cdc Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Wed, 2 Apr 2025 05:58:04 +0200
Subject: [PATCH 12/68] Use media DC for uploads
---
src/Client.Helpers.cs | 5 +++--
src/Client.cs | 2 +-
src/TL.Xtended.cs | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/Client.Helpers.cs b/src/Client.Helpers.cs
index 25124ea..eefcd36 100644
--- a/src/Client.Helpers.cs
+++ b/src/Client.Helpers.cs
@@ -33,6 +33,7 @@ namespace WTelegram
/// an or than can be used in various requests
public async Task UploadFileAsync(Stream stream, string filename, ProgressCallback progress = null)
{
+ var client = await GetClientForDC(-_dcSession.DcID, true);
using (stream)
{
bool hasLength = stream.CanSeek;
@@ -65,9 +66,9 @@ namespace WTelegram
try
{
if (isBig)
- await this.Upload_SaveBigFilePart(file_id, file_part, file_total_parts, bytes);
+ await client.Upload_SaveBigFilePart(file_id, file_part, file_total_parts, bytes);
else
- await this.Upload_SaveFilePart(file_id, file_part, bytes);
+ await client.Upload_SaveFilePart(file_id, file_part, bytes);
lock (tasks) { transmitted += bytes.Length; tasks.Remove(file_part); }
progress?.Invoke(transmitted, length);
}
diff --git a/src/Client.cs b/src/Client.cs
index 2dc60d6..29d50b7 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -312,7 +312,7 @@ namespace WTelegram
try
{
Auth_ExportedAuthorization exported = null;
- if (_session.UserId != 0 && IsMainDC && altSession.UserId != _session.UserId)
+ if (_session.UserId != 0 && IsMainDC && altSession.UserId != _session.UserId && altSession.DcID != _dcSession.DcID)
exported = await this.Auth_ExportAuthorization(Math.Abs(dcId));
await altSession.Client.ConnectAsync();
if (exported != null)
diff --git a/src/TL.Xtended.cs b/src/TL.Xtended.cs
index 7b36f1d..30a2c39 100644
--- a/src/TL.Xtended.cs
+++ b/src/TL.Xtended.cs
@@ -525,7 +525,7 @@ namespace TL
partial class Document
{
public override long ID => id;
- public override string ToString() => Filename is string filename ? base.ToString() + ": " + filename : base.ToString();
+ public override string ToString() => $"{Filename ?? $"Document {mime_type}"} {size:N0} bytes";
public string Filename => GetAttribute()?.file_name;
protected override InputDocument ToInputDocument() => new() { id = id, access_hash = access_hash, file_reference = file_reference };
public InputDocumentFileLocation ToFileLocation(PhotoSizeBase thumbSize = null) => new() { id = id, access_hash = access_hash, file_reference = file_reference, thumb_size = thumbSize?.Type };
From 6d238dc528e28e490f877ccedb722774ca91d6ea Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Sun, 6 Apr 2025 19:48:43 +0200
Subject: [PATCH 13/68] Store less stuff in session data and reduce save
frequency for better performance.
---
Examples/Program_Heroku.cs | 22 +++-------
src/Client.cs | 88 ++++++++++++++++++++------------------
src/Encryption.cs | 8 ++--
src/Session.cs | 19 ++++----
4 files changed, 67 insertions(+), 70 deletions(-)
diff --git a/Examples/Program_Heroku.cs b/Examples/Program_Heroku.cs
index 5ae5fe7..4ad3740 100644
--- a/Examples/Program_Heroku.cs
+++ b/Examples/Program_Heroku.cs
@@ -62,10 +62,8 @@ namespace WTelegramClientTest
{
private readonly NpgsqlConnection _sql;
private readonly string _sessionName;
- private byte[] _data;
- private int _dataLen;
- private DateTime _lastWrite;
- private Task _delayedWrite;
+ private readonly byte[] _data;
+ private readonly int _dataLen;
/// Heroku DB URL of the form "postgres://user:password@host:port/database"
/// Entry name for the session data in the WTelegram_sessions table (default: "Heroku")
@@ -85,7 +83,6 @@ namespace WTelegramClientTest
protected override void Dispose(bool disposing)
{
- _delayedWrite?.Wait();
_sql.Dispose();
}
@@ -97,18 +94,9 @@ namespace WTelegramClientTest
public override void Write(byte[] buffer, int offset, int count) // Write call and buffer modifications are done within a lock()
{
- _data = buffer; _dataLen = count;
- if (_delayedWrite != null) return;
- var left = 1000 - (int)(DateTime.UtcNow - _lastWrite).TotalMilliseconds;
- if (left < 0)
- {
- using var cmd = new NpgsqlCommand($"INSERT INTO WTelegram_sessions (name, data) VALUES ('{_sessionName}', @data) ON CONFLICT (name) DO UPDATE SET data = EXCLUDED.data", _sql);
- cmd.Parameters.AddWithValue("data", count == buffer.Length ? buffer : buffer[offset..(offset + count)]);
- cmd.ExecuteNonQuery();
- _lastWrite = DateTime.UtcNow;
- }
- else // delay writings for a full second
- _delayedWrite = Task.Delay(left).ContinueWith(t => { lock (this) { _delayedWrite = null; Write(_data, 0, _dataLen); } });
+ using var cmd = new NpgsqlCommand($"INSERT INTO WTelegram_sessions (name, data) VALUES ('{_sessionName}', @data) ON CONFLICT (name) DO UPDATE SET data = EXCLUDED.data", _sql);
+ cmd.Parameters.AddWithValue("data", count == buffer.Length ? buffer : buffer[offset..(offset + count)]);
+ cmd.ExecuteNonQuery();
}
public override long Length => _dataLen;
diff --git a/src/Client.cs b/src/Client.cs
index 29d50b7..74e0b7a 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -115,7 +115,7 @@ namespace WTelegram
_session = Session.LoadOrCreate(sessionStore, Convert.FromHexString(session_key));
if (_session.ApiId == 0) _session.ApiId = int.Parse(Config("api_id"));
if (_session.MainDC != 0) _session.DCSessions.TryGetValue(_session.MainDC, out _dcSession);
- _dcSession ??= new() { Id = Helpers.RandomLong() };
+ _dcSession ??= new();
_dcSession.Client = this;
var version = Assembly.GetExecutingAssembly().GetCustomAttribute().InformationalVersion;
Helpers.Log(1, $"WTelegramClient {version} running under {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}");
@@ -272,8 +272,8 @@ namespace WTelegram
// we have already negociated an AuthKey with this DC
if (dcSession.DataCenter.flags == flags && _session.DCSessions.Remove(-dcId))
return _session.DCSessions[dcId] = dcSession; // we found a misclassed DC, change its sign
- dcSession = new Session.DCSession { Id = Helpers.RandomLong(), // clone AuthKey for a session on the matching media_only DC
- AuthKeyID = dcSession.AuthKeyID, AuthKey = dcSession.AuthKey, UserId = dcSession.UserId };
+ dcSession = new Session.DCSession { // clone AuthKey for a session on the matching media_only DC
+ authKeyID = dcSession.authKeyID, AuthKey = dcSession.AuthKey, UserId = dcSession.UserId };
}
// try to find the most appropriate DcOption for this DC
if (dcSession?.AuthKey == null) // we'll need to negociate an AuthKey => can't use media_only DC
@@ -283,7 +283,7 @@ namespace WTelegram
}
var dcOptions = GetDcOptions(Math.Abs(dcId), flags);
var dcOption = dcOptions.FirstOrDefault() ?? throw new WTException($"Could not find adequate dc_option for DC {dcId}");
- dcSession ??= new Session.DCSession { Id = Helpers.RandomLong() }; // create new session only if not already existing
+ dcSession ??= new(); // create new session only if not already existing
dcSession.DataCenter = dcOption;
return _session.DCSessions[dcId] = dcSession;
}
@@ -302,6 +302,7 @@ namespace WTelegram
var flags = _dcSession.DataCenter.flags;
if (dcId < 0) flags = (flags & DcOption.Flags.ipv6) | DcOption.Flags.media_only;
altSession = GetOrCreateDCSession(dcId, flags);
+ _session.Save();
if (altSession.Client?.Disconnected ?? false) { altSession.Client.Dispose(); altSession.Client = null; }
altSession.Client ??= new Client(this, altSession);
}
@@ -321,6 +322,7 @@ namespace WTelegram
if (authorization is not Auth_Authorization { user: User user })
throw new WTException("Failed to get Authorization: " + authorization.GetType().Name);
altSession.UserId = user.id;
+ lock (_session) _session.Save();
}
}
finally
@@ -419,7 +421,7 @@ namespace WTelegram
}
internal DateTime MsgIdToStamp(long serverMsgId)
- => new((serverMsgId >> 32) * 10000000 - _dcSession.ServerTicksOffset + 621355968000000000L, DateTimeKind.Utc);
+ => new((serverMsgId >> 32) * 10000000 - _dcSession.serverTicksOffset + 621355968000000000L, DateTimeKind.Utc);
internal IObject ReadFrame(byte[] data, int dataLen)
{
@@ -432,7 +434,7 @@ namespace WTelegram
throw new WTException($"Packet payload too small: {dataLen}");
long authKeyId = BinaryPrimitives.ReadInt64LittleEndian(data);
- if (authKeyId != _dcSession.AuthKeyID)
+ if (authKeyId != _dcSession.authKeyID)
throw new WTException($"Received a packet encrypted with unexpected key {authKeyId:X}");
if (authKeyId == 0) // Unencrypted message
{
@@ -468,7 +470,7 @@ namespace WTelegram
if (length < 0 || length % 4 != 0) throw new WTException($"Invalid message_data_length: {length}");
if (decrypted_data.Length - 32 - length is < 12 or > 1024) throw new WTException($"Invalid message padding length: {decrypted_data.Length - 32}-{length}");
- if (sessionId != _dcSession.Id) throw new WTException($"Unexpected session ID: {sessionId} != {_dcSession.Id}");
+ if (sessionId != _dcSession.id) throw new WTException($"Unexpected session ID: {sessionId} != {_dcSession.id}");
if ((msgId & 1) == 0) throw new WTException($"msg_id is not odd: {msgId}");
if (!_dcSession.CheckNewMsgId(msgId))
{
@@ -477,19 +479,20 @@ namespace WTelegram
}
var utcNow = DateTime.UtcNow;
if (_lastRecvMsgId == 0) // resync ServerTicksOffset on first message
- _dcSession.ServerTicksOffset = (msgId >> 32) * 10000000 - utcNow.Ticks + 621355968000000000L;
+ _dcSession.serverTicksOffset = (msgId >> 32) * 10000000 - utcNow.Ticks + 621355968000000000L;
var msgStamp = MsgIdToStamp(_lastRecvMsgId = msgId);
long deltaTicks = (msgStamp - utcNow).Ticks;
if (deltaTicks is > 0)
if (deltaTicks < Ticks5Secs) // resync if next message is less than 5 seconds in the future
- _dcSession.ServerTicksOffset += deltaTicks;
- else if (_dcSession.ServerTicksOffset < -Ticks5Secs && deltaTicks + _dcSession.ServerTicksOffset < 0)
- _dcSession.ServerTicksOffset += deltaTicks;
+ _dcSession.serverTicksOffset += deltaTicks;
+ else if (_dcSession.serverTicksOffset < -Ticks5Secs && deltaTicks + _dcSession.serverTicksOffset < 0)
+ _dcSession.serverTicksOffset += deltaTicks;
if (serverSalt != _dcSession.Salt && serverSalt != _dcSession.OldSalt && serverSalt != _dcSession.Salts?.Values.ElementAtOrDefault(1))
{
Helpers.Log(3, $"{_dcSession.DcID}>Server salt has changed: {_dcSession.Salt:X} -> {serverSalt:X}");
_dcSession.OldSalt = _dcSession.Salt;
_dcSession.Salt = serverSalt;
+ lock (_session) _session.Save();
if (++_saltChangeCounter >= 10)
throw new WTException("Server salt changed too often! Security issue?");
CheckSalt();
@@ -499,7 +502,7 @@ namespace WTelegram
var ctorNb = reader.ReadUInt32();
if (ctorNb != Layer.BadMsgCtor && deltaTicks / TimeSpan.TicksPerSecond is > 30 or < -300)
{ // msg_id values that belong over 30 seconds in the future or over 300 seconds in the past are to be ignored.
- Helpers.Log(1, $"{_dcSession.DcID}>Ignoring 0x{ctorNb:X8} because of wrong timestamp {msgStamp:u} - {utcNow:u} Δ={new TimeSpan(_dcSession.ServerTicksOffset):c}");
+ Helpers.Log(1, $"{_dcSession.DcID}>Ignoring 0x{ctorNb:X8} because of wrong timestamp {msgStamp:u} - {utcNow:u} Δ={new TimeSpan(_dcSession.serverTicksOffset):c}");
return null;
}
try
@@ -546,9 +549,11 @@ namespace WTelegram
{
var keys = _dcSession.Salts.Keys;
if (keys[^1] == DateTime.MaxValue) return; // GetFutureSalts ongoing
- var now = DateTime.UtcNow.AddTicks(_dcSession.ServerTicksOffset);
- for (; keys.Count > 1 && keys[1] < now; _dcSession.OldSalt = _dcSession.Salt, _dcSession.Salt = _dcSession.Salts.Values[0])
+ var now = DateTime.UtcNow.AddTicks(_dcSession.serverTicksOffset);
+ bool removed = false;
+ for (; keys.Count > 1 && keys[1] < now; _dcSession.OldSalt = _dcSession.Salt, _dcSession.Salt = _dcSession.Salts.Values[0], removed = true)
_dcSession.Salts.RemoveAt(0);
+ if (removed) _session.Save();
if (_dcSession.Salts.Count > 48) return;
}
_dcSession.Salts[DateTime.MaxValue] = 0;
@@ -694,7 +699,7 @@ namespace WTelegram
rpc.tcs.SetResult(obj);
return;
}
- else if (_dcSession.AuthKeyID == 0)
+ else if (_dcSession.authKeyID == 0)
throw new WTException($"Received a {obj.GetType()} incompatible with expected bare {rpc?.type}");
lock (_pendingRpcs)
_pendingRpcs[_bareRpc.msgId] = _bareRpc;
@@ -726,7 +731,7 @@ namespace WTelegram
break; // we don't do anything with these, for now
case BadMsgNotification badMsgNotification:
await _sendSemaphore.WaitAsync();
- bool retryLast = badMsgNotification.bad_msg_id == _dcSession.LastSentMsgId;
+ bool retryLast = badMsgNotification.bad_msg_id == _dcSession.lastSentMsgId;
var lastSentMsg = _lastSentMsg;
_sendSemaphore.Release();
var logLevel = badMsgNotification.error_code == 48 ? 2 : 4;
@@ -735,14 +740,14 @@ namespace WTelegram
{
case 16: // msg_id too low (most likely, client time is wrong; synchronize it using msg_id notifications and re-send the original message)
case 17: // msg_id too high (similar to the previous case, the client time has to be synchronized, and the message re-sent with the correct msg_id)
- _dcSession.LastSentMsgId = 0;
+ _dcSession.lastSentMsgId = 0;
var localTime = DateTime.UtcNow;
- _dcSession.ServerTicksOffset = (_lastRecvMsgId >> 32) * 10000000 - localTime.Ticks + 621355968000000000L;
- Helpers.Log(1, $"Time offset: {_dcSession.ServerTicksOffset} | Server: {MsgIdToStamp(_lastRecvMsgId).AddTicks(_dcSession.ServerTicksOffset).TimeOfDay} UTC | Local: {localTime.TimeOfDay} UTC");
+ _dcSession.serverTicksOffset = (_lastRecvMsgId >> 32) * 10000000 - localTime.Ticks + 621355968000000000L;
+ Helpers.Log(1, $"Time offset: {_dcSession.serverTicksOffset} | Server: {MsgIdToStamp(_lastRecvMsgId).AddTicks(_dcSession.serverTicksOffset).TimeOfDay} UTC | Local: {localTime.TimeOfDay} UTC");
break;
case 32: // msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)
case 33: // msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)
- if (_dcSession.Seqno <= 1)
+ if (_dcSession.seqno <= 1)
retryLast = false;
else
{
@@ -754,6 +759,7 @@ namespace WTelegram
case 48: // incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)
_dcSession.OldSalt = _dcSession.Salt;
_dcSession.Salt = ((BadServerSalt)badMsgNotification).new_server_salt;
+ lock (_session) _session.Save();
CheckSalt();
break;
default:
@@ -942,7 +948,7 @@ namespace WTelegram
// is it address for a known DCSession?
_dcSession = _session.DCSessions.Values.FirstOrDefault(dcs => dcs.EndPoint.Equals(endpoint));
if (defaultDc != 0) _dcSession ??= _session.DCSessions.GetValueOrDefault(defaultDc);
- _dcSession ??= new() { Id = Helpers.RandomLong() };
+ _dcSession ??= new();
_dcSession.Client = this;
_dcSession.DataCenter = null;
Helpers.Log(2, $"Connecting to {endpoint}...");
@@ -976,7 +982,7 @@ namespace WTelegram
try
{
- if (_dcSession.AuthKeyID == 0)
+ if (_dcSession.authKeyID == 0)
await CreateAuthorizationKey(this, _dcSession);
if (_networkStream != null) _ = KeepAlive(_cts.Token);
@@ -1125,6 +1131,7 @@ namespace WTelegram
if (self.id == long.Parse(botToken.Split(':')[0]))
{
_session.UserId = _dcSession.UserId = self.id;
+ lock (_session) _session.Save();
RaiseUpdates(self);
return User = self;
}
@@ -1164,6 +1171,7 @@ namespace WTelegram
self.phone == string.Concat((phone_number = Config("phone_number")).Where(char.IsDigit)))
{
_session.UserId = _dcSession.UserId = self.id;
+ lock (_session) _session.Save();
RaiseUpdates(self);
return User = self;
}
@@ -1420,21 +1428,17 @@ namespace WTelegram
internal (long msgId, int seqno) NewMsgId(bool isContent)
{
int seqno;
- long msgId = DateTime.UtcNow.Ticks + _dcSession.ServerTicksOffset - 621355968000000000L;
+ long msgId = DateTime.UtcNow.Ticks + _dcSession.serverTicksOffset - 621355968000000000L;
msgId = msgId * 428 + (msgId >> 24) * 25110956; // approximately unixtime*2^32 and divisible by 4
- lock (_session)
- {
- if (msgId <= _dcSession.LastSentMsgId) msgId = _dcSession.LastSentMsgId += 4; else _dcSession.LastSentMsgId = msgId;
- seqno = isContent ? _dcSession.Seqno++ * 2 + 1 : _dcSession.Seqno * 2;
- _session.Save();
- }
+ if (msgId <= _dcSession.lastSentMsgId) msgId = _dcSession.lastSentMsgId += 4; else _dcSession.lastSentMsgId = msgId;
+ seqno = isContent ? _dcSession.seqno++ * 2 + 1 : _dcSession.seqno * 2;
return (msgId, seqno);
}
private async Task SendAsync(IObject msg, bool isContent, Rpc rpc = null)
{
if (_reactorTask == null) throw new WTException("You must connect to Telegram first");
- isContent &= _dcSession.AuthKeyID != 0;
+ isContent &= _dcSession.authKeyID != 0;
var (msgId, seqno) = NewMsgId(isContent);
if (rpc != null)
lock (_pendingRpcs)
@@ -1462,7 +1466,7 @@ namespace WTelegram
using var writer = new BinaryWriter(memStream);
writer.Write(0); // int32 payload_len (to be patched with payload length)
- if (_dcSession.AuthKeyID == 0) // send unencrypted message
+ if (_dcSession.authKeyID == 0) // send unencrypted message
{
if (_bareRpc == null) throw new WTException($"Shouldn't send a {msg.GetType().Name} unencrypted");
writer.Write(0L); // int64 auth_key_id = 0 (Unencrypted)
@@ -1479,7 +1483,7 @@ namespace WTelegram
using var clearWriter = new BinaryWriter(clearStream);
clearWriter.Write(_dcSession.AuthKey, 88, 32);
clearWriter.Write(_dcSession.Salt); // int64 salt
- clearWriter.Write(_dcSession.Id); // int64 session_id
+ clearWriter.Write(_dcSession.id); // int64 session_id
clearWriter.Write(msgId); // int64 message_id
clearWriter.Write(seqno); // int32 msg_seqno
clearWriter.Write(0); // int32 message_data_length (to be patched)
@@ -1499,13 +1503,13 @@ namespace WTelegram
const int msgKeyOffset = 8; // msg_key = middle 128-bits of SHA256(authkey_part+plaintext+padding)
byte[] encrypted_data = EncryptDecryptMessage(clearBuffer.AsSpan(32, clearLength + padding), true, 0, _dcSession.AuthKey, msgKeyLarge, msgKeyOffset, _sha256);
- writer.Write(_dcSession.AuthKeyID); // int64 auth_key_id
+ writer.Write(_dcSession.authKeyID); // int64 auth_key_id
writer.Write(msgKeyLarge, msgKeyOffset, 16); // int128 msg_key
writer.Write(encrypted_data); // bytes encrypted_data
}
if (_paddedMode) // Padded intermediate mode => append random padding
{
- var padding = new byte[_random.Next(_dcSession.AuthKeyID == 0 ? 257 : 16)];
+ var padding = new byte[_random.Next(_dcSession.authKeyID == 0 ? 257 : 16)];
RNG.GetBytes(padding);
writer.Write(padding);
}
@@ -1572,7 +1576,7 @@ namespace WTelegram
/// Wait for the reply and return the resulting object, or throws an RpcException if an error was replied
public async Task Invoke(IMethod query)
{
- if (_dcSession.WithoutUpdates && query is not IMethod and not IMethod)
+ if (_dcSession.withoutUpdates && query is not IMethod and not IMethod)
query = new TL.Methods.InvokeWithoutUpdates { query = query };
bool got503 = false;
retry:
@@ -1610,7 +1614,7 @@ namespace WTelegram
{
if (x <= FloodRetryThreshold)
{
- if (x == 0) x =1;
+ if (x == 0) x = 1;
await Task.Delay(x * 1000);
goto retry;
}
@@ -1623,14 +1627,16 @@ namespace WTelegram
else if (code == 400 && message == "CONNECTION_NOT_INITED")
{
await InitConnection();
+ lock (_session) _session.Save();
goto retry;
}
else if (code == 500 && message == "AUTH_RESTART")
- {
- _session.UserId = 0; // force a full login authorization flow, next time
- User = null;
- lock (_session) _session.Save();
- }
+ lock (_session)
+ {
+ _session.UserId = 0; // force a full login authorization flow, next time
+ User = null;
+ _session.Save();
+ }
throw new RpcException(code, message, x);
case ReactorError:
goto retry;
diff --git a/src/Encryption.cs b/src/Encryption.cs
index d943e5d..957c537 100644
--- a/src/Encryption.cs
+++ b/src/Encryption.cs
@@ -110,9 +110,9 @@ namespace WTelegram
var g_a = BigEndianInteger(serverDHinnerData.g_a);
var dh_prime = BigEndianInteger(serverDHinnerData.dh_prime);
CheckGoodPrime(dh_prime, serverDHinnerData.g);
- session.LastSentMsgId = 0;
- session.ServerTicksOffset = (serverDHinnerData.server_time - localTime).Ticks;
- Helpers.Log(1, $"Time offset: {session.ServerTicksOffset} | Server: {serverDHinnerData.server_time.TimeOfDay} UTC | Local: {localTime.TimeOfDay} UTC");
+ session.lastSentMsgId = 0;
+ session.serverTicksOffset = (serverDHinnerData.server_time - localTime).Ticks;
+ Helpers.Log(1, $"Time offset: {session.serverTicksOffset} | Server: {serverDHinnerData.server_time.TimeOfDay} UTC | Local: {localTime.TimeOfDay} UTC");
//6)
var salt = new byte[256];
RNG.GetBytes(salt);
@@ -159,7 +159,7 @@ namespace WTelegram
if (!Enumerable.SequenceEqual(dhGenOk.new_nonce_hash1.raw, sha1.ComputeHash(expected_new_nonceN).Skip(4)))
throw new WTException("setClientDHparamsAnswer.new_nonce_hashN mismatch");
- session.AuthKeyID = BinaryPrimitives.ReadInt64LittleEndian(authKeyHash.AsSpan(12));
+ session.authKeyID = BinaryPrimitives.ReadInt64LittleEndian(authKeyHash.AsSpan(12));
session.AuthKey = authKey;
session.Salt = BinaryPrimitives.ReadInt64LittleEndian(pqInnerData.new_nonce.raw) ^ BinaryPrimitives.ReadInt64LittleEndian(resPQ.server_nonce.raw);
session.OldSalt = session.Salt;
diff --git a/src/Session.cs b/src/Session.cs
index 86a0fec..c12d65a 100644
--- a/src/Session.cs
+++ b/src/Session.cs
@@ -21,25 +21,25 @@ namespace WTelegram
public sealed class DCSession
{
- public long Id;
- public long AuthKeyID;
public byte[] AuthKey; // 2048-bit = 256 bytes
public long UserId;
public long OldSalt; // still accepted for a further 1800 seconds
public long Salt;
public SortedList Salts;
- public int Seqno;
- public long ServerTicksOffset;
- public long LastSentMsgId;
public TL.DcOption DataCenter;
- public bool WithoutUpdates;
public int Layer;
+ internal long id = Helpers.RandomLong();
+ internal long authKeyID;
+ internal int seqno;
+ internal long serverTicksOffset;
+ internal long lastSentMsgId;
+ internal bool withoutUpdates;
internal Client Client;
internal int DcID => DataCenter?.id ?? 0;
internal IPEndPoint EndPoint => DataCenter == null ? null : new(IPAddress.Parse(DataCenter.ip_address), DataCenter.port);
- internal void Renew() { Helpers.Log(3, $"Renewing session on DC {DcID}..."); Id = Helpers.RandomLong(); Seqno = 0; LastSentMsgId = 0; }
- public void DisableUpdates(bool disable = true) { if (WithoutUpdates != disable) { WithoutUpdates = disable; Renew(); } }
+ internal void Renew() { Helpers.Log(3, $"Renewing session on DC {DcID}..."); id = Helpers.RandomLong(); seqno = 0; lastSentMsgId = 0; }
+ public void DisableUpdates(bool disable = true) { if (withoutUpdates != disable) { withoutUpdates = disable; Renew(); } }
const int MsgIdsN = 512;
private long[] _msgIds;
@@ -117,6 +117,9 @@ namespace WTelegram
throw new WTException("Integrity check failed in session loading");
session = JsonSerializer.Deserialize(utf8Json.AsSpan(32), Helpers.JsonOptions);
Helpers.Log(2, "Loaded previous session");
+ using var sha1 = SHA1.Create();
+ foreach (var dcs in session.DCSessions.Values)
+ dcs.authKeyID = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(dcs.AuthKey).AsSpan(12));
}
session ??= new Session();
session._store = store;
From eaea2d051a3f4ae8624d263da7d803d81ea9f457 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Sun, 20 Apr 2025 03:23:43 +0200
Subject: [PATCH 14/68] API Layer 201.2: business bot stars
---
src/TL.Schema.cs | 8 ++++++++
src/TL.Table.cs | 3 ++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 9a1af73..424006f 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -15946,6 +15946,13 @@ namespace TL
has_message = 0x1,
}
}
+ /// See
+ [TLDef(0xF4997E42)]
+ public sealed partial class InputInvoiceBusinessBotTransferStars : InputInvoice
+ {
+ public InputUserBase bot;
+ public long stars;
+ }
/// Exported invoice deep link See
[TLDef(0xAED0CBD9)]
@@ -19510,6 +19517,7 @@ namespace TL
has_paid_messages = 0x80000,
/// Field has a value
has_premium_gift_months = 0x100000,
+ business_transfer = 0x200000,
}
}
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index e441650..36011aa 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 201; // fetched 26/03/2025 23:35:58
+ public const int Version = 201; // fetched 20/04/2025 01:20:15
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -1111,6 +1111,7 @@ namespace TL
[0x4D818D5D] = typeof(InputInvoiceStarGiftUpgrade),
[0x4A5F5BD9] = typeof(InputInvoiceStarGiftTransfer),
[0xDABAB2EF] = typeof(InputInvoicePremiumGiftStars),
+ [0xF4997E42] = typeof(InputInvoiceBusinessBotTransferStars),
[0xAED0CBD9] = typeof(Payments_ExportedInvoice),
[0xCFB9D957] = typeof(Messages_TranscribedAudio),
[0x5334759C] = typeof(Help_PremiumPromo),
From 6fb59286bde7fc8641c93f31ea01bf32c87db2fd Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 1 May 2025 12:17:06 +0200
Subject: [PATCH 15/68] API Layer 202: E2E group calls
https://core.telegram.org/api/end-to-end/group-calls
---
README.md | 2 +-
src/TL.Schema.cs | 117 ++++++++++++---------
src/TL.SchemaFuncs.cs | 210 ++++++++++++++++++++++++++++---------
src/TL.Table.cs | 20 ++--
src/WTelegramClient.csproj | 2 +-
5 files changed, 242 insertions(+), 109 deletions(-)
diff --git a/README.md b/README.md
index 32a183d..d2aadf3 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 424006f..58a7de8 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -692,7 +692,7 @@ namespace TL
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// Livestream info
- public InputGroupCall call;
+ public InputGroupCallBase call;
/// Timestamp in milliseconds
public long time_ms;
/// Specifies the duration of the video segment to fetch in milliseconds, by bitshifting 1000 to the right scale times: duration_ms := 1000 >> scale
@@ -1262,7 +1262,7 @@ namespace TL
/// Peer folder ID, for more info click here
public virtual int Folder => default;
/// Group call information
- public virtual InputGroupCall Call => default;
+ public virtual InputGroupCallBase Call => default;
/// Time-To-Live of messages sent by the current user to this chat
public virtual int TtlPeriod => default;
/// When using Phone_GetGroupCallJoinAs to get a list of peers that can be used to join a group call, this field indicates the peer that should be selected by default.
@@ -1303,7 +1303,7 @@ namespace TL
/// Peer folder ID, for more info click here
[IfFlag(11)] public int folder_id;
/// Group call information
- [IfFlag(12)] public InputGroupCall call;
+ [IfFlag(12)] public InputGroupCallBase call;
/// Time-To-Live of messages sent by the current user to this chat
[IfFlag(14)] public int ttl_period;
/// When using Phone_GetGroupCallJoinAs to get a list of peers that can be used to join a group call, this field indicates the peer that should be selected by default.
@@ -1370,7 +1370,7 @@ namespace TL
/// Peer folder ID, for more info click here
public override int Folder => folder_id;
/// Group call information
- public override InputGroupCall Call => call;
+ public override InputGroupCallBase Call => call;
/// Time-To-Live of messages sent by the current user to this chat
public override int TtlPeriod => ttl_period;
/// When using Phone_GetGroupCallJoinAs to get a list of peers that can be used to join a group call, this field indicates the peer that should be selected by default.
@@ -1447,7 +1447,7 @@ namespace TL
/// Latest PTS for this channel
public int pts;
/// Livestream or group call information
- [IfFlag(21)] public InputGroupCall call;
+ [IfFlag(21)] public InputGroupCallBase call;
/// Time-To-Live of messages in this channel or supergroup
[IfFlag(24)] public int ttl_period;
/// A list of suggested actions for the supergroup admin, see here for more info ».
@@ -1606,7 +1606,7 @@ namespace TL
/// Peer folder ID, for more info click here
public override int Folder => folder_id;
/// Livestream or group call information
- public override InputGroupCall Call => call;
+ public override InputGroupCallBase Call => call;
/// Time-To-Live of messages in this channel or supergroup
public override int TtlPeriod => ttl_period;
/// When using Phone_GetGroupCallJoinAs to get a list of peers that can be used to join a group call, this field indicates the peer that should be selected by default.
@@ -2548,7 +2548,7 @@ namespace TL
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// Group call
- public InputGroupCall call;
+ public InputGroupCallBase call;
/// Group call duration
[IfFlag(0)] public int duration;
@@ -2563,7 +2563,7 @@ namespace TL
public sealed partial class MessageActionInviteToGroupCall : MessageAction
{
/// The group call
- public InputGroupCall call;
+ public InputGroupCallBase call;
/// The invited users
public long[] users;
}
@@ -2589,7 +2589,7 @@ namespace TL
public sealed partial class MessageActionGroupCallScheduled : MessageAction
{
/// The group call
- public InputGroupCall call;
+ public InputGroupCallBase call;
/// When is this group call scheduled to start
public DateTime schedule_date;
}
@@ -2959,6 +2959,24 @@ namespace TL
{
public long stars;
}
+ /// See
+ [TLDef(0x2FFE2F7A)]
+ public sealed partial class MessageActionConferenceCall : MessageAction
+ {
+ public Flags flags;
+ public long call_id;
+ [IfFlag(2)] public int duration;
+ [IfFlag(3)] public Peer[] other_participants;
+
+ [Flags] public enum Flags : uint
+ {
+ missed = 0x1,
+ active = 0x2,
+ has_duration = 0x4,
+ has_other_participants = 0x8,
+ video = 0x10,
+ }
+ }
/// Chat info. See Derived classes: ,
public abstract partial class DialogBase : IObject
@@ -5124,7 +5142,7 @@ namespace TL
public sealed partial class UpdateGroupCallParticipants : Update
{
/// Group call
- public InputGroupCall call;
+ public InputGroupCallBase call;
/// New participant list
public GroupCallParticipant[] participants;
/// Version
@@ -5818,6 +5836,15 @@ namespace TL
{
public Auth_SentCodeBase sent_code;
}
+ /// See
+ [TLDef(0xA477288F)]
+ public sealed partial class UpdateGroupCallChainBlocks : Update
+ {
+ public InputGroupCallBase call;
+ public int sub_chain_id;
+ public byte[][] blocks;
+ public int next_offset;
+ }
/// Updates state. See
[TLDef(0xA56C2A3E)]
@@ -10529,11 +10556,11 @@ namespace TL
/// The phone call was discarded because the user is busy in another call See
[TLDef(0xFAF7E8C9)]
public sealed partial class PhoneCallDiscardReasonBusy : PhoneCallDiscardReason { }
- /// See
- [TLDef(0xAFE2B839)]
- public sealed partial class PhoneCallDiscardReasonAllowGroupCall : PhoneCallDiscardReason
+ /// See
+ [TLDef(0x9FBBF1F7)]
+ public sealed partial class PhoneCallDiscardReasonMigrateConferenceCall : PhoneCallDiscardReason
{
- public byte[] encrypted_key;
+ public string slug;
}
/// Represents a json-encoded object See
@@ -11232,7 +11259,6 @@ namespace TL
public virtual long ParticipantId => default;
/// Phone call protocol info
public virtual PhoneCallProtocol Protocol => default;
- public virtual InputGroupCall ConferenceCall => default;
}
/// Empty constructor See
[TLDef(0x5366C915)]
@@ -11245,7 +11271,7 @@ namespace TL
public override long ID => id;
}
/// Incoming phone call See
- [TLDef(0xEED42858)]
+ [TLDef(0xC5226F17)]
public sealed partial class PhoneCallWaiting : PhoneCallBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -11264,7 +11290,6 @@ namespace TL
public PhoneCallProtocol protocol;
/// When was the phone call received
[IfFlag(0)] public DateTime receive_date;
- [IfFlag(8)] public InputGroupCall conference_call;
[Flags] public enum Flags : uint
{
@@ -11272,8 +11297,6 @@ namespace TL
has_receive_date = 0x1,
/// Is this a video call
video = 0x40,
- /// Field has a value
- has_conference_call = 0x100,
}
/// Call ID
@@ -11288,10 +11311,9 @@ namespace TL
public override long ParticipantId => participant_id;
/// Phone call protocol info
public override PhoneCallProtocol Protocol => protocol;
- public override InputGroupCall ConferenceCall => conference_call;
}
/// Requested phone call See
- [TLDef(0x45361C63)]
+ [TLDef(0x14B0ED0C)]
public sealed partial class PhoneCallRequested : PhoneCallBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -11310,14 +11332,11 @@ namespace TL
public byte[] g_a_hash;
/// Call protocol info to be passed to libtgvoip
public PhoneCallProtocol protocol;
- [IfFlag(8)] public InputGroupCall conference_call;
[Flags] public enum Flags : uint
{
/// Whether this is a video call
video = 0x40,
- /// Field has a value
- has_conference_call = 0x100,
}
/// Phone call ID
@@ -11332,10 +11351,9 @@ namespace TL
public override long ParticipantId => participant_id;
/// Call protocol info to be passed to libtgvoip
public override PhoneCallProtocol Protocol => protocol;
- public override InputGroupCall ConferenceCall => conference_call;
}
/// An accepted phone call See
- [TLDef(0x22FD7181)]
+ [TLDef(0x3660C311)]
public sealed partial class PhoneCallAccepted : PhoneCallBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -11354,14 +11372,11 @@ namespace TL
public byte[] g_b;
/// Protocol to use for phone call
public PhoneCallProtocol protocol;
- [IfFlag(8)] public InputGroupCall conference_call;
[Flags] public enum Flags : uint
{
/// Whether this is a video call
video = 0x40,
- /// Field has a value
- has_conference_call = 0x100,
}
/// ID of accepted phone call
@@ -11376,10 +11391,9 @@ namespace TL
public override long ParticipantId => participant_id;
/// Protocol to use for phone call
public override PhoneCallProtocol Protocol => protocol;
- public override InputGroupCall ConferenceCall => conference_call;
}
/// Phone call See
- [TLDef(0x3BA5940C)]
+ [TLDef(0x30535AF5)]
public sealed partial class PhoneCall : PhoneCallBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -11406,7 +11420,6 @@ namespace TL
public DateTime start_date;
/// Custom JSON-encoded call parameters to be passed to tgcalls.
[IfFlag(7)] public DataJSON custom_parameters;
- [IfFlag(8)] public InputGroupCall conference_call;
[Flags] public enum Flags : uint
{
@@ -11416,8 +11429,7 @@ namespace TL
video = 0x40,
/// Field has a value
has_custom_parameters = 0x80,
- /// Field has a value
- has_conference_call = 0x100,
+ conference_supported = 0x100,
}
/// Call ID
@@ -11432,10 +11444,9 @@ namespace TL
public override long ParticipantId => participant_id;
/// Call protocol info to be passed to libtgvoip
public override PhoneCallProtocol Protocol => protocol;
- public override InputGroupCall ConferenceCall => conference_call;
}
/// Indicates a discarded phone call See
- [TLDef(0xF9D25503)]
+ [TLDef(0x50CA4DE1)]
public sealed partial class PhoneCallDiscarded : PhoneCallBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -11446,7 +11457,6 @@ namespace TL
[IfFlag(0)] public PhoneCallDiscardReason reason;
/// Duration of the phone call in seconds
[IfFlag(1)] public int duration;
- [IfFlag(8)] public InputGroupCall conference_call;
[Flags] public enum Flags : uint
{
@@ -11460,13 +11470,10 @@ namespace TL
need_debug = 0x8,
/// Whether the call was a video call
video = 0x40,
- /// Field has a value
- has_conference_call = 0x100,
}
/// Call ID
public override long ID => id;
- public override InputGroupCall ConferenceCall => conference_call;
}
/// Phone call connection See Derived classes: ,
@@ -11904,14 +11911,14 @@ namespace TL
public sealed partial class ChannelAdminLogEventActionStartGroupCall : ChannelAdminLogEventAction
{
/// Group call
- public InputGroupCall call;
+ public InputGroupCallBase call;
}
/// A group call was terminated See
[TLDef(0xDB9F9140)]
public sealed partial class ChannelAdminLogEventActionDiscardGroupCall : ChannelAdminLogEventAction
{
/// The group call that was terminated
- public InputGroupCall call;
+ public InputGroupCallBase call;
}
/// A group call participant was muted See
[TLDef(0xF92424D2)]
@@ -14809,7 +14816,7 @@ namespace TL
public override long AccessHash => access_hash;
}
/// Info about a group call or livestream See
- [TLDef(0xCDF8D3E3)]
+ [TLDef(0x553B0BA1)]
public sealed partial class GroupCall : GroupCallBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -14834,7 +14841,7 @@ namespace TL
public int unmuted_video_limit;
/// Version
public int version;
- [IfFlag(14)] public long conference_from_call;
+ [IfFlag(16)] public string invite_link;
[Flags] public enum Flags : uint
{
@@ -14864,8 +14871,10 @@ namespace TL
rtmp_stream = 0x1000,
/// Whether the listeners list is hidden and cannot be fetched using Phone_GetGroupParticipants. The phone.groupParticipants.count and groupCall.participants_count counters will still include listeners.
listeners_hidden = 0x2000,
- /// Field has a value
- has_conference_from_call = 0x4000,
+ conference = 0x4000,
+ creator = 0x8000,
+ /// Field has a value
+ has_invite_link = 0x10000,
}
/// Group call ID
@@ -14874,15 +14883,29 @@ namespace TL
public override long AccessHash => access_hash;
}
+ /// Indicates a group call See Derived classes:
+ public abstract partial class InputGroupCallBase : IObject { }
/// Points to a specific group call See
[TLDef(0xD8AA840F)]
- public sealed partial class InputGroupCall : IObject
+ public sealed partial class InputGroupCall : InputGroupCallBase
{
/// Group call ID
public long id;
/// ⚠ REQUIRED FIELD. See how to obtain it
Group call access hash
public long access_hash;
}
+ /// See
+ [TLDef(0xFE06823F)]
+ public sealed partial class InputGroupCallSlug : InputGroupCallBase
+ {
+ public string slug;
+ }
+ /// See
+ [TLDef(0x8C10603F)]
+ public sealed partial class InputGroupCallInviteMessage : InputGroupCallBase
+ {
+ public int msg_id;
+ }
/// Info about a group call participant See
[TLDef(0xEBA636FE)]
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index aa0b3db..9a50d76 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -6509,12 +6509,11 @@ namespace TL
/// Random ID to avoid resending the same object
/// Parameter for E2E encryption key exchange »
/// Phone call settings
- public static Task Phone_RequestCall(this Client client, InputUserBase user_id, int random_id, byte[] g_a_hash, PhoneCallProtocol protocol, InputGroupCall conference_call = null, bool video = false)
+ public static Task Phone_RequestCall(this Client client, InputUserBase user_id, int random_id, byte[] g_a_hash, PhoneCallProtocol protocol, bool video = false)
=> client.Invoke(new Phone_RequestCall
{
- flags = (Phone_RequestCall.Flags)((conference_call != null ? 0x2 : 0) | (video ? 0x1 : 0)),
+ flags = (Phone_RequestCall.Flags)(video ? 0x1 : 0),
user_id = user_id,
- conference_call = conference_call,
random_id = random_id,
g_a_hash = g_a_hash,
protocol = protocol,
@@ -6627,21 +6626,22 @@ namespace TL
/// Join the group call, presenting yourself as the specified user/channel
/// The invitation hash from the invite link », if provided allows speaking in a livestream or muted group chat.
/// WebRTC parameters
- public static Task Phone_JoinGroupCall(this Client client, InputGroupCall call, InputPeer join_as, DataJSON params_, string invite_hash = null, long? key_fingerprint = null, bool muted = false, bool video_stopped = false)
+ public static Task Phone_JoinGroupCall(this Client client, InputGroupCallBase call, InputPeer join_as, DataJSON params_, string invite_hash = null, Int256? public_key = null, byte[] block = null, bool muted = false, bool video_stopped = false)
=> client.Invoke(new Phone_JoinGroupCall
{
- flags = (Phone_JoinGroupCall.Flags)((invite_hash != null ? 0x2 : 0) | (key_fingerprint != null ? 0x8 : 0) | (muted ? 0x1 : 0) | (video_stopped ? 0x4 : 0)),
+ flags = (Phone_JoinGroupCall.Flags)((invite_hash != null ? 0x2 : 0) | (public_key != null ? 0x8 : 0) | (block != null ? 0x8 : 0) | (muted ? 0x1 : 0) | (video_stopped ? 0x4 : 0)),
call = call,
join_as = join_as,
invite_hash = invite_hash,
- key_fingerprint = key_fingerprint ?? default,
+ public_key = public_key ?? default,
+ block = block,
params_ = params_,
});
/// Leave a group call See Possible codes: 400 (details)
/// The group call
/// Your source ID
- public static Task Phone_LeaveGroupCall(this Client client, InputGroupCall call, int source)
+ public static Task Phone_LeaveGroupCall(this Client client, InputGroupCallBase call, int source)
=> client.Invoke(new Phone_LeaveGroupCall
{
call = call,
@@ -6651,7 +6651,7 @@ namespace TL
/// Invite a set of users to a group call. See Possible codes: 400,403 (details)
/// The group call
/// The users to invite.
- public static Task Phone_InviteToGroupCall(this Client client, InputGroupCall call, params InputUserBase[] users)
+ public static Task Phone_InviteToGroupCall(this Client client, InputGroupCallBase call, params InputUserBase[] users)
=> client.Invoke(new Phone_InviteToGroupCall
{
call = call,
@@ -6660,7 +6660,7 @@ namespace TL
/// Terminate a group call See Possible codes: 400,403 (details)
/// The group call to terminate
- public static Task Phone_DiscardGroupCall(this Client client, InputGroupCall call)
+ public static Task Phone_DiscardGroupCall(this Client client, InputGroupCallBase call)
=> client.Invoke(new Phone_DiscardGroupCall
{
call = call,
@@ -6670,7 +6670,7 @@ namespace TL
/// Invalidate existing invite links
/// Group call
/// Whether all users will that join this group call are muted by default upon joining the group call
- public static Task Phone_ToggleGroupCallSettings(this Client client, InputGroupCall call, bool? join_muted = default, bool reset_invite_hash = false)
+ public static Task Phone_ToggleGroupCallSettings(this Client client, InputGroupCallBase call, bool? join_muted = default, bool reset_invite_hash = false)
=> client.Invoke(new Phone_ToggleGroupCallSettings
{
flags = (Phone_ToggleGroupCallSettings.Flags)((join_muted != default ? 0x1 : 0) | (reset_invite_hash ? 0x2 : 0)),
@@ -6681,7 +6681,7 @@ namespace TL
/// Get info about a group call See Possible codes: 400,403 (details)
/// The group call
/// Maximum number of results to return, see pagination
- public static Task Phone_GetGroupCall(this Client client, InputGroupCall call, int limit = int.MaxValue)
+ public static Task Phone_GetGroupCall(this Client client, InputGroupCallBase call, int limit = int.MaxValue)
=> client.Invoke(new Phone_GetGroupCall
{
call = call,
@@ -6694,7 +6694,7 @@ namespace TL
/// If specified, will fetch group participant info about the specified WebRTC source IDs
/// Offset for results, taken from the next_offset field of , initially an empty string.
Note: if no more results are available, the method call will return an empty next_offset; thus, avoid providing the next_offset returned in if it is empty, to avoid an infinite loop.
/// Maximum number of results to return, see pagination
- public static Task Phone_GetGroupParticipants(this Client client, InputGroupCall call, InputPeer[] ids, int[] sources, string offset, int limit = int.MaxValue)
+ public static Task Phone_GetGroupParticipants(this Client client, InputGroupCallBase call, InputPeer[] ids, int[] sources, string offset, int limit = int.MaxValue)
=> client.Invoke(new Phone_GetGroupParticipants
{
call = call,
@@ -6707,7 +6707,7 @@ namespace TL
/// Check whether the group call Server Forwarding Unit is currently receiving the streams with the specified WebRTC source IDs.
Returns an intersection of the source IDs specified in sources, and the source IDs currently being forwarded by the SFU. See Possible codes: 400 (details)
/// Group call
/// Source IDs
- public static Task Phone_CheckGroupCall(this Client client, InputGroupCall call, params int[] sources)
+ public static Task Phone_CheckGroupCall(this Client client, InputGroupCallBase call, params int[] sources)
=> client.Invoke(new Phone_CheckGroupCall
{
call = call,
@@ -6720,7 +6720,7 @@ namespace TL
/// The group call or livestream
/// Recording title
/// If video stream recording is enabled, whether to record in portrait or landscape mode
- public static Task Phone_ToggleGroupCallRecord(this Client client, InputGroupCall call, string title = null, bool? video_portrait = default, bool start = false, bool video = false)
+ public static Task Phone_ToggleGroupCallRecord(this Client client, InputGroupCallBase call, string title = null, bool? video_portrait = default, bool start = false, bool video = false)
=> client.Invoke(new Phone_ToggleGroupCallRecord
{
flags = (Phone_ToggleGroupCallRecord.Flags)((title != null ? 0x2 : 0) | (video_portrait != default ? 0x4 : 0) | (start ? 0x1 : 0) | (video ? 0x4 : 0)),
@@ -6738,7 +6738,7 @@ namespace TL
/// Start or stop the video stream
/// Pause or resume the video stream
/// Pause or resume the screen sharing stream
- public static Task Phone_EditGroupCallParticipant(this Client client, InputGroupCall call, InputPeer participant, bool? muted = default, int? volume = null, bool? raise_hand = default, bool? video_stopped = default, bool? video_paused = default, bool? presentation_paused = default)
+ public static Task Phone_EditGroupCallParticipant(this Client client, InputGroupCallBase call, InputPeer participant, bool? muted = default, int? volume = null, bool? raise_hand = default, bool? video_stopped = default, bool? video_paused = default, bool? presentation_paused = default)
=> client.Invoke(new Phone_EditGroupCallParticipant
{
flags = (Phone_EditGroupCallParticipant.Flags)((muted != default ? 0x1 : 0) | (volume != null ? 0x2 : 0) | (raise_hand != default ? 0x4 : 0) | (video_stopped != default ? 0x8 : 0) | (video_paused != default ? 0x10 : 0) | (presentation_paused != default ? 0x20 : 0)),
@@ -6755,7 +6755,7 @@ namespace TL
/// Edit the title of a group call or livestream See Possible codes: 400,403 (details)
/// Group call
/// New title
- public static Task Phone_EditGroupCallTitle(this Client client, InputGroupCall call, string title)
+ public static Task Phone_EditGroupCallTitle(this Client client, InputGroupCallBase call, string title)
=> client.Invoke(new Phone_EditGroupCallTitle
{
call = call,
@@ -6773,7 +6773,7 @@ namespace TL
/// Get an invite link for a group call or livestream See Possible codes: 400,403 (details)
/// For livestreams or muted group chats, if set, users that join using this link will be able to speak without explicitly requesting permission by (for example by raising their hand).
/// The group call
- public static Task Phone_ExportGroupCallInvite(this Client client, InputGroupCall call, bool can_self_unmute = false)
+ public static Task Phone_ExportGroupCallInvite(this Client client, InputGroupCallBase call, bool can_self_unmute = false)
=> client.Invoke(new Phone_ExportGroupCallInvite
{
flags = (Phone_ExportGroupCallInvite.Flags)(can_self_unmute ? 0x1 : 0),
@@ -6783,7 +6783,7 @@ namespace TL
/// Subscribe or unsubscribe to a scheduled group call See Possible codes: 400,403 (details)
/// Scheduled group call
/// Enable or disable subscription
- public static Task Phone_ToggleGroupCallStartSubscription(this Client client, InputGroupCall call, bool subscribed)
+ public static Task Phone_ToggleGroupCallStartSubscription(this Client client, InputGroupCallBase call, bool subscribed)
=> client.Invoke(new Phone_ToggleGroupCallStartSubscription
{
call = call,
@@ -6792,7 +6792,7 @@ namespace TL
/// Start a scheduled group call. See Possible codes: 400,403 (details)
/// The scheduled group call
- public static Task Phone_StartScheduledGroupCall(this Client client, InputGroupCall call)
+ public static Task Phone_StartScheduledGroupCall(this Client client, InputGroupCallBase call)
=> client.Invoke(new Phone_StartScheduledGroupCall
{
call = call,
@@ -6811,7 +6811,7 @@ namespace TL
/// Start screen sharing in a call See Possible codes: 400,403 (details)
/// The group call
/// WebRTC parameters
- public static Task Phone_JoinGroupCallPresentation(this Client client, InputGroupCall call, DataJSON params_)
+ public static Task Phone_JoinGroupCallPresentation(this Client client, InputGroupCallBase call, DataJSON params_)
=> client.Invoke(new Phone_JoinGroupCallPresentation
{
call = call,
@@ -6820,7 +6820,7 @@ namespace TL
/// Stop screen sharing in a group call See Possible codes: 400 (details)
/// The group call
- public static Task Phone_LeaveGroupCallPresentation(this Client client, InputGroupCall call)
+ public static Task Phone_LeaveGroupCallPresentation(this Client client, InputGroupCallBase call)
=> client.Invoke(new Phone_LeaveGroupCallPresentation
{
call = call,
@@ -6828,7 +6828,7 @@ namespace TL
/// Get info about RTMP streams in a group call or livestream.
This method should be invoked to the same group/channel-related DC used for downloading livestream chunks.
As usual, the media DC is preferred, if available. See Possible codes: 400 (details)
/// Group call or livestream
- public static Task Phone_GetGroupCallStreamChannels(this Client client, InputGroupCall call)
+ public static Task Phone_GetGroupCallStreamChannels(this Client client, InputGroupCallBase call)
=> client.Invoke(new Phone_GetGroupCallStreamChannels
{
call = call,
@@ -6855,11 +6855,58 @@ namespace TL
});
/// See
- public static Task Phone_CreateConferenceCall(this Client client, InputPhoneCall peer, long key_fingerprint)
+ public static Task Phone_CreateConferenceCall(this Client client, int random_id, Int256? public_key = null, byte[] block = null, DataJSON params_ = null, bool muted = false, bool video_stopped = false, bool join = false)
=> client.Invoke(new Phone_CreateConferenceCall
{
- peer = peer,
- key_fingerprint = key_fingerprint,
+ flags = (Phone_CreateConferenceCall.Flags)((public_key != null ? 0x8 : 0) | (block != null ? 0x8 : 0) | (params_ != null ? 0x8 : 0) | (muted ? 0x1 : 0) | (video_stopped ? 0x4 : 0) | (join ? 0x8 : 0)),
+ random_id = random_id,
+ public_key = public_key ?? default,
+ block = block,
+ params_ = params_,
+ });
+
+ /// See
+ public static Task Phone_DeleteConferenceCallParticipants(this Client client, InputGroupCallBase call, long[] ids, byte[] block, bool only_left = false, bool kick = false)
+ => client.Invoke(new Phone_DeleteConferenceCallParticipants
+ {
+ flags = (Phone_DeleteConferenceCallParticipants.Flags)((only_left ? 0x1 : 0) | (kick ? 0x2 : 0)),
+ call = call,
+ ids = ids,
+ block = block,
+ });
+
+ /// See
+ public static Task Phone_SendConferenceCallBroadcast(this Client client, InputGroupCallBase call, byte[] block)
+ => client.Invoke(new Phone_SendConferenceCallBroadcast
+ {
+ call = call,
+ block = block,
+ });
+
+ /// See
+ public static Task Phone_InviteConferenceCallParticipant(this Client client, InputGroupCallBase call, InputUserBase user_id, bool video = false)
+ => client.Invoke(new Phone_InviteConferenceCallParticipant
+ {
+ flags = (Phone_InviteConferenceCallParticipant.Flags)(video ? 0x1 : 0),
+ call = call,
+ user_id = user_id,
+ });
+
+ /// See
+ public static Task Phone_DeclineConferenceCallInvite(this Client client, int msg_id)
+ => client.Invoke(new Phone_DeclineConferenceCallInvite
+ {
+ msg_id = msg_id,
+ });
+
+ /// See
+ public static Task Phone_GetGroupCallChainBlocks(this Client client, InputGroupCallBase call, int sub_chain_id, int offset = default, int limit = int.MaxValue)
+ => client.Invoke(new Phone_GetGroupCallChainBlocks
+ {
+ call = call,
+ sub_chain_id = sub_chain_id,
+ offset = offset,
+ limit = limit,
});
/// Get localization pack strings See Possible codes: 400 (details)
@@ -12964,12 +13011,11 @@ namespace TL.Methods
[TLDef(0x55451FA9)]
public sealed partial class Phone_GetCallConfig : IMethod { }
- [TLDef(0xA6C4600C)]
+ [TLDef(0x42FF96ED)]
public sealed partial class Phone_RequestCall : IMethod
{
public Flags flags;
public InputUserBase user_id;
- [IfFlag(1)] public InputGroupCall conference_call;
public int random_id;
public byte[] g_a_hash;
public PhoneCallProtocol protocol;
@@ -12977,7 +13023,6 @@ namespace TL.Methods
[Flags] public enum Flags : uint
{
video = 0x1,
- has_conference_call = 0x2,
}
}
@@ -13064,14 +13109,15 @@ namespace TL.Methods
}
}
- [TLDef(0xD61E1DF3)]
+ [TLDef(0x8FB53057)]
public sealed partial class Phone_JoinGroupCall : IMethod
{
public Flags flags;
- public InputGroupCall call;
+ public InputGroupCallBase call;
public InputPeer join_as;
[IfFlag(1)] public string invite_hash;
- [IfFlag(3)] public long key_fingerprint;
+ [IfFlag(3)] public Int256 public_key;
+ [IfFlag(3)] public byte[] block;
public DataJSON params_;
[Flags] public enum Flags : uint
@@ -13079,35 +13125,35 @@ namespace TL.Methods
muted = 0x1,
has_invite_hash = 0x2,
video_stopped = 0x4,
- has_key_fingerprint = 0x8,
+ has_public_key = 0x8,
}
}
[TLDef(0x500377F9)]
public sealed partial class Phone_LeaveGroupCall : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public int source;
}
[TLDef(0x7B393160)]
public sealed partial class Phone_InviteToGroupCall : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public InputUserBase[] users;
}
[TLDef(0x7A777135)]
public sealed partial class Phone_DiscardGroupCall : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
}
[TLDef(0x74BBB43D)]
public sealed partial class Phone_ToggleGroupCallSettings : IMethod
{
public Flags flags;
- public InputGroupCall call;
+ public InputGroupCallBase call;
[IfFlag(0)] public bool join_muted;
[Flags] public enum Flags : uint
@@ -13120,14 +13166,14 @@ namespace TL.Methods
[TLDef(0x041845DB)]
public sealed partial class Phone_GetGroupCall : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public int limit;
}
[TLDef(0xC558D8AB)]
public sealed partial class Phone_GetGroupParticipants : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public InputPeer[] ids;
public int[] sources;
public string offset;
@@ -13137,7 +13183,7 @@ namespace TL.Methods
[TLDef(0xB59CF977)]
public sealed partial class Phone_CheckGroupCall : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public int[] sources;
}
@@ -13145,7 +13191,7 @@ namespace TL.Methods
public sealed partial class Phone_ToggleGroupCallRecord : IMethod
{
public Flags flags;
- public InputGroupCall call;
+ public InputGroupCallBase call;
[IfFlag(1)] public string title;
[IfFlag(2)] public bool video_portrait;
@@ -13161,7 +13207,7 @@ namespace TL.Methods
public sealed partial class Phone_EditGroupCallParticipant : IMethod
{
public Flags flags;
- public InputGroupCall call;
+ public InputGroupCallBase call;
public InputPeer participant;
[IfFlag(0)] public bool muted;
[IfFlag(1)] public int volume;
@@ -13184,7 +13230,7 @@ namespace TL.Methods
[TLDef(0x1CA6AC0A)]
public sealed partial class Phone_EditGroupCallTitle : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public string title;
}
@@ -13198,7 +13244,7 @@ namespace TL.Methods
public sealed partial class Phone_ExportGroupCallInvite : IMethod
{
public Flags flags;
- public InputGroupCall call;
+ public InputGroupCallBase call;
[Flags] public enum Flags : uint
{
@@ -13209,14 +13255,14 @@ namespace TL.Methods
[TLDef(0x219C34E6)]
public sealed partial class Phone_ToggleGroupCallStartSubscription : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public bool subscribed;
}
[TLDef(0x5680E342)]
public sealed partial class Phone_StartScheduledGroupCall : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
}
[TLDef(0x575E1F8C)]
@@ -13229,20 +13275,20 @@ namespace TL.Methods
[TLDef(0xCBEA6BC4)]
public sealed partial class Phone_JoinGroupCallPresentation : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
public DataJSON params_;
}
[TLDef(0x1C50D144)]
public sealed partial class Phone_LeaveGroupCallPresentation : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
}
[TLDef(0x1AB21940)]
public sealed partial class Phone_GetGroupCallStreamChannels : IMethod
{
- public InputGroupCall call;
+ public InputGroupCallBase call;
}
[TLDef(0xDEB3ABBF)]
@@ -13259,11 +13305,71 @@ namespace TL.Methods
public InputFileBase file;
}
- [TLDef(0xDFC909AB)]
- public sealed partial class Phone_CreateConferenceCall : IMethod
+ [TLDef(0x7D0444BB)]
+ public sealed partial class Phone_CreateConferenceCall : IMethod
{
- public InputPhoneCall peer;
- public long key_fingerprint;
+ public Flags flags;
+ public int random_id;
+ [IfFlag(3)] public Int256 public_key;
+ [IfFlag(3)] public byte[] block;
+ [IfFlag(3)] public DataJSON params_;
+
+ [Flags] public enum Flags : uint
+ {
+ muted = 0x1,
+ video_stopped = 0x4,
+ join = 0x8,
+ }
+ }
+
+ [TLDef(0x8CA60525)]
+ public sealed partial class Phone_DeleteConferenceCallParticipants : IMethod
+ {
+ public Flags flags;
+ public InputGroupCallBase call;
+ public long[] ids;
+ public byte[] block;
+
+ [Flags] public enum Flags : uint
+ {
+ only_left = 0x1,
+ kick = 0x2,
+ }
+ }
+
+ [TLDef(0xC6701900)]
+ public sealed partial class Phone_SendConferenceCallBroadcast : IMethod
+ {
+ public InputGroupCallBase call;
+ public byte[] block;
+ }
+
+ [TLDef(0xBCF22685)]
+ public sealed partial class Phone_InviteConferenceCallParticipant : IMethod
+ {
+ public Flags flags;
+ public InputGroupCallBase call;
+ public InputUserBase user_id;
+
+ [Flags] public enum Flags : uint
+ {
+ video = 0x1,
+ }
+ }
+
+ [TLDef(0x3C479971)]
+ public sealed partial class Phone_DeclineConferenceCallInvite : IMethod
+ {
+ public int msg_id;
+ }
+
+ [TLDef(0xEE9F88A6)]
+ public sealed partial class Phone_GetGroupCallChainBlocks : IMethod
+ {
+ public InputGroupCallBase call;
+ public int sub_chain_id;
+ public int offset;
+ public int limit;
}
[TLDef(0xF2F2330A)]
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 36011aa..892f37e 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 201; // fetched 20/04/2025 01:20:15
+ public const int Version = 202; // fetched 01/05/2025 10:01:40
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -217,6 +217,7 @@ namespace TL
[0xACDFCB81] = typeof(MessageActionStarGiftUnique),
[0xAC1F1FCD] = typeof(MessageActionPaidMessagesRefunded),
[0xBCD71419] = typeof(MessageActionPaidMessagesPrice),
+ [0x2FFE2F7A] = typeof(MessageActionConferenceCall),
[0xD58A08C6] = typeof(Dialog),
[0x71BD134C] = typeof(DialogFolder),
[0x2331B22D] = typeof(PhotoEmpty),
@@ -424,6 +425,7 @@ namespace TL
[0x283BD312] = typeof(UpdateBotPurchasedPaidMedia),
[0x8B725FCE] = typeof(UpdatePaidReactionPrivacy),
[0x504AA18F] = typeof(UpdateSentPhoneCode),
+ [0xA477288F] = typeof(UpdateGroupCallChainBlocks),
[0xA56C2A3E] = typeof(Updates_State),
[0x5D75A138] = typeof(Updates_DifferenceEmpty),
[0x00F49CA0] = typeof(Updates_Difference),
@@ -756,7 +758,7 @@ namespace TL
[0xE095C1A0] = typeof(PhoneCallDiscardReasonDisconnect),
[0x57ADC690] = typeof(PhoneCallDiscardReasonHangup),
[0xFAF7E8C9] = typeof(PhoneCallDiscardReasonBusy),
- [0xAFE2B839] = typeof(PhoneCallDiscardReasonAllowGroupCall),
+ [0x9FBBF1F7] = typeof(PhoneCallDiscardReasonMigrateConferenceCall),
[0x7D748D04] = typeof(DataJSON),
[0xCB296BF8] = typeof(LabeledPrice),
[0x049EE584] = typeof(Invoice),
@@ -789,11 +791,11 @@ namespace TL
[0x32DA9E9C] = typeof(InputStickerSetItem),
[0x1E36FDED] = typeof(InputPhoneCall),
[0x5366C915] = typeof(PhoneCallEmpty),
- [0xEED42858] = typeof(PhoneCallWaiting),
- [0x45361C63] = typeof(PhoneCallRequested),
- [0x22FD7181] = typeof(PhoneCallAccepted),
- [0x3BA5940C] = typeof(PhoneCall),
- [0xF9D25503] = typeof(PhoneCallDiscarded),
+ [0xC5226F17] = typeof(PhoneCallWaiting),
+ [0x14B0ED0C] = typeof(PhoneCallRequested),
+ [0x3660C311] = typeof(PhoneCallAccepted),
+ [0x30535AF5] = typeof(PhoneCall),
+ [0x50CA4DE1] = typeof(PhoneCallDiscarded),
[0x9CC123C7] = typeof(PhoneConnection),
[0x635FE375] = typeof(PhoneConnectionWebrtc),
[0xFC878FC8] = typeof(PhoneCallProtocol),
@@ -1031,8 +1033,10 @@ namespace TL
[0xE8FD8014] = typeof(PeerBlocked),
[0x7FE91C14] = typeof(Stats_MessageStats),
[0x7780BCB4] = typeof(GroupCallDiscarded),
- [0xCDF8D3E3] = typeof(GroupCall),
+ [0x553B0BA1] = typeof(GroupCall),
[0xD8AA840F] = typeof(InputGroupCall),
+ [0xFE06823F] = typeof(InputGroupCallSlug),
+ [0x8C10603F] = typeof(InputGroupCallInviteMessage),
[0xEBA636FE] = typeof(GroupCallParticipant),
[0x9E727AAD] = typeof(Phone_GroupCall),
[0xF47751B6] = typeof(Phone_GroupParticipants),
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 1debd31..a19c731 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 201
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 202
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From 8836f8372b6a76d747e34867e1e7218c715cb50e Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Wed, 14 May 2025 18:18:20 +0200
Subject: [PATCH 16/68] API Layer 203: Stargift resale, auto-translation...
---
README.md | 2 +-
src/TL.Schema.cs | 143 ++++++++++++++++++++++++++++++++++---
src/TL.SchemaFuncs.cs | 67 ++++++++++++++++-
src/TL.Table.cs | 24 +++++--
src/WTelegramClient.csproj | 2 +-
5 files changed, 215 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
index d2aadf3..557ce41 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index 58a7de8..c05334e 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -1204,6 +1204,7 @@ namespace TL
has_bot_verification_icon = 0x2000,
/// Field has a value
has_send_paid_messages_stars = 0x4000,
+ autotranslation = 0x8000,
}
/// ID of the channel, see here » for more info
@@ -2923,7 +2924,7 @@ namespace TL
}
}
/// See
- [TLDef(0xACDFCB81)]
+ [TLDef(0x2E3AE60E)]
public sealed partial class MessageActionStarGiftUnique : MessageAction
{
public Flags flags;
@@ -2933,6 +2934,9 @@ namespace TL
[IfFlag(6)] public Peer from_id;
[IfFlag(7)] public Peer peer;
[IfFlag(7)] public long saved_id;
+ [IfFlag(8)] public long resale_stars;
+ [IfFlag(9)] public int can_transfer_at;
+ [IfFlag(10)] public int can_resell_at;
[Flags] public enum Flags : uint
{
@@ -2944,6 +2948,9 @@ namespace TL
refunded = 0x20,
has_from_id = 0x40,
has_peer = 0x80,
+ has_resale_stars = 0x100,
+ has_can_transfer_at = 0x200,
+ has_can_resell_at = 0x400,
}
}
/// See
@@ -12137,6 +12144,12 @@ namespace TL
/// The subscriber that extended the subscription.
public ChannelParticipantBase new_participant;
}
+ /// See
+ [TLDef(0xC517F77E)]
+ public sealed partial class ChannelAdminLogEventActionToggleAutotranslation : ChannelAdminLogEventAction
+ {
+ public bool new_value;
+ }
/// Admin log event See
[TLDef(0x1FAD68CD)]
@@ -14367,7 +14380,7 @@ namespace TL
public DateTime expires;
}
/// MTProxy/Public Service Announcement information See
- [TLDef(0x8C39793F)]
+ [TLDef(0x08A4D87A)]
public sealed partial class Help_PromoData : Help_PromoDataBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -14375,15 +14388,18 @@ namespace TL
/// Expiry of PSA/MTProxy info
public DateTime expires;
/// MTProxy/PSA peer
- public Peer peer;
- /// Chat info
- public Dictionary chats;
- /// User info
- public Dictionary users;
+ [IfFlag(3)] public Peer peer;
/// PSA type
[IfFlag(1)] public string psa_type;
/// PSA message
[IfFlag(2)] public string psa_message;
+ public string[] pending_suggestions;
+ public string[] dismissed_suggestions;
+ [IfFlag(4)] public PendingSuggestion custom_pending_suggestion;
+ /// Chat info
+ public Dictionary chats;
+ /// User info
+ public Dictionary users;
[Flags] public enum Flags : uint
{
@@ -14393,6 +14409,10 @@ namespace TL
has_psa_type = 0x2,
/// Field has a value
has_psa_message = 0x4,
+ /// Field has a value
+ has_peer = 0x8,
+ /// Field has a value
+ has_custom_pending_suggestion = 0x10,
}
/// returns a or for the result
public IPeerInfo UserOrChat => peer?.UserOrChat(users, chats);
@@ -15976,6 +15996,13 @@ namespace TL
public InputUserBase bot;
public long stars;
}
+ /// See
+ [TLDef(0x63CBC38C)]
+ public sealed partial class InputInvoiceStarGiftResale : InputInvoice
+ {
+ public string slug;
+ public InputPeer to_id;
+ }
/// Exported invoice deep link See
[TLDef(0xAED0CBD9)]
@@ -19541,6 +19568,7 @@ namespace TL
/// Field has a value
has_premium_gift_months = 0x100000,
business_transfer = 0x200000,
+ stargift_resale = 0x400000,
}
}
@@ -19909,9 +19937,10 @@ namespace TL
public virtual long ID => default;
/// For limited-supply gifts: the total number of gifts that was available in the initial supply.
public virtual int AvailabilityTotal => default;
+ public virtual string Title => default;
}
/// Represents a star gift, see here » for more info. See
- [TLDef(0x02CC73C8)]
+ [TLDef(0xC62ACA28)]
public sealed partial class StarGift : StarGiftBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -19926,6 +19955,7 @@ namespace TL
[IfFlag(0)] public int availability_remains;
/// For limited-supply gifts: the total number of gifts that was available in the initial supply.
[IfFlag(0)] public int availability_total;
+ [IfFlag(4)] public long availability_resale;
/// The receiver of this gift may convert it to this many Telegram Stars, instead of displaying it on their profile page.
convert_stars will be equal to stars only if the gift was bought using recently bought Telegram Stars, otherwise it will be less than stars.
public long convert_stars;
/// For sold out gifts only: when was the gift first bought.
@@ -19933,6 +19963,8 @@ namespace TL
/// For sold out gifts only: when was the gift last bought.
[IfFlag(1)] public DateTime last_sale_date;
[IfFlag(3)] public long upgrade_stars;
+ [IfFlag(4)] public long resell_min_stars;
+ [IfFlag(5)] public string title;
[Flags] public enum Flags : uint
{
@@ -19944,15 +19976,20 @@ namespace TL
birthday = 0x4,
/// Field has a value
has_upgrade_stars = 0x8,
+ /// Fields and have a value
+ has_availability_resale = 0x10,
+ /// Field has a value
+ has_title = 0x20,
}
/// Identifier of the gift
public override long ID => id;
/// For limited-supply gifts: the total number of gifts that was available in the initial supply.
public override int AvailabilityTotal => availability_total;
+ public override string Title => title;
}
/// See
- [TLDef(0x5C62D151)]
+ [TLDef(0x6411DB89)]
public sealed partial class StarGiftUnique : StarGiftBase
{
public Flags flags;
@@ -19967,6 +20004,7 @@ namespace TL
public int availability_issued;
public int availability_total;
[IfFlag(3)] public string gift_address;
+ [IfFlag(4)] public long resell_stars;
[Flags] public enum Flags : uint
{
@@ -19974,10 +20012,12 @@ namespace TL
has_owner_name = 0x2,
has_owner_address = 0x4,
has_gift_address = 0x8,
+ has_resell_stars = 0x10,
}
public override long ID => id;
public override int AvailabilityTotal => availability_total;
+ public override string Title => title;
}
/// Available gifts ». See
@@ -20272,10 +20312,11 @@ namespace TL
public int rarity_permille;
}
/// See
- [TLDef(0x94271762)]
+ [TLDef(0xD93D859C)]
public sealed partial class StarGiftAttributeBackdrop : StarGiftAttribute
{
public string name;
+ public int backdrop_id;
public int center_color;
public int edge_color;
public int pattern_color;
@@ -20336,7 +20377,7 @@ namespace TL
}
/// See
- [TLDef(0x6056DBA5)]
+ [TLDef(0xDFDA0499)]
public sealed partial class SavedStarGift : IObject
{
public Flags flags;
@@ -20350,6 +20391,8 @@ namespace TL
[IfFlag(6)] public long upgrade_stars;
[IfFlag(7)] public int can_export_at;
[IfFlag(8)] public long transfer_stars;
+ [IfFlag(13)] public int can_transfer_at;
+ [IfFlag(14)] public int can_resell_at;
[Flags] public enum Flags : uint
{
@@ -20366,6 +20409,8 @@ namespace TL
can_upgrade = 0x400,
has_saved_id = 0x800,
pinned_to_top = 0x1000,
+ has_can_transfer_at = 0x2000,
+ has_can_resell_at = 0x4000,
}
}
@@ -20405,6 +20450,12 @@ namespace TL
public InputPeer peer;
public long saved_id;
}
+ /// See
+ [TLDef(0x2085C238)]
+ public sealed partial class InputSavedStarGiftSlug : InputSavedStarGift
+ {
+ public string slug;
+ }
/// See
[TLDef(0x84AA3A9C)]
@@ -20514,4 +20565,74 @@ namespace TL
/// returns a or for the given Peer
public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
}
+
+ /// See
+ public abstract partial class StarGiftAttributeId : IObject { }
+ /// See
+ [TLDef(0x48AAAE3C)]
+ public sealed partial class StarGiftAttributeIdModel : StarGiftAttributeId
+ {
+ public long document_id;
+ }
+ /// See
+ [TLDef(0x4A162433)]
+ public sealed partial class StarGiftAttributeIdPattern : StarGiftAttributeId
+ {
+ public long document_id;
+ }
+ /// See
+ [TLDef(0x1F01C757)]
+ public sealed partial class StarGiftAttributeIdBackdrop : StarGiftAttributeId
+ {
+ public int backdrop_id;
+ }
+
+ /// See
+ [TLDef(0x2EB1B658)]
+ public sealed partial class StarGiftAttributeCounter : IObject
+ {
+ public StarGiftAttributeId attribute;
+ public int count;
+ }
+
+ /// See
+ [TLDef(0x947A12DF)]
+ public sealed partial class Payments_ResaleStarGifts : IObject, IPeerResolver
+ {
+ public Flags flags;
+ public int count;
+ public StarGiftBase[] gifts;
+ [IfFlag(0)] public string next_offset;
+ [IfFlag(1)] public StarGiftAttribute[] attributes;
+ [IfFlag(1)] public long attributes_hash;
+ public Dictionary chats;
+ [IfFlag(2)] public StarGiftAttributeCounter[] counters;
+ public Dictionary users;
+
+ [Flags] public enum Flags : uint
+ {
+ has_next_offset = 0x1,
+ has_attributes = 0x2,
+ has_counters = 0x4,
+ }
+ /// returns a or for the given Peer
+ public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
+ }
+
+ /// See
+ [TLDef(0xC387C04E)]
+ public sealed partial class Stories_CanSendStoryCount : IObject
+ {
+ public int count_remains;
+ }
+
+ /// See
+ [TLDef(0xE7E82E12)]
+ public sealed partial class PendingSuggestion : IObject
+ {
+ public string suggestion;
+ public TextWithEntities title;
+ public TextWithEntities description;
+ public string url;
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 9a50d76..e872cc4 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -5587,6 +5587,14 @@ namespace TL
send_paid_messages_stars = send_paid_messages_stars,
});
+ /// See
+ public static Task Channels_ToggleAutotranslation(this Client client, InputChannelBase channel, bool enabled)
+ => client.Invoke(new Channels_ToggleAutotranslation
+ {
+ channel = channel,
+ enabled = enabled,
+ });
+
/// Sends a custom request; for bots only See [bots: ✓] Possible codes: 400,403 (details)
/// The method name
/// JSON-serialized method parameters
@@ -6367,6 +6375,26 @@ namespace TL
purpose = purpose,
});
+ /// See
+ public static Task Payments_GetResaleStarGifts(this Client client, long gift_id, string offset, int limit = int.MaxValue, long? attributes_hash = null, StarGiftAttributeId[] attributes = null, bool sort_by_price = false, bool sort_by_num = false)
+ => client.Invoke(new Payments_GetResaleStarGifts
+ {
+ flags = (Payments_GetResaleStarGifts.Flags)((attributes_hash != null ? 0x1 : 0) | (attributes != null ? 0x8 : 0) | (sort_by_price ? 0x2 : 0) | (sort_by_num ? 0x4 : 0)),
+ attributes_hash = attributes_hash ?? default,
+ gift_id = gift_id,
+ attributes = attributes,
+ offset = offset,
+ limit = limit,
+ });
+
+ /// See
+ public static Task Payments_UpdateStarGiftPrice(this Client client, InputSavedStarGift stargift, long resell_stars)
+ => client.Invoke(new Payments_UpdateStarGiftPrice
+ {
+ stargift = stargift,
+ resell_stars = resell_stars,
+ });
+
/// Create a stickerset. See [bots: ✓] Possible codes: 400 (details)
/// Whether this is a mask stickerset
/// Whether this is a custom emoji stickerset.
@@ -7193,7 +7221,7 @@ namespace TL
/// Check whether we can post stories as the specified peer. See Possible codes: 400 (details)
/// The peer from which we wish to post stories.
- public static Task Stories_CanSendStory(this Client client, InputPeer peer)
+ public static Task Stories_CanSendStory(this Client client, InputPeer peer)
=> client.Invoke(new Stories_CanSendStory
{
peer = peer,
@@ -12224,6 +12252,13 @@ namespace TL.Methods
public long send_paid_messages_stars;
}
+ [TLDef(0x167FC0A1)]
+ public sealed partial class Channels_ToggleAutotranslation : IMethod
+ {
+ public InputChannelBase channel;
+ public bool enabled;
+ }
+
[TLDef(0xAA2769ED)]
public sealed partial class Bots_SendCustomRequest : IMethod
{
@@ -12903,6 +12938,32 @@ namespace TL.Methods
public InputStorePaymentPurpose purpose;
}
+ [TLDef(0x7A5FA236)]
+ public sealed partial class Payments_GetResaleStarGifts : IMethod
+ {
+ public Flags flags;
+ [IfFlag(0)] public long attributes_hash;
+ public long gift_id;
+ [IfFlag(3)] public StarGiftAttributeId[] attributes;
+ public string offset;
+ public int limit;
+
+ [Flags] public enum Flags : uint
+ {
+ has_attributes_hash = 0x1,
+ sort_by_price = 0x2,
+ sort_by_num = 0x4,
+ has_attributes = 0x8,
+ }
+ }
+
+ [TLDef(0x3BAEA4E1)]
+ public sealed partial class Payments_UpdateStarGiftPrice : IMethod
+ {
+ public InputSavedStarGift stargift;
+ public long resell_stars;
+ }
+
[TLDef(0x9021AB67)]
public sealed partial class Stickers_CreateStickerSet : IMethod
{
@@ -13604,8 +13665,8 @@ namespace TL.Methods
public InputPeer[] peers;
}
- [TLDef(0xC7DFDFDD)]
- public sealed partial class Stories_CanSendStory : IMethod
+ [TLDef(0x30EB63F0)]
+ public sealed partial class Stories_CanSendStory : IMethod
{
public InputPeer peer;
}
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 892f37e..8e52198 100644
--- a/src/TL.Table.cs
+++ b/src/TL.Table.cs
@@ -6,7 +6,7 @@ namespace TL
{
public static partial class Layer
{
- public const int Version = 202; // fetched 01/05/2025 10:01:40
+ public const int Version = 203; // fetched 14/05/2025 16:07:47
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -214,7 +214,7 @@ namespace TL
[0x45D5B021] = typeof(MessageActionGiftStars),
[0xB00C47A2] = typeof(MessageActionPrizeStars),
[0x4717E8A4] = typeof(MessageActionStarGift),
- [0xACDFCB81] = typeof(MessageActionStarGiftUnique),
+ [0x2E3AE60E] = typeof(MessageActionStarGiftUnique),
[0xAC1F1FCD] = typeof(MessageActionPaidMessagesRefunded),
[0xBCD71419] = typeof(MessageActionPaidMessagesPrice),
[0x2FFE2F7A] = typeof(MessageActionConferenceCall),
@@ -859,6 +859,7 @@ namespace TL
[0x46D840AB] = typeof(ChannelAdminLogEventActionChangeEmojiStickerSet),
[0x60A79C79] = typeof(ChannelAdminLogEventActionToggleSignatureProfiles),
[0x64642DB3] = typeof(ChannelAdminLogEventActionParticipantSubExtend),
+ [0xC517F77E] = typeof(ChannelAdminLogEventActionToggleAutotranslation),
[0x1FAD68CD] = typeof(ChannelAdminLogEvent),
[0xED8AF74D] = typeof(Channels_AdminLogResults),
[0xEA107AE4] = typeof(ChannelAdminLogEventsFilter),
@@ -1011,7 +1012,7 @@ namespace TL
[0x8EA464B6] = typeof(StatsGraph),
[0x396CA5FC] = typeof(Stats_BroadcastStats),
[0x98F6AC75] = typeof(Help_PromoDataEmpty),
- [0x8C39793F] = typeof(Help_PromoData),
+ [0x08A4D87A] = typeof(Help_PromoData),
[0xDE33B094] = typeof(VideoSize),
[0xF85C413C] = typeof(VideoSizeEmojiMarkup),
[0x0DA082FE] = typeof(VideoSizeStickerMarkup),
@@ -1116,6 +1117,7 @@ namespace TL
[0x4A5F5BD9] = typeof(InputInvoiceStarGiftTransfer),
[0xDABAB2EF] = typeof(InputInvoicePremiumGiftStars),
[0xF4997E42] = typeof(InputInvoiceBusinessBotTransferStars),
+ [0x63CBC38C] = typeof(InputInvoiceStarGiftResale),
[0xAED0CBD9] = typeof(Payments_ExportedInvoice),
[0xCFB9D957] = typeof(Messages_TranscribedAudio),
[0x5334759C] = typeof(Help_PremiumPromo),
@@ -1353,8 +1355,8 @@ namespace TL
[0x4BA3A95A] = typeof(MessageReactor),
[0x94CE852A] = typeof(StarsGiveawayOption),
[0x54236209] = typeof(StarsGiveawayWinnersOption),
- [0x02CC73C8] = typeof(StarGift),
- [0x5C62D151] = typeof(StarGiftUnique),
+ [0xC62ACA28] = typeof(StarGift),
+ [0x6411DB89] = typeof(StarGiftUnique),
[0xA388A368] = null,//Payments_StarGiftsNotModified
[0x901689EA] = typeof(Payments_StarGifts),
[0x7903E3D9] = typeof(MessageReportOption),
@@ -1375,17 +1377,18 @@ namespace TL
[0xF93CD45C] = typeof(BotVerification),
[0x39D99013] = typeof(StarGiftAttributeModel),
[0x13ACFF19] = typeof(StarGiftAttributePattern),
- [0x94271762] = typeof(StarGiftAttributeBackdrop),
+ [0xD93D859C] = typeof(StarGiftAttributeBackdrop),
[0xE0BFF26C] = typeof(StarGiftAttributeOriginalDetails),
[0x167BD90B] = typeof(Payments_StarGiftUpgradePreview),
[0x62D706B8] = typeof(Users_Users),
[0x315A4974] = typeof(Users_UsersSlice),
[0xCAA2F60B] = typeof(Payments_UniqueStarGift),
[0xB53E8B21] = typeof(Messages_WebPagePreview),
- [0x6056DBA5] = typeof(SavedStarGift),
+ [0xDFDA0499] = typeof(SavedStarGift),
[0x95F389B1] = typeof(Payments_SavedStarGifts),
[0x69279795] = typeof(InputSavedStarGiftUser),
[0xF101AA7F] = typeof(InputSavedStarGiftChat),
+ [0x2085C238] = typeof(InputSavedStarGiftSlug),
[0x84AA3A9C] = typeof(Payments_StarGiftWithdrawalUrl),
[0x206AD49E] = null,//PaidReactionPrivacyDefault
[0x1F0C1AD9] = typeof(PaidReactionPrivacyAnonymous),
@@ -1399,6 +1402,13 @@ namespace TL
[0xC69708D3] = typeof(SponsoredPeer),
[0xEA32B4B1] = null,//Contacts_SponsoredPeersEmpty
[0xEB032884] = typeof(Contacts_SponsoredPeers),
+ [0x48AAAE3C] = typeof(StarGiftAttributeIdModel),
+ [0x4A162433] = typeof(StarGiftAttributeIdPattern),
+ [0x1F01C757] = typeof(StarGiftAttributeIdBackdrop),
+ [0x2EB1B658] = typeof(StarGiftAttributeCounter),
+ [0x947A12DF] = typeof(Payments_ResaleStarGifts),
+ [0xC387C04E] = typeof(Stories_CanSendStoryCount),
+ [0xE7E82E12] = typeof(PendingSuggestion),
// from TL.Secret:
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
[0x020DF5D0] = typeof(Layer101.MessageEntityBlockquote),
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index a19c731..2a71dd9 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,7 +13,7 @@
WTelegramClient
0.0.0
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 202
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 203
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From 5358471574404a4103c386a9c5bc18c4fec25fcc Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Mon, 2 Jun 2025 02:41:06 +0200
Subject: [PATCH 17/68] Fix fields serialization order on
KeyboardButtonSimpleWebView
---
generator/MTProtoGenerator.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/generator/MTProtoGenerator.cs b/generator/MTProtoGenerator.cs
index 5cc7719..4fd169d 100644
--- a/generator/MTProtoGenerator.cs
+++ b/generator/MTProtoGenerator.cs
@@ -54,7 +54,6 @@ public class MTProtoGenerator : IIncrementalGenerator
var tldef = symbol.GetAttributes().FirstOrDefault(a => a.AttributeClass == tlDefAttribute);
if (tldef == null) continue;
var id = (uint)tldef.ConstructorArguments[0].Value;
- var inheritBefore = (bool?)tldef.NamedArguments.FirstOrDefault(k => k.Key == "inheritBefore").Value.Value ?? false;
StringBuilder writeTl = new(), readTL = new();
var ns = symbol.BaseType.ContainingNamespace.ToString();
var name = symbol.BaseType.Name;
@@ -105,8 +104,12 @@ public class MTProtoGenerator : IIncrementalGenerator
.AppendLine($"\t\t\twriter.Write(0x{id:X8});");
var members = symbol.GetMembers().ToList();
for (var parent = symbol.BaseType; parent != object_; parent = parent.BaseType)
+ {
+ var inheritBefore = (bool?)tldef.NamedArguments.FirstOrDefault(k => k.Key == "inheritBefore").Value.Value ?? false;
if (inheritBefore) members.InsertRange(0, parent.GetMembers());
else members.AddRange(parent.GetMembers());
+ tldef = parent.GetAttributes().FirstOrDefault(a => a.AttributeClass == tlDefAttribute);
+ }
foreach (var member in members.OfType())
{
if (member.DeclaredAccessibility != Accessibility.Public || member.IsStatic) continue;
From d49d620eddc35aff6570879c5e9f0984f669cc4c Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Tue, 24 Jun 2025 19:01:52 +0200
Subject: [PATCH 18/68] Fixed possible concurrency issue on msgId/seqno, that
could freeze protocol or cause BadMsgNotification (during downloads for
example) Thanks goes to @Deeps00009
---
src/Client.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/Client.cs b/src/Client.cs
index 74e0b7a..222c6f6 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -1430,8 +1430,11 @@ namespace WTelegram
int seqno;
long msgId = DateTime.UtcNow.Ticks + _dcSession.serverTicksOffset - 621355968000000000L;
msgId = msgId * 428 + (msgId >> 24) * 25110956; // approximately unixtime*2^32 and divisible by 4
- if (msgId <= _dcSession.lastSentMsgId) msgId = _dcSession.lastSentMsgId += 4; else _dcSession.lastSentMsgId = msgId;
- seqno = isContent ? _dcSession.seqno++ * 2 + 1 : _dcSession.seqno * 2;
+ lock (_session)
+ {
+ if (msgId <= _dcSession.lastSentMsgId) msgId = _dcSession.lastSentMsgId += 4; else _dcSession.lastSentMsgId = msgId;
+ seqno = isContent ? _dcSession.seqno++ * 2 + 1 : _dcSession.seqno * 2;
+ }
return (msgId, seqno);
}
From 04e043222e7ab7f888727f77c9d6f7bb21c0b314 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Tue, 24 Jun 2025 19:11:14 +0200
Subject: [PATCH 19/68] ParallelTransfers property can configure how many
parallel download/upload of file chunks can occur at the same time. Default
is 2 (optimal for non-premium accounts), was 10 in previous versions.
---
src/Client.cs | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/Client.cs b/src/Client.cs
index 222c6f6..fa8f430 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -59,6 +59,18 @@ namespace WTelegram
public long UserId => _session.UserId;
/// Info about the current logged-in user. This is only filled after a successful (re)login, not updated later
public User User { get; private set; }
+ /// Number of parallel transfers operations (uploads/downloads) allowed at the same time.
+ /// Don't use this property while transfers are ongoing!
+ public int ParallelTransfers
+ {
+ get => _parallelTransfers.CurrentCount;
+ set
+ {
+ int delta = value - _parallelTransfers.CurrentCount;
+ for (; delta < 0; delta++) _parallelTransfers.Wait();
+ if (delta > 0) _parallelTransfers.Release(delta);
+ }
+ }
private Func _config;
private readonly Session _session;
@@ -83,7 +95,7 @@ namespace WTelegram
private int _reactorReconnects = 0;
private const string ConnectionShutDown = "Could not read payload length : Connection shut down";
private const long Ticks5Secs = 5 * TimeSpan.TicksPerSecond;
- private readonly SemaphoreSlim _parallelTransfers = new(10); // max parallel part uploads/downloads
+ private readonly SemaphoreSlim _parallelTransfers = new(2); // max parallel part uploads/downloads
private readonly SHA256 _sha256 = SHA256.Create();
private readonly SHA256 _sha256Recv = SHA256.Create();
#if OBFUSCATION
@@ -209,7 +221,7 @@ namespace WTelegram
if (_tcpClient != null) throw new InvalidOperationException("Cannot switch to HTTP after TCP connection");
_httpClient = httpClient ?? new();
_httpWait = defaultHttpWait;
- while (_parallelTransfers.CurrentCount > 1) _parallelTransfers.Wait();
+ ParallelTransfers = 1;
}
/// Disconnect from Telegram (shouldn't be needed in normal usage)
From 3ff1200068394c71e5891ed653d1c249d0d241cf Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 26 Jun 2025 22:02:26 +0200
Subject: [PATCH 20/68] Use signed DcId values (improved logs)
---
src/Client.cs | 27 +++++++++++++--------------
src/Session.cs | 2 +-
src/TL.cs | 4 ++--
3 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/src/Client.cs b/src/Client.cs
index fa8f430..40354de 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -325,7 +325,7 @@ namespace WTelegram
try
{
Auth_ExportedAuthorization exported = null;
- if (_session.UserId != 0 && IsMainDC && altSession.UserId != _session.UserId && altSession.DcID != _dcSession.DcID)
+ if (_session.UserId != 0 && IsMainDC && altSession.UserId != _session.UserId && Math.Abs(altSession.DcID) != Math.Abs(_dcSession.DcID))
exported = await this.Auth_ExportAuthorization(Math.Abs(dcId));
await altSession.Client.ConnectAsync();
if (exported != null)
@@ -345,16 +345,16 @@ namespace WTelegram
return altSession.Client;
}
- private async Task Reactor(Stream stream, CancellationTokenSource cts)
+ private async Task Reactor(Stream stream, CancellationToken ct)
{
const int MinBufferSize = 1024;
var data = new byte[MinBufferSize];
- while (!cts.IsCancellationRequested)
+ while (!ct.IsCancellationRequested)
{
IObject obj = null;
try
{
- if (await stream.FullReadAsync(data, 4, cts.Token) != 4)
+ if (await stream.FullReadAsync(data, 4, ct) != 4)
throw new WTException(ConnectionShutDown);
#if OBFUSCATION
_recvCtr.EncryptDecrypt(data, 4);
@@ -366,7 +366,7 @@ namespace WTelegram
data = new byte[payloadLen];
else if (Math.Max(payloadLen, MinBufferSize) < data.Length / 4)
data = new byte[Math.Max(payloadLen, MinBufferSize)];
- if (await stream.FullReadAsync(data, payloadLen, cts.Token) != payloadLen)
+ if (await stream.FullReadAsync(data, payloadLen, ct) != payloadLen)
throw new WTException("Could not read frame data : Connection shut down");
#if OBFUSCATION
_recvCtr.EncryptDecrypt(data, payloadLen);
@@ -375,14 +375,14 @@ namespace WTelegram
}
catch (Exception ex) // an exception in RecvAsync is always fatal
{
- if (cts.IsCancellationRequested) return;
+ if (ct.IsCancellationRequested) return;
bool disconnectedAltDC = !IsMainDC && ex is WTException { Message: ConnectionShutDown } or IOException { InnerException: SocketException };
if (disconnectedAltDC)
Helpers.Log(3, $"{_dcSession.DcID}>Alt DC disconnected: {ex.Message}");
else
Helpers.Log(5, $"{_dcSession.DcID}>An exception occured in the reactor: {ex}");
var oldSemaphore = _sendSemaphore;
- await oldSemaphore.WaitAsync(cts.Token); // prevent any sending while we reconnect
+ await oldSemaphore.WaitAsync(ct); // prevent any sending while we reconnect
var reactorError = new ReactorError { Exception = ex };
try
{
@@ -599,13 +599,13 @@ namespace WTelegram
var ctorNb = reader.ReadUInt32();
if (ctorNb == Layer.RpcResultCtor)
{
- Helpers.Log(1, $" → {"RpcResult",-38} {MsgIdToStamp(msg.msg_id):u}");
+ Helpers.Log(1, $" → {"RpcResult",-38} {MsgIdToStamp(msg.msg_id):u}");
msg.body = ReadRpcResult(reader);
}
else
{
var obj = msg.body = reader.ReadTLObject(ctorNb);
- Helpers.Log(1, $" → {obj.GetType().Name,-38} {MsgIdToStamp(msg.msg_id):u} {((msg.seq_no & 1) != 0 ? "" : "(svc)")} {((msg.msg_id & 2) == 0 ? "" : "NAR")}");
+ Helpers.Log(1, $" → {obj.GetType().Name,-38} {MsgIdToStamp(msg.msg_id):u} {((msg.seq_no & 1) != 0 ? "" : "(svc)")} {((msg.msg_id & 2) == 0 ? "" : "NAR")}");
}
}
catch (Exception ex)
@@ -676,9 +676,9 @@ namespace WTelegram
var typeName = result?.GetType().Name;
if (MsgIdToStamp(msgId) >= _session.SessionStart)
- Helpers.Log(4, $" → {typeName,-37} for unknown msgId #{(short)msgId.GetHashCode():X4}");
+ Helpers.Log(4, $" → {typeName,-37} for unknown msgId #{(short)msgId.GetHashCode():X4}");
else
- Helpers.Log(1, $" → {typeName,-37} for past msgId #{(short)msgId.GetHashCode():X4}");
+ Helpers.Log(1, $" → {typeName,-37} for past msgId #{(short)msgId.GetHashCode():X4}");
}
return new RpcResult { req_msg_id = msgId, result = result };
}
@@ -889,8 +889,7 @@ namespace WTelegram
if (MTProxyUrl != null)
{
#if OBFUSCATION
- if (TLConfig?.test_mode == true) dcId += 10000;
- if (_dcSession.DataCenter?.flags.HasFlag(DcOption.Flags.media_only) == true) dcId = -dcId;
+ if (TLConfig?.test_mode == true) dcId += dcId < 0 ? -10000 : 10000;
var parms = HttpUtility.ParseQueryString(MTProxyUrl[MTProxyUrl.IndexOf('?')..]);
var server = parms["server"];
int port = int.Parse(parms["port"]);
@@ -988,7 +987,7 @@ namespace WTelegram
#endif
await _networkStream.WriteAsync(preamble, 0, preamble.Length, _cts.Token);
- _reactorTask = Reactor(_networkStream, _cts);
+ _reactorTask = Reactor(_networkStream, _cts.Token);
}
_sendSemaphore.Release();
diff --git a/src/Session.cs b/src/Session.cs
index c12d65a..321c319 100644
--- a/src/Session.cs
+++ b/src/Session.cs
@@ -36,7 +36,7 @@ namespace WTelegram
internal long lastSentMsgId;
internal bool withoutUpdates;
internal Client Client;
- internal int DcID => DataCenter?.id ?? 0;
+ internal int DcID => DataCenter == null ? 0 : DataCenter.flags.HasFlag(TL.DcOption.Flags.media_only) ? -DataCenter.id : DataCenter.id;
internal IPEndPoint EndPoint => DataCenter == null ? null : new(IPAddress.Parse(DataCenter.ip_address), DataCenter.port);
internal void Renew() { Helpers.Log(3, $"Renewing session on DC {DcID}..."); id = Helpers.RandomLong(); seqno = 0; lastSentMsgId = 0; }
public void DisableUpdates(bool disable = true) { if (withoutUpdates != disable) { withoutUpdates = disable; Renew(); } }
diff --git a/src/TL.cs b/src/TL.cs
index 741bab4..67342ea 100644
--- a/src/TL.cs
+++ b/src/TL.cs
@@ -201,9 +201,9 @@ namespace TL
var patchPos = writer.BaseStream.Position;
writer.Write(0); // patched below
if ((msg.seq_no & 1) != 0)
- WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38} #{(short)msg.msg_id.GetHashCode():X4}");
+ WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38} #{(short)msg.msg_id.GetHashCode():X4}");
else
- WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38}");
+ WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38}");
writer.WriteTLObject(msg.body);
writer.BaseStream.Position = patchPos;
writer.Write((int)(writer.BaseStream.Length - patchPos - 4)); // patch bytes field
From 25990a8477e6e222c832ed3bfb52a6b8154fb8e8 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Sun, 29 Jun 2025 16:01:05 +0200
Subject: [PATCH 21/68] Fix Salts management
---
src/Client.cs | 32 ++++++++++++--------------------
1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/src/Client.cs b/src/Client.cs
index 40354de..f834bd2 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -140,6 +140,7 @@ namespace WTelegram
TcpHandler = cloneOf.TcpHandler;
MTProxyUrl = cloneOf.MTProxyUrl;
PingInterval = cloneOf.PingInterval;
+ MaxAutoReconnects = cloneOf.MaxAutoReconnects;
TLConfig = cloneOf.TLConfig;
_dcSession = dcSession;
}
@@ -561,7 +562,7 @@ namespace WTelegram
{
var keys = _dcSession.Salts.Keys;
if (keys[^1] == DateTime.MaxValue) return; // GetFutureSalts ongoing
- var now = DateTime.UtcNow.AddTicks(_dcSession.serverTicksOffset);
+ var now = DateTime.UtcNow.AddTicks(_dcSession.serverTicksOffset - TimeSpan.TicksPerMinute);
bool removed = false;
for (; keys.Count > 1 && keys[1] < now; _dcSession.OldSalt = _dcSession.Salt, _dcSession.Salt = _dcSession.Salts.Values[0], removed = true)
_dcSession.Salts.RemoveAt(0);
@@ -742,10 +743,7 @@ namespace WTelegram
case MsgsAck msgsAck:
break; // we don't do anything with these, for now
case BadMsgNotification badMsgNotification:
- await _sendSemaphore.WaitAsync();
- bool retryLast = badMsgNotification.bad_msg_id == _dcSession.lastSentMsgId;
- var lastSentMsg = _lastSentMsg;
- _sendSemaphore.Release();
+ bool retryRpcs = true;
var logLevel = badMsgNotification.error_code == 48 ? 2 : 4;
Helpers.Log(logLevel, $"BadMsgNotification {badMsgNotification.error_code} for msg #{(short)badMsgNotification.bad_msg_id.GetHashCode():X4}");
switch (badMsgNotification.error_code)
@@ -760,7 +758,7 @@ namespace WTelegram
case 32: // msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)
case 33: // msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)
if (_dcSession.seqno <= 1)
- retryLast = false;
+ retryRpcs = false;
else
{
await ResetAsync(false, false);
@@ -775,25 +773,19 @@ namespace WTelegram
CheckSalt();
break;
default:
- retryLast = false;
+ retryRpcs = false;
break;
}
- if (retryLast)
+ if (retryRpcs)
{
- Rpc prevRequest;
lock (_pendingRpcs)
- _pendingRpcs.TryGetValue(badMsgNotification.bad_msg_id, out prevRequest);
- await SendAsync(lastSentMsg, lastSentMsg is not MsgContainer, prevRequest);
- lock (_pendingRpcs)
- _pendingRpcs.Remove(badMsgNotification.bad_msg_id);
- }
- else if (PullPendingRequest(badMsgNotification.bad_msg_id) is Rpc rpc)
- {
- if (_bareRpc?.msgId == badMsgNotification.bad_msg_id) _bareRpc = null;
- rpc.tcs.SetException(new WTException($"BadMsgNotification {badMsgNotification.error_code}"));
- }
- else
+ {
+ foreach (var rpc in _pendingRpcs.Values)
+ rpc.tcs.TrySetResult(new RpcError { error_code = -503, error_message = $"BadMsgNotification {badMsgNotification.error_code}" });
+ _pendingRpcs.Clear();
+ }
RaiseUpdates(badMsgNotification);
+ }
break;
default:
RaiseUpdates(obj);
From fa90e236e704eec061f2942fb613413417d5d506 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Sun, 29 Jun 2025 16:42:27 +0200
Subject: [PATCH 22/68] Helpers to download animated photos (DownloadFileAsync
+ photo.LargestVideoSize)
---
src/Client.Helpers.cs | 12 ++++++++++++
src/TL.Xtended.cs | 3 ++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/Client.Helpers.cs b/src/Client.Helpers.cs
index eefcd36..a26210d 100644
--- a/src/Client.Helpers.cs
+++ b/src/Client.Helpers.cs
@@ -334,6 +334,18 @@ namespace WTelegram
return await DownloadFileAsync(fileLocation, outputStream, photo.dc_id, photoSize.FileSize, progress);
}
+ /// Download an animated photo from Telegram into the outputStream
+ /// The photo to download
+ /// Stream to write the file content to. This method does not close/dispose the stream
+ /// A specific size/version of the animated photo. Use photo.LargestVideoSize to download the largest version of the animated photo
+ /// (optional) Callback for tracking the progression of the transfer
+ /// The file type of the photo
+ public async Task DownloadFileAsync(Photo photo, Stream outputStream, VideoSize videoSize, ProgressCallback progress = null)
+ {
+ var fileLocation = photo.ToFileLocation(videoSize);
+ return await DownloadFileAsync(fileLocation, outputStream, photo.dc_id, videoSize.size, progress);
+ }
+
/// Download a document from Telegram into the outputStream
/// The document to download
/// Stream to write the file content to. This method does not close/dispose the stream
diff --git a/src/TL.Xtended.cs b/src/TL.Xtended.cs
index 30a2c39..630a370 100644
--- a/src/TL.Xtended.cs
+++ b/src/TL.Xtended.cs
@@ -348,8 +348,9 @@ namespace TL
protected override InputPhoto ToInputPhoto() => new() { id = id, access_hash = access_hash, file_reference = file_reference };
public InputPhotoFileLocation ToFileLocation() => ToFileLocation(LargestPhotoSize);
public InputPhotoFileLocation ToFileLocation(PhotoSizeBase photoSize) => new() { id = id, access_hash = access_hash, file_reference = file_reference, thumb_size = photoSize.Type };
- public InputDocumentFileLocation ToFileLocation(VideoSize videoSize) => new() { id = id, access_hash = access_hash, file_reference = file_reference, thumb_size = videoSize.type };
+ public InputPhotoFileLocation ToFileLocation(VideoSize videoSize) => new() { id = id, access_hash = access_hash, file_reference = file_reference, thumb_size = videoSize.type };
public PhotoSizeBase LargestPhotoSize => sizes.Aggregate((agg, next) => (long)next.Width * next.Height > (long)agg.Width * agg.Height ? next : agg);
+ public VideoSize LargestVideoSize => video_sizes?.OfType().DefaultIfEmpty().Aggregate((agg, next) => (long)next.w * next.h > (long)agg.w * agg.h ? next : agg);
}
partial class PhotoSizeBase
From 4f7954db6153eae5ead0b547df140c9bae9579a9 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Tue, 24 Jun 2025 19:25:30 +0200
Subject: [PATCH 23/68] API Layer 204: Channel DMs (MonoForum), Forum Tabs,
Saved peer/dialog stuff...
(for the very latest layers, go to https://patreon.com/wizou)
---
README.md | 2 +-
src/TL.Schema.cs | 106 +++++++++++++++++++++---
src/TL.SchemaFuncs.cs | 164 ++++++++++++++++++++++++++++++-------
src/TL.Table.cs | 20 +++--
src/WTelegramClient.csproj | 5 +-
5 files changed, 245 insertions(+), 52 deletions(-)
diff --git a/README.md b/README.md
index 557ce41..84117c0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://corefork.telegram.org/methods)
+[](https://corefork.telegram.org/methods)
[](https://www.nuget.org/packages/WTelegramClient/)
[](https://www.nuget.org/packages/WTelegramClient/absoluteLatest)
[](https://buymeacoffee.com/wizou)
diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs
index c05334e..0208090 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -1074,7 +1074,7 @@ namespace TL
public override string Title => title;
}
/// Channel/supergroup info See
- [TLDef(0x7482147E)]
+ [TLDef(0xFE685355)]
public sealed partial class Channel : ChatBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1119,6 +1119,7 @@ namespace TL
[IfFlag(43)] public DateTime subscription_until_date;
[IfFlag(45)] public long bot_verification_icon;
[IfFlag(46)] public long send_paid_messages_stars;
+ [IfFlag(50)] public long linked_monoforum_id;
[Flags] public enum Flags : uint
{
@@ -1205,6 +1206,11 @@ namespace TL
/// Field has a value
has_send_paid_messages_stars = 0x4000,
autotranslation = 0x8000,
+ broadcast_messages_allowed = 0x10000,
+ monoforum = 0x20000,
+ /// Field has a value
+ has_linked_monoforum_id = 0x40000,
+ forum_tabs = 0x80000,
}
/// ID of the channel, see here » for more info
@@ -2961,10 +2967,16 @@ namespace TL
public long stars;
}
/// See
- [TLDef(0xBCD71419)]
+ [TLDef(0x84B88578)]
public sealed partial class MessageActionPaidMessagesPrice : MessageAction
{
+ public Flags flags;
public long stars;
+
+ [Flags] public enum Flags : uint
+ {
+ broadcast_messages_allowed = 0x1,
+ }
}
/// See
[TLDef(0x2FFE2F7A)]
@@ -4650,7 +4662,7 @@ namespace TL
public int max_id;
}
/// Notifies a change of a message draft. See
- [TLDef(0x1B49EC6D)]
+ [TLDef(0xEDFC111E)]
public sealed partial class UpdateDraftMessage : Update
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -4659,6 +4671,7 @@ namespace TL
public Peer peer;
/// ID of the forum topic to which the draft is associated
[IfFlag(0)] public int top_msg_id;
+ [IfFlag(1)] public Peer saved_peer_id;
/// The draft
public DraftMessageBase draft;
@@ -4666,6 +4679,8 @@ namespace TL
{
/// Field has a value
has_top_msg_id = 0x1,
+ /// Field has a value
+ has_saved_peer_id = 0x2,
}
}
/// Some featured stickers were marked as read See
@@ -4812,7 +4827,7 @@ namespace TL
[TLDef(0xE511996D)]
public sealed partial class UpdateFavedStickers : Update { }
/// The specified channel/supergroup messages were read See
- [TLDef(0xEA29055D)]
+ [TLDef(0x25F324F7)]
public sealed partial class UpdateChannelReadMessagesContents : Update
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -4821,6 +4836,7 @@ namespace TL
public long channel_id;
/// Forum topic ID.
[IfFlag(0)] public int top_msg_id;
+ [IfFlag(1)] public Peer saved_peer_id;
/// IDs of messages that were read
public int[] messages;
@@ -4828,6 +4844,8 @@ namespace TL
{
/// Field has a value
has_top_msg_id = 0x1,
+ /// Field has a value
+ has_saved_peer_id = 0x2,
}
}
/// All contacts were deleted See
@@ -4841,18 +4859,21 @@ namespace TL
public int available_min_id;
}
/// The manual unread mark of a chat was changed See
- [TLDef(0xE16459C3)]
+ [TLDef(0xB658F23E)]
public sealed partial class UpdateDialogUnreadMark : Update
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// The dialog
public DialogPeerBase peer;
+ [IfFlag(1)] public Peer saved_peer_id;
[Flags] public enum Flags : uint
{
/// Was the chat marked or unmarked as read
unread = 0x1,
+ /// Field has a value
+ has_saved_peer_id = 0x2,
}
}
/// The results of a poll have changed See
@@ -5332,7 +5353,7 @@ namespace TL
public override (long, int, int) GetMBox() => (-1, qts, 1);
}
/// New message reactions » are available See
- [TLDef(0x5E1B3CB8)]
+ [TLDef(0x1E297BFA)]
public sealed partial class UpdateMessageReactions : Update
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -5343,6 +5364,7 @@ namespace TL
public int msg_id;
/// Forum topic ID
[IfFlag(0)] public int top_msg_id;
+ [IfFlag(1)] public Peer saved_peer_id;
/// Reactions
public MessageReactions reactions;
@@ -5350,6 +5372,8 @@ namespace TL
{
/// Field has a value
has_top_msg_id = 0x1,
+ /// Field has a value
+ has_saved_peer_id = 0x2,
}
}
/// The list of installed attachment menu entries » has changed, use Messages_GetAttachMenuBots to fetch the updated list. See
@@ -5852,6 +5876,22 @@ namespace TL
public byte[][] blocks;
public int next_offset;
}
+ /// See
+ [TLDef(0x77B0E372)]
+ public sealed partial class UpdateReadMonoForumInbox : Update
+ {
+ public long channel_id;
+ public Peer saved_peer_id;
+ public int read_max_id;
+ }
+ /// See
+ [TLDef(0xA4A79376)]
+ public sealed partial class UpdateReadMonoForumOutbox : Update
+ {
+ public long channel_id;
+ public Peer saved_peer_id;
+ public int read_max_id;
+ }
/// Updates state. See
[TLDef(0xA56C2A3E)]
@@ -17484,7 +17524,7 @@ namespace TL
/// Contains info about a message or story to reply to. See Derived classes: ,
public abstract partial class InputReplyTo : IObject { }
/// Reply to a message. See
- [TLDef(0x22C0F6D5)]
+ [TLDef(0xB07038B0)]
public sealed partial class InputReplyToMessage : InputReplyTo
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -17501,6 +17541,7 @@ namespace TL
[IfFlag(3)] public MessageEntity[] quote_entities;
/// Offset of the message quote_text within the original message (in UTF-16 code units).
[IfFlag(4)] public int quote_offset;
+ [IfFlag(5)] public InputPeer monoforum_peer_id;
[Flags] public enum Flags : uint
{
@@ -17514,6 +17555,8 @@ namespace TL
has_quote_entities = 0x8,
/// Field has a value
has_quote_offset = 0x10,
+ /// Field has a value
+ has_monoforum_peer_id = 0x20,
}
}
/// Reply to a story. See
@@ -17525,6 +17568,12 @@ namespace TL
/// ID of the story to reply to.
public int story_id;
}
+ /// See
+ [TLDef(0x69D66C45)]
+ public sealed partial class InputReplyToMonoForum : InputReplyTo
+ {
+ public InputPeer monoforum_peer_id;
+ }
/// Represents a story deep link. See
[TLDef(0x3FC9053B)]
@@ -18336,9 +18385,17 @@ namespace TL
public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
}
+ /// Represents a saved message dialog ». See Derived classes:
+ public abstract partial class SavedDialogBase : IObject
+ {
+ /// The dialog
+ public virtual Peer Peer => default;
+ /// The latest message ID
+ public virtual int TopMessage => default;
+ }
/// Represents a saved dialog ». See
[TLDef(0xBD87CB6C)]
- public sealed partial class SavedDialog : IObject
+ public sealed partial class SavedDialog : SavedDialogBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
@@ -18352,13 +18409,40 @@ namespace TL
/// Is the dialog pinned
pinned = 0x4,
}
+
+ /// The dialog
+ public override Peer Peer => peer;
+ /// The latest message ID
+ public override int TopMessage => top_message;
+ }
+ /// See
+ [TLDef(0x64407EA7)]
+ public sealed partial class MonoForumDialog : SavedDialogBase
+ {
+ public Flags flags;
+ public Peer peer;
+ public int top_message;
+ public int read_inbox_max_id;
+ public int read_outbox_max_id;
+ public int unread_count;
+ public int unread_reactions_count;
+ [IfFlag(1)] public DraftMessageBase draft;
+
+ [Flags] public enum Flags : uint
+ {
+ has_draft = 0x2,
+ unread_mark = 0x8,
+ }
+
+ public override Peer Peer => peer;
+ public override int TopMessage => top_message;
}
/// Represents some saved message dialogs ». See Derived classes: , ,
public abstract partial class Messages_SavedDialogsBase : IObject
{
/// Saved message dialogs ».
- public virtual SavedDialog[] Dialogs => default;
+ public virtual SavedDialogBase[] Dialogs => default;
/// List of last messages from each saved dialog
public virtual MessageBase[] Messages => default;
/// Mentioned chats
@@ -18371,7 +18455,7 @@ namespace TL
public partial class Messages_SavedDialogs : Messages_SavedDialogsBase, IPeerResolver
{
/// Saved message dialogs ».
- public SavedDialog[] dialogs;
+ public SavedDialogBase[] dialogs;
/// List of last messages from each saved dialog
public MessageBase[] messages;
/// Mentioned chats
@@ -18380,7 +18464,7 @@ namespace TL
public Dictionary users;
/// Saved message dialogs ».
- public override SavedDialog[] Dialogs => dialogs;
+ public override SavedDialogBase[] Dialogs => dialogs;
/// List of last messages from each saved dialog
public override MessageBase[] Messages => messages;
/// Mentioned chats
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index e872cc4..2cc521c 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1972,15 +1972,16 @@ namespace TL
/// Scheduled message date for scheduled messages
/// Forward the messages as the specified peer
/// Add the messages to the specified quick reply shortcut », instead.
- public static Task Messages_ForwardMessages(this Client client, InputPeer from_peer, int[] id, long[] random_id, InputPeer to_peer, int? top_msg_id = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, int? video_timestamp = null, long? allow_paid_stars = null, bool silent = false, bool background = false, bool with_my_score = false, bool drop_author = false, bool drop_media_captions = false, bool noforwards = false, bool allow_paid_floodskip = false)
+ public static Task Messages_ForwardMessages(this Client client, InputPeer from_peer, int[] id, long[] random_id, InputPeer to_peer, int? top_msg_id = null, DateTime? schedule_date = null, InputPeer send_as = null, InputQuickReplyShortcutBase quick_reply_shortcut = null, int? video_timestamp = null, long? allow_paid_stars = null, InputReplyTo reply_to = null, bool silent = false, bool background = false, bool with_my_score = false, bool drop_author = false, bool drop_media_captions = false, bool noforwards = false, bool allow_paid_floodskip = false)
=> client.Invoke(new Messages_ForwardMessages
{
- flags = (Messages_ForwardMessages.Flags)((top_msg_id != null ? 0x200 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (video_timestamp != null ? 0x100000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (with_my_score ? 0x100 : 0) | (drop_author ? 0x800 : 0) | (drop_media_captions ? 0x1000 : 0) | (noforwards ? 0x4000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
+ flags = (Messages_ForwardMessages.Flags)((top_msg_id != null ? 0x200 : 0) | (schedule_date != null ? 0x400 : 0) | (send_as != null ? 0x2000 : 0) | (quick_reply_shortcut != null ? 0x20000 : 0) | (video_timestamp != null ? 0x100000 : 0) | (allow_paid_stars != null ? 0x200000 : 0) | (reply_to != null ? 0x400000 : 0) | (silent ? 0x20 : 0) | (background ? 0x40 : 0) | (with_my_score ? 0x100 : 0) | (drop_author ? 0x800 : 0) | (drop_media_captions ? 0x1000 : 0) | (noforwards ? 0x4000 : 0) | (allow_paid_floodskip ? 0x80000 : 0)),
from_peer = from_peer,
id = id,
random_id = random_id,
to_peer = to_peer,
top_msg_id = top_msg_id ?? default,
+ reply_to = reply_to,
schedule_date = schedule_date ?? default,
send_as = send_as,
quick_reply_shortcut = quick_reply_shortcut,
@@ -2978,17 +2979,20 @@ namespace TL
/// Manually mark dialog as unread See Possible codes: 400 (details)
/// Mark as unread/read
/// Dialog
- public static Task Messages_MarkDialogUnread(this Client client, InputDialogPeerBase peer, bool unread = false)
+ public static Task Messages_MarkDialogUnread(this Client client, InputDialogPeerBase peer, InputPeer parent_peer = null, bool unread = false)
=> client.Invoke(new Messages_MarkDialogUnread
{
- flags = (Messages_MarkDialogUnread.Flags)(unread ? 0x1 : 0),
+ flags = (Messages_MarkDialogUnread.Flags)((parent_peer != null ? 0x2 : 0) | (unread ? 0x1 : 0)),
+ parent_peer = parent_peer,
peer = peer,
});
/// Get dialogs manually marked as unread See
- public static Task Messages_GetDialogUnreadMarks(this Client client)
+ public static Task Messages_GetDialogUnreadMarks(this Client client, InputPeer parent_peer = null)
=> client.Invoke(new Messages_GetDialogUnreadMarks
{
+ flags = (Messages_GetDialogUnreadMarks.Flags)(parent_peer != null ? 0x1 : 0),
+ parent_peer = parent_peer,
});
/// Clear all drafts. See