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 01/56] 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 02/56] 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 03/56] 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 04/56] 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 05/56] 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 06/56] 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 07/56] 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 08/56] 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 09/56] 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 10/56] 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 11/56] 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
@@ -3312,12 +3316,13 @@ namespace TL
/// Unpin all pinned messages See [bots: ✓] Possible codes: 400 (details)
/// Chat where to unpin
/// Forum topic where to unpin
- public static Task Messages_UnpinAllMessages(this Client client, InputPeer peer, int? top_msg_id = null)
+ public static Task Messages_UnpinAllMessages(this Client client, InputPeer peer, int? top_msg_id = null, InputPeer saved_peer_id = null)
=> client.InvokeAffected(new Messages_UnpinAllMessages
{
- flags = (Messages_UnpinAllMessages.Flags)(top_msg_id != null ? 0x1 : 0),
+ flags = (Messages_UnpinAllMessages.Flags)((top_msg_id != null ? 0x1 : 0) | (saved_peer_id != null ? 0x2 : 0)),
peer = peer,
top_msg_id = top_msg_id ?? default,
+ saved_peer_id = saved_peer_id,
}, peer is InputPeerChannel ipc ? ipc.channel_id : 0);
/// ⚠ 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 Delete a chat See Possible codes: 400 (details)
@@ -3691,12 +3696,13 @@ namespace TL
/// Maximum number of results to return, see pagination
/// Only return reactions for messages up until this message ID
/// Only return reactions for messages starting from this message ID
- public static Task Messages_GetUnreadReactions(this Client client, InputPeer peer, int offset_id = default, int add_offset = default, int limit = int.MaxValue, int max_id = default, int min_id = default, int? top_msg_id = null)
+ public static Task Messages_GetUnreadReactions(this Client client, InputPeer peer, int offset_id = default, int add_offset = default, int limit = int.MaxValue, int max_id = default, int min_id = default, int? top_msg_id = null, InputPeer saved_peer_id = null)
=> client.Invoke(new Messages_GetUnreadReactions
{
- flags = (Messages_GetUnreadReactions.Flags)(top_msg_id != null ? 0x1 : 0),
+ flags = (Messages_GetUnreadReactions.Flags)((top_msg_id != null ? 0x1 : 0) | (saved_peer_id != null ? 0x2 : 0)),
peer = peer,
top_msg_id = top_msg_id ?? default,
+ saved_peer_id = saved_peer_id,
offset_id = offset_id,
add_offset = add_offset,
limit = limit,
@@ -3707,12 +3713,13 @@ namespace TL
/// Mark message reactions » as read See Possible codes: 400 (details)
/// Peer
/// Mark as read only reactions to messages within the specified forum topic
- public static Task Messages_ReadReactions(this Client client, InputPeer peer, int? top_msg_id = null)
+ public static Task Messages_ReadReactions(this Client client, InputPeer peer, int? top_msg_id = null, InputPeer saved_peer_id = null)
=> client.InvokeAffected(new Messages_ReadReactions
{
- flags = (Messages_ReadReactions.Flags)(top_msg_id != null ? 0x1 : 0),
+ flags = (Messages_ReadReactions.Flags)((top_msg_id != null ? 0x1 : 0) | (saved_peer_id != null ? 0x2 : 0)),
peer = peer,
top_msg_id = top_msg_id ?? default,
+ saved_peer_id = saved_peer_id,
}, peer is InputPeerChannel ipc ? ipc.channel_id : 0);
/// View and search recently sent media.
This method does not support pagination. See Possible codes: 400 (details)
@@ -4088,10 +4095,11 @@ namespace TL
/// Offset peer for pagination
/// Number of list elements to be returned
/// Hash used for caching, for more info click here
- public static Task Messages_GetSavedDialogs(this Client client, DateTime offset_date = default, int offset_id = default, InputPeer offset_peer = null, int limit = int.MaxValue, long hash = default, bool exclude_pinned = false)
+ public static Task Messages_GetSavedDialogs(this Client client, DateTime offset_date = default, int offset_id = default, InputPeer offset_peer = null, int limit = int.MaxValue, long hash = default, InputPeer parent_peer = null, bool exclude_pinned = false)
=> client.Invoke(new Messages_GetSavedDialogs
{
- flags = (Messages_GetSavedDialogs.Flags)(exclude_pinned ? 0x1 : 0),
+ flags = (Messages_GetSavedDialogs.Flags)((parent_peer != null ? 0x2 : 0) | (exclude_pinned ? 0x1 : 0)),
+ parent_peer = parent_peer,
offset_date = offset_date,
offset_id = offset_id,
offset_peer = offset_peer,
@@ -4108,9 +4116,11 @@ namespace TL
/// If a positive value was transferred, the method will return only messages with IDs less than max_id
/// If a positive value was transferred, the method will return only messages with IDs more than min_id
/// Result hash
- public static Task Messages_GetSavedHistory(this Client client, InputPeer peer, int offset_id = default, DateTime offset_date = default, int add_offset = default, int limit = int.MaxValue, int max_id = default, int min_id = default, long hash = default)
+ public static Task Messages_GetSavedHistory(this Client client, InputPeer peer, int offset_id = default, DateTime offset_date = default, int add_offset = default, int limit = int.MaxValue, int max_id = default, int min_id = default, long hash = default, InputPeer parent_peer = null)
=> client.Invoke(new Messages_GetSavedHistory
{
+ flags = (Messages_GetSavedHistory.Flags)(parent_peer != null ? 0x1 : 0),
+ parent_peer = parent_peer,
peer = peer,
offset_id = offset_id,
offset_date = offset_date,
@@ -4126,10 +4136,11 @@ namespace TL
/// Maximum ID of message to delete
/// Delete all messages newer than this UNIX timestamp
/// Delete all messages older than this UNIX timestamp
- public static Task Messages_DeleteSavedHistory(this Client client, InputPeer peer, int max_id = default, DateTime? min_date = null, DateTime? max_date = null)
+ public static Task Messages_DeleteSavedHistory(this Client client, InputPeer peer, int max_id = default, InputPeer parent_peer = null, DateTime? min_date = null, DateTime? max_date = null)
=> client.InvokeAffected(new Messages_DeleteSavedHistory
{
- flags = (Messages_DeleteSavedHistory.Flags)((min_date != null ? 0x4 : 0) | (max_date != null ? 0x8 : 0)),
+ flags = (Messages_DeleteSavedHistory.Flags)((parent_peer != null ? 0x1 : 0) | (min_date != null ? 0x4 : 0) | (max_date != null ? 0x8 : 0)),
+ parent_peer = parent_peer,
peer = peer,
max_id = max_id,
min_date = min_date ?? default,
@@ -4496,6 +4507,24 @@ namespace TL
id = id,
});
+ /// See
+ public static Task Messages_GetSavedDialogsByID(this Client client, InputPeer[] ids, InputPeer parent_peer = null)
+ => client.Invoke(new Messages_GetSavedDialogsByID
+ {
+ flags = (Messages_GetSavedDialogsByID.Flags)(parent_peer != null ? 0x2 : 0),
+ parent_peer = parent_peer,
+ ids = ids,
+ });
+
+ /// See
+ public static Task Messages_ReadSavedHistory(this Client client, InputPeer parent_peer, InputPeer peer, int max_id = default)
+ => client.Invoke(new Messages_ReadSavedHistory
+ {
+ parent_peer = parent_peer,
+ peer = peer,
+ max_id = max_id,
+ });
+
/// Returns a current state of updates. See [bots: ✓]
public static Task Updates_GetState(this Client client)
=> client.Invoke(new Updates_GetState
@@ -5352,11 +5381,12 @@ namespace TL
/// Enable or disable forum functionality in a supergroup. See Possible codes: 400 (details)
/// Supergroup ID
/// Enable or disable forum functionality
- public static Task Channels_ToggleForum(this Client client, InputChannelBase channel, bool enabled)
+ public static Task Channels_ToggleForum(this Client client, InputChannelBase channel, bool enabled, bool tabs)
=> client.Invoke(new Channels_ToggleForum
{
channel = channel,
enabled = enabled,
+ tabs = tabs,
});
/// Create a forum topic; requires manage_topics rights. See [bots: ✓] Possible codes: 400,403 (details)
@@ -5580,9 +5610,10 @@ namespace TL
});
/// See
- public static Task Channels_UpdatePaidMessagesPrice(this Client client, InputChannelBase channel, long send_paid_messages_stars)
+ public static Task Channels_UpdatePaidMessagesPrice(this Client client, InputChannelBase channel, long send_paid_messages_stars, bool broadcast_messages_allowed = false)
=> client.Invoke(new Channels_UpdatePaidMessagesPrice
{
+ flags = (Channels_UpdatePaidMessagesPrice.Flags)(broadcast_messages_allowed ? 0x1 : 0),
channel = channel,
send_paid_messages_stars = send_paid_messages_stars,
});
@@ -5595,6 +5626,14 @@ namespace TL
enabled = enabled,
});
+ /// See
+ public static Task Channels_GetMessageAuthor(this Client client, InputChannelBase channel, int id)
+ => client.Invoke(new Channels_GetMessageAuthor
+ {
+ channel = channel,
+ id = id,
+ });
+
/// Sends a custom request; for bots only See [bots: ✓] Possible codes: 400,403 (details)
/// The method name
/// JSON-serialized method parameters
@@ -9238,7 +9277,7 @@ namespace TL.Methods
}
}
- [TLDef(0xBB9FA475)]
+ [TLDef(0x38F0188C)]
public sealed partial class Messages_ForwardMessages : IMethod
{
public Flags flags;
@@ -9247,6 +9286,7 @@ namespace TL.Methods
public long[] random_id;
public InputPeer to_peer;
[IfFlag(9)] public int top_msg_id;
+ [IfFlag(22)] public InputReplyTo reply_to;
[IfFlag(10)] public DateTime schedule_date;
[IfFlag(13)] public InputPeer send_as;
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
@@ -9268,6 +9308,7 @@ namespace TL.Methods
allow_paid_floodskip = 0x80000,
has_video_timestamp = 0x100000,
has_allow_paid_stars = 0x200000,
+ has_reply_to = 0x400000,
}
}
@@ -10131,20 +10172,31 @@ namespace TL.Methods
[TLDef(0x1CFF7E08)]
public sealed partial class Messages_GetSplitRanges : IMethod { }
- [TLDef(0xC286D98F)]
+ [TLDef(0x8C5006F8)]
public sealed partial class Messages_MarkDialogUnread : IMethod
{
public Flags flags;
+ [IfFlag(1)] public InputPeer parent_peer;
public InputDialogPeerBase peer;
[Flags] public enum Flags : uint
{
unread = 0x1,
+ has_parent_peer = 0x2,
}
}
- [TLDef(0x22E24E22)]
- public sealed partial class Messages_GetDialogUnreadMarks : IMethod { }
+ [TLDef(0x21202222)]
+ public sealed partial class Messages_GetDialogUnreadMarks : IMethod
+ {
+ public Flags flags;
+ [IfFlag(0)] public InputPeer parent_peer;
+
+ [Flags] public enum Flags : uint
+ {
+ has_parent_peer = 0x1,
+ }
+ }
[TLDef(0x7E58EE9C)]
public sealed partial class Messages_ClearAllDrafts : IMethod { }
@@ -10400,16 +10452,18 @@ namespace TL.Methods
public int read_max_id;
}
- [TLDef(0xEE22B9A8)]
+ [TLDef(0x062DD747)]
public sealed partial class Messages_UnpinAllMessages : IMethod
{
public Flags flags;
public InputPeer peer;
[IfFlag(0)] public int top_msg_id;
+ [IfFlag(1)] public InputPeer saved_peer_id;
[Flags] public enum Flags : uint
{
has_top_msg_id = 0x1,
+ has_saved_peer_id = 0x2,
}
}
@@ -10729,12 +10783,13 @@ namespace TL.Methods
}
}
- [TLDef(0x3223495B)]
+ [TLDef(0xBD7F90AC)]
public sealed partial class Messages_GetUnreadReactions : IMethod
{
public Flags flags;
public InputPeer peer;
[IfFlag(0)] public int top_msg_id;
+ [IfFlag(1)] public InputPeer saved_peer_id;
public int offset_id;
public int add_offset;
public int limit;
@@ -10744,19 +10799,22 @@ namespace TL.Methods
[Flags] public enum Flags : uint
{
has_top_msg_id = 0x1,
+ has_saved_peer_id = 0x2,
}
}
- [TLDef(0x54AA7F8E)]
+ [TLDef(0x9EC44F93)]
public sealed partial class Messages_ReadReactions : IMethod
{
public Flags flags;
public InputPeer peer;
[IfFlag(0)] public int top_msg_id;
+ [IfFlag(1)] public InputPeer saved_peer_id;
[Flags] public enum Flags : uint
{
has_top_msg_id = 0x1,
+ has_saved_peer_id = 0x2,
}
}
@@ -11056,10 +11114,11 @@ namespace TL.Methods
}
}
- [TLDef(0x5381D21A)]
+ [TLDef(0x1E91FC99)]
public sealed partial class Messages_GetSavedDialogs : IMethod
{
public Flags flags;
+ [IfFlag(1)] public InputPeer parent_peer;
public DateTime offset_date;
public int offset_id;
public InputPeer offset_peer;
@@ -11069,12 +11128,15 @@ namespace TL.Methods
[Flags] public enum Flags : uint
{
exclude_pinned = 0x1,
+ has_parent_peer = 0x2,
}
}
- [TLDef(0x3D9A414D)]
+ [TLDef(0x998AB009)]
public sealed partial class Messages_GetSavedHistory : IMethod
{
+ public Flags flags;
+ [IfFlag(0)] public InputPeer parent_peer;
public InputPeer peer;
public int offset_id;
public DateTime offset_date;
@@ -11083,12 +11145,18 @@ namespace TL.Methods
public int max_id;
public int min_id;
public long hash;
+
+ [Flags] public enum Flags : uint
+ {
+ has_parent_peer = 0x1,
+ }
}
- [TLDef(0x6E98102B)]
+ [TLDef(0x4DC5085F)]
public sealed partial class Messages_DeleteSavedHistory : IMethod
{
public Flags flags;
+ [IfFlag(0)] public InputPeer parent_peer;
public InputPeer peer;
public int max_id;
[IfFlag(2)] public DateTime min_date;
@@ -11096,6 +11164,7 @@ namespace TL.Methods
[Flags] public enum Flags : uint
{
+ has_parent_peer = 0x1,
has_min_date = 0x4,
has_max_date = 0x8,
}
@@ -11404,6 +11473,27 @@ namespace TL.Methods
}
}
+ [TLDef(0x6F6F9C96)]
+ public sealed partial class Messages_GetSavedDialogsByID : IMethod
+ {
+ public Flags flags;
+ [IfFlag(1)] public InputPeer parent_peer;
+ public InputPeer[] ids;
+
+ [Flags] public enum Flags : uint
+ {
+ has_parent_peer = 0x2,
+ }
+ }
+
+ [TLDef(0xBA4A3B5B)]
+ public sealed partial class Messages_ReadSavedHistory : IMethod
+ {
+ public InputPeer parent_peer;
+ public InputPeer peer;
+ public int max_id;
+ }
+
[TLDef(0xEDD4882A)]
public sealed partial class Updates_GetState : IMethod { }
@@ -12053,11 +12143,12 @@ namespace TL.Methods
public InputChannelBase channel;
}
- [TLDef(0xA4298B29)]
+ [TLDef(0x3FF75734)]
public sealed partial class Channels_ToggleForum : IMethod
{
public InputChannelBase channel;
public bool enabled;
+ public bool tabs;
}
[TLDef(0xF40C0224)]
@@ -12245,11 +12336,17 @@ namespace TL.Methods
public int limit;
}
- [TLDef(0xFC84653F)]
+ [TLDef(0x4B12327B)]
public sealed partial class Channels_UpdatePaidMessagesPrice : IMethod
{
+ public Flags flags;
public InputChannelBase channel;
public long send_paid_messages_stars;
+
+ [Flags] public enum Flags : uint
+ {
+ broadcast_messages_allowed = 0x1,
+ }
}
[TLDef(0x167FC0A1)]
@@ -12259,6 +12356,13 @@ namespace TL.Methods
public bool enabled;
}
+ [TLDef(0xECE2A0E6)]
+ public sealed partial class Channels_GetMessageAuthor : IMethod
+ {
+ public InputChannelBase channel;
+ public int id;
+ }
+
[TLDef(0xAA2769ED)]
public sealed partial class Bots_SendCustomRequest : IMethod
{
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 8e52198..9cba0d9 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 = 203; // fetched 14/05/2025 16:07:47
+ public const int Version = 204; // fetched 04/06/2025 15:07:47
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -136,7 +136,7 @@ namespace TL
[0x29562865] = typeof(ChatEmpty),
[0x41CBF256] = typeof(Chat),
[0x6592A1A7] = typeof(ChatForbidden),
- [0x7482147E] = typeof(Channel),
+ [0xFE685355] = typeof(Channel),
[0x17D493D5] = typeof(ChannelForbidden),
[0x2633421B] = typeof(ChatFull),
[0x52D6806B] = typeof(ChannelFull),
@@ -216,7 +216,7 @@ namespace TL
[0x4717E8A4] = typeof(MessageActionStarGift),
[0x2E3AE60E] = typeof(MessageActionStarGiftUnique),
[0xAC1F1FCD] = typeof(MessageActionPaidMessagesRefunded),
- [0xBCD71419] = typeof(MessageActionPaidMessagesPrice),
+ [0x84B88578] = typeof(MessageActionPaidMessagesPrice),
[0x2FFE2F7A] = typeof(MessageActionConferenceCall),
[0xD58A08C6] = typeof(Dialog),
[0x71BD134C] = typeof(DialogFolder),
@@ -325,7 +325,7 @@ namespace TL
[0xE40370A3] = typeof(UpdateEditMessage),
[0x691E9052] = typeof(UpdateInlineBotCallbackQuery),
[0xB75F99A9] = typeof(UpdateReadChannelOutbox),
- [0x1B49EC6D] = typeof(UpdateDraftMessage),
+ [0xEDFC111E] = typeof(UpdateDraftMessage),
[0x571D2742] = typeof(UpdateReadFeaturedStickers),
[0x9A422C20] = typeof(UpdateRecentStickers),
[0xA229DD06] = typeof(UpdateConfig),
@@ -341,10 +341,10 @@ namespace TL
[0x46560264] = typeof(UpdateLangPackTooLong),
[0x56022F4D] = typeof(UpdateLangPack),
[0xE511996D] = typeof(UpdateFavedStickers),
- [0xEA29055D] = typeof(UpdateChannelReadMessagesContents),
+ [0x25F324F7] = typeof(UpdateChannelReadMessagesContents),
[0x7084A7BE] = typeof(UpdateContactsReset),
[0xB23FC698] = typeof(UpdateChannelAvailableMessages),
- [0xE16459C3] = typeof(UpdateDialogUnreadMark),
+ [0xB658F23E] = typeof(UpdateDialogUnreadMark),
[0xACA1657B] = typeof(UpdateMessagePoll),
[0x54C01850] = typeof(UpdateChatDefaultBannedRights),
[0x19360DC0] = typeof(UpdateFolderPeers),
@@ -378,7 +378,7 @@ namespace TL
[0x4D712F2E] = typeof(UpdateBotCommands),
[0x7063C3DB] = typeof(UpdatePendingJoinRequests),
[0x11DFA986] = typeof(UpdateBotChatInviteRequester),
- [0x5E1B3CB8] = typeof(UpdateMessageReactions),
+ [0x1E297BFA] = typeof(UpdateMessageReactions),
[0x17B7A20B] = typeof(UpdateAttachMenuBots),
[0x1592B79D] = typeof(UpdateWebViewResultSent),
[0x14B85813] = typeof(UpdateBotMenuButton),
@@ -426,6 +426,8 @@ namespace TL
[0x8B725FCE] = typeof(UpdatePaidReactionPrivacy),
[0x504AA18F] = typeof(UpdateSentPhoneCode),
[0xA477288F] = typeof(UpdateGroupCallChainBlocks),
+ [0x77B0E372] = typeof(UpdateReadMonoForumInbox),
+ [0xA4A79376] = typeof(UpdateReadMonoForumOutbox),
[0xA56C2A3E] = typeof(Updates_State),
[0x5D75A138] = typeof(Updates_DifferenceEmpty),
[0x00F49CA0] = typeof(Updates_Difference),
@@ -1211,8 +1213,9 @@ namespace TL
[0xBD74CF49] = typeof(StoryViewPublicRepost),
[0x59D78FC5] = typeof(Stories_StoryViewsList),
[0xDE9EED1D] = typeof(Stories_StoryViews),
- [0x22C0F6D5] = typeof(InputReplyToMessage),
+ [0xB07038B0] = typeof(InputReplyToMessage),
[0x5881323A] = typeof(InputReplyToStory),
+ [0x69D66C45] = typeof(InputReplyToMonoForum),
[0x3FC9053B] = typeof(ExportedStoryLink),
[0x712E27FD] = typeof(StoriesStealthMode),
[0xCFC9E002] = typeof(MediaAreaCoordinates),
@@ -1257,6 +1260,7 @@ namespace TL
[0xCFCD0F13] = typeof(StoryReactionPublicRepost),
[0xAA5F789C] = typeof(Stories_StoryReactionsList),
[0xBD87CB6C] = typeof(SavedDialog),
+ [0x64407EA7] = typeof(MonoForumDialog),
[0xF83AE221] = typeof(Messages_SavedDialogs),
[0x44BA9DD9] = typeof(Messages_SavedDialogsSlice),
[0xC01F6FE8] = typeof(Messages_SavedDialogsNotModified),
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 2a71dd9..1c5aa10 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -11,9 +11,10 @@
snupkg
true
WTelegramClient
- 0.0.0
+ 0.0.0
+ layer.204
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 203
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 204
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From bdcf389ed22655dc4defd0ab452e203aa7f36952 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Tue, 8 Jul 2025 19:47:44 +0200
Subject: [PATCH 12/56] API Layer 206: ToDo lists, suggested posts, choose TON
vs Stars for gifts/transactions, ...
(for the very latest layers, go to https://patreon.com/wizou)
---
README.md | 2 +-
src/TL.Schema.cs | 356 +++++++++++++++++++++++--------------
src/TL.SchemaFuncs.cs | 264 ++++++++++++++++-----------
src/TL.Table.cs | 41 +++--
src/WTelegramClient.csproj | 6 +-
5 files changed, 416 insertions(+), 253 deletions(-)
diff --git a/README.md b/README.md
index 84117c0..838b958 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 0208090..367010b 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -507,6 +507,12 @@ namespace TL
has_payload = 0x1,
}
}
+ /// See
+ [TLDef(0x9FC55FDE)]
+ public sealed partial class InputMediaTodo : InputMedia
+ {
+ public TodoList todo;
+ }
/// Defines a new group profile photo. See Derived classes: ,
/// a value means inputChatPhotoEmpty
@@ -1394,7 +1400,7 @@ namespace TL
public override int ReactionsLimit => reactions_limit;
}
/// Full info about a channel, supergroup or gigagroup. See
- [TLDef(0x52D6806B)]
+ [TLDef(0xE07429DE)]
public sealed partial class ChannelFull : ChatFullBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1485,6 +1491,7 @@ namespace TL
[IfFlag(42)] public StickerSet emojiset;
[IfFlag(49)] public BotVerification bot_verification;
[IfFlag(50)] public int stargifts_count;
+ [IfFlag(53)] public long send_paid_messages_stars;
[Flags] public enum Flags : uint
{
@@ -1594,6 +1601,8 @@ namespace TL
has_stargifts_count = 0x40000,
stargifts_available = 0x80000,
paid_messages_available = 0x100000,
+ /// Field has a value
+ has_send_paid_messages_stars = 0x200000,
}
/// ID of the channel
@@ -1739,6 +1748,8 @@ namespace TL
public virtual Peer From => default;
/// Peer ID, the chat where this message was sent
public virtual Peer Peer => default;
+ /// Messages fetched from a saved messages dialog » will have peer= and the saved_peer_id flag set to the ID of the saved dialog.
+ public virtual Peer SavedPeer => default;
/// Reply information
public virtual MessageReplyHeaderBase ReplyTo => default;
/// Date of the message
@@ -1771,7 +1782,7 @@ namespace TL
public override Peer Peer => peer_id;
}
/// A message See
- [TLDef(0xEABCDD4D)]
+ [TLDef(0x9815CEC8)]
public sealed partial class Message : MessageBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1832,6 +1843,7 @@ namespace TL
[IfFlag(35)] public FactCheck factcheck;
[IfFlag(37)] public DateTime report_delivery_until_date;
[IfFlag(38)] public long paid_message_stars;
+ [IfFlag(39)] public SuggestedPost suggested_post;
[Flags] public enum Flags : uint
{
@@ -1911,6 +1923,10 @@ namespace TL
has_report_delivery_until_date = 0x20,
/// Field has a value
has_paid_message_stars = 0x40,
+ /// Field has a value
+ has_suggested_post = 0x80,
+ paid_suggested_post_stars = 0x100,
+ paid_suggested_post_ton = 0x200,
}
/// ID of the message
@@ -1919,6 +1935,8 @@ namespace TL
public override Peer From => from_id;
/// Peer ID, the chat where this message was sent
public override Peer Peer => peer_id;
+ /// Messages fetched from a saved messages dialog » will have peer= and the saved_peer_id flag set to the ID of the saved dialog.
+ public override Peer SavedPeer => saved_peer_id;
/// Reply information
public override MessageReplyHeaderBase ReplyTo => reply_to;
/// Date of the message
@@ -1929,7 +1947,7 @@ namespace TL
public override int TtlPeriod => ttl_period;
}
/// Indicates a service message See
- [TLDef(0xD3D28540)]
+ [TLDef(0x7A800E0A)]
public sealed partial class MessageService : MessageBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -1940,6 +1958,7 @@ namespace TL
[IfFlag(8)] public Peer from_id;
/// Sender of service message
public Peer peer_id;
+ [IfFlag(28)] public Peer saved_peer_id;
/// Reply (thread) information
[IfFlag(3)] public MessageReplyHeaderBase reply_to;
/// Message date
@@ -1973,6 +1992,8 @@ namespace TL
has_reactions = 0x100000,
/// Field has a value
has_ttl_period = 0x2000000,
+ /// Field has a value
+ has_saved_peer_id = 0x10000000,
}
/// Message ID
@@ -1981,6 +2002,7 @@ namespace TL
public override Peer From => from_id;
/// Sender of service message
public override Peer Peer => peer_id;
+ public override Peer SavedPeer => saved_peer_id;
/// Reply (thread) information
public override MessageReplyHeaderBase ReplyTo => reply_to;
/// Message date
@@ -2311,6 +2333,19 @@ namespace TL
/// Either the paid-for media, or super low resolution media previews if the media wasn't purchased yet, see here » for more info.
public MessageExtendedMediaBase[] extended_media;
}
+ /// See
+ [TLDef(0x8A53B014)]
+ public sealed partial class MessageMediaToDo : MessageMedia
+ {
+ public Flags flags;
+ public TodoList todo;
+ [IfFlag(0)] public TodoCompletion[] completions;
+
+ [Flags] public enum Flags : uint
+ {
+ has_completions = 0x1,
+ }
+ }
/// Object describing actions connected to a service message. See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
/// a value means messageActionEmpty
@@ -2996,6 +3031,70 @@ namespace TL
video = 0x10,
}
}
+ /// See
+ [TLDef(0xCC7C5C89)]
+ public sealed partial class MessageActionTodoCompletions : MessageAction
+ {
+ public int[] completed;
+ public int[] incompleted;
+ }
+ /// See
+ [TLDef(0xC7EDBC83)]
+ public sealed partial class MessageActionTodoAppendTasks : MessageAction
+ {
+ public TodoItem[] list;
+ }
+ /// See
+ [TLDef(0xEE7A1596)]
+ public sealed partial class MessageActionSuggestedPostApproval : MessageAction
+ {
+ public Flags flags;
+ [IfFlag(2)] public string reject_comment;
+ [IfFlag(3)] public DateTime schedule_date;
+ [IfFlag(4)] public StarsAmountBase price;
+
+ [Flags] public enum Flags : uint
+ {
+ rejected = 0x1,
+ balance_too_low = 0x2,
+ has_reject_comment = 0x4,
+ has_schedule_date = 0x8,
+ has_price = 0x10,
+ }
+ }
+ /// See
+ [TLDef(0x95DDCF69)]
+ public sealed partial class MessageActionSuggestedPostSuccess : MessageAction
+ {
+ public StarsAmountBase price;
+ }
+ /// See
+ [TLDef(0x69F916F8)]
+ public sealed partial class MessageActionSuggestedPostRefund : MessageAction
+ {
+ public Flags flags;
+
+ [Flags] public enum Flags : uint
+ {
+ payer_initiated = 0x1,
+ }
+ }
+ /// See
+ [TLDef(0xA8A3C699)]
+ public sealed partial class MessageActionGiftTon : MessageAction
+ {
+ public Flags flags;
+ public string currency;
+ public long amount;
+ public string crypto_currency;
+ public long crypto_amount;
+ [IfFlag(0)] public string transaction_id;
+
+ [Flags] public enum Flags : uint
+ {
+ has_transaction_id = 0x1,
+ }
+ }
/// Chat info. See Derived classes: ,
public abstract partial class DialogBase : IObject
@@ -5787,21 +5886,12 @@ namespace TL
/// The reaction.
public Reaction reaction;
}
- /// A new channel ad revenue transaction was made, see here » for more info. See
- [TLDef(0xDFD961F5)]
- public sealed partial class UpdateBroadcastRevenueTransactions : Update
- {
- /// Channel
- public Peer peer;
- /// New ad revenue balance.
- public BroadcastRevenueBalances balances;
- }
/// The current account's Telegram Stars balance » has changed. See
[TLDef(0x4E80A379)]
public sealed partial class UpdateStarsBalance : Update
{
/// New balance.
- public StarsAmount balance;
+ public StarsAmountBase balance;
}
/// A callback button sent via a business connection was pressed, and the button data was sent to the bot that created the button. See
[TLDef(0x1EA2FDA7)]
@@ -5892,6 +5982,19 @@ namespace TL
public Peer saved_peer_id;
public int read_max_id;
}
+ /// See
+ [TLDef(0x9F812B08)]
+ public sealed partial class UpdateMonoForumNoPaidException : Update
+ {
+ public Flags flags;
+ public long channel_id;
+ public Peer saved_peer_id;
+
+ [Flags] public enum Flags : uint
+ {
+ exception = 0x1,
+ }
+ }
/// Updates state. See
[TLDef(0xA56C2A3E)]
@@ -7872,6 +7975,9 @@ namespace TL
/// Default custom emoji status stickerset for channel statuses See
[TLDef(0x49748553)]
public sealed partial class InputStickerSetEmojiChannelDefaultStatuses : InputStickerSet { }
+ /// See
+ [TLDef(0x1CF671A0)]
+ public sealed partial class InputStickerSetTonGifts : InputStickerSet { }
/// Represents a stickerset (stickerpack) See
[TLDef(0x2DD14EDC)]
@@ -9893,7 +9999,7 @@ namespace TL
}
}
/// Represents a message draft. See
- [TLDef(0x2D65321F)]
+ [TLDef(0x96EAA5EB)]
public sealed partial class DraftMessage : DraftMessageBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -9910,6 +10016,7 @@ namespace TL
public DateTime date;
/// A message effect that should be played as specified here ».
[IfFlag(7)] public long effect;
+ [IfFlag(8)] public SuggestedPost suggested_post;
[Flags] public enum Flags : uint
{
@@ -9925,6 +10032,8 @@ namespace TL
invert_media = 0x40,
/// Field has a value
has_effect = 0x80,
+ /// Field has a value
+ has_suggested_post = 0x100,
}
}
@@ -13444,6 +13553,7 @@ namespace TL
edit_stories = 0x8000,
/// If set, allows the admin to delete stories posted by the other admins of the channel.
delete_stories = 0x10000,
+ manage_direct_messages = 0x20000,
}
}
@@ -15354,7 +15464,7 @@ namespace TL
public sealed partial class Account_ResetPasswordOk : Account_ResetPasswordResult { }
/// A sponsored message. See
- [TLDef(0x4D93A990)]
+ [TLDef(0x7DBF8673)]
public sealed partial class SponsoredMessage : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -15381,6 +15491,8 @@ namespace TL
[IfFlag(7)] public string sponsor_info;
/// If set, contains additional information about the sponsored message to be shown along with the message.
[IfFlag(8)] public string additional_info;
+ [IfFlag(15)] public int min_display_duration;
+ [IfFlag(15)] public int max_display_duration;
[Flags] public enum Flags : uint
{
@@ -15400,18 +15512,22 @@ namespace TL
has_color = 0x2000,
/// Field has a value
has_media = 0x4000,
+ /// Fields and have a value
+ has_min_display_duration = 0x8000,
}
}
/// A set of sponsored messages associated to a channel See
/// a value means messages.sponsoredMessagesEmpty
- [TLDef(0xC9EE1D87)]
+ [TLDef(0xFFDA656D)]
public sealed partial class Messages_SponsoredMessages : IObject, IPeerResolver
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// If set, specifies the minimum number of messages between shown sponsored messages; otherwise, only one sponsored message must be shown after all ordinary messages.
[IfFlag(0)] public int posts_between;
+ [IfFlag(1)] public int start_delay;
+ [IfFlag(2)] public int between_delay;
/// Sponsored messages
public SponsoredMessage[] messages;
/// Chats mentioned in the sponsored messages
@@ -15423,6 +15539,10 @@ namespace TL
{
/// Field has a value
has_posts_between = 0x1,
+ /// Field has a value
+ has_start_delay = 0x2,
+ /// Field has a value
+ has_between_delay = 0x4,
}
/// returns a or for the given Peer
public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
@@ -18432,6 +18552,7 @@ namespace TL
{
has_draft = 0x2,
unread_mark = 0x8,
+ nopaid_messages_exception = 0x10,
}
public override Peer Peer => peer;
@@ -19306,90 +19427,6 @@ namespace TL
[TLDef(0xAD798849)]
public sealed partial class Channels_SponsoredMessageReportResultReported : Channels_SponsoredMessageReportResult { }
- /// Channel revenue ad statistics, see here » for more info. See
- [TLDef(0x5407E297)]
- public sealed partial class Stats_BroadcastRevenueStats : IObject
- {
- /// Ad impressions graph
- public StatsGraphBase top_hours_graph;
- /// Ad revenue graph (in the smallest unit of the cryptocurrency in which revenue is calculated)
- public StatsGraphBase revenue_graph;
- /// Current balance, current withdrawable balance and overall revenue
- public BroadcastRevenueBalances balances;
- /// Current conversion rate of the cryptocurrency (not in the smallest unit) in which revenue is calculated to USD
- public double usd_rate;
- }
-
- /// Contains the URL to use to withdraw channel ad revenue. See
- [TLDef(0xEC659737)]
- public sealed partial class Stats_BroadcastRevenueWithdrawalUrl : IObject
- {
- /// A unique URL to a Fragment page where the user will be able to specify and submit the address of the TON wallet where the funds will be sent.
- public string url;
- }
-
- /// A channel ad revenue » transaction. See Derived classes: , ,
- public abstract partial class BroadcastRevenueTransaction : IObject { }
- /// Describes earnings from sponsored messages in a channel in some time frame, see here » for more info. See
- [TLDef(0x557E2CC4)]
- public sealed partial class BroadcastRevenueTransactionProceeds : BroadcastRevenueTransaction
- {
- /// Amount in the smallest unit of the cryptocurrency.
- public long amount;
- /// Start unixtime for the timeframe.
- public DateTime from_date;
- /// End unixtime for the timeframe.
- public DateTime to_date;
- }
- /// Describes a withdrawal of ad earnings » See
- [TLDef(0x5A590978)]
- public sealed partial class BroadcastRevenueTransactionWithdrawal : BroadcastRevenueTransaction
- {
- /// Extra bits of information, use flags.HasFlag(...) to test for those
- public Flags flags;
- /// Amount withdrawn
- public long amount;
- /// Withdrawal date
- public DateTime date;
- /// Payment provider name
- public string provider;
- /// If neither pending nor failed are set, the transaction was completed successfully, and this field will contain the point in time (Unix timestamp) when the withdrawal was completed successfully.
- [IfFlag(1)] public DateTime transaction_date;
- /// If neither pending nor failed are set, the transaction was completed successfully, and this field will contain a URL where the withdrawal transaction can be viewed.
- [IfFlag(1)] public string transaction_url;
-
- [Flags] public enum Flags : uint
- {
- /// Whether the withdrawal is currently pending
- pending = 0x1,
- /// Fields and have a value
- has_transaction_date = 0x2,
- /// Whether the withdrawal has failed
- failed = 0x4,
- }
- }
- /// Describes a refund for failed withdrawal of ad earnings » See
- [TLDef(0x42D30D2E)]
- public sealed partial class BroadcastRevenueTransactionRefund : BroadcastRevenueTransaction
- {
- /// Amount refunded.
- public long amount;
- /// Date of refund.
- public DateTime date;
- /// Payment provider name.
- public string provider;
- }
-
- /// Channel ad revenue transactions ». See
- [TLDef(0x87158466)]
- public sealed partial class Stats_BroadcastRevenueTransactions : IObject
- {
- /// Total number of transactions.
- public int count;
- /// Transactions
- public BroadcastRevenueTransaction[] transactions;
- }
-
/// Reaction notification settings See
public enum ReactionNotificationsFrom : uint
{
@@ -19423,26 +19460,6 @@ namespace TL
}
}
- /// Describes channel ad revenue balances ». See
- [TLDef(0xC3FF71E7)]
- public sealed partial class BroadcastRevenueBalances : IObject
- {
- /// Extra bits of information, use flags.HasFlag(...) to test for those
- public Flags flags;
- /// Amount of not-yet-withdrawn cryptocurrency.
- public long current_balance;
- /// Amount of withdrawable cryptocurrency, out of the currently available balance (available_balance <= current_balance).
- public long available_balance;
- /// Total amount of earned cryptocurrency.
- public long overall_revenue;
-
- [Flags] public enum Flags : uint
- {
- /// If set, the available balance can be withdrawn ».
- withdrawal_enabled = 0x1,
- }
- }
-
/// Represents a message effect ». See
[TLDef(0x93C3E27E)]
public sealed partial class AvailableEffect : IObject
@@ -19562,15 +19579,14 @@ namespace TL
}
/// Represents a Telegram Stars transaction ». See
- [TLDef(0xA39FD94A)]
+ [TLDef(0x13659EB0)]
public sealed partial class StarsTransaction : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// Transaction ID.
public string id;
- /// Amount of Stars (negative for outgoing transactions).
- public StarsAmount stars;
+ public StarsAmountBase amount;
/// Date of the transaction (unixtime).
public DateTime date;
/// Source of the incoming transaction, or its recipient for outgoing transactions.
@@ -19604,9 +19620,11 @@ namespace TL
/// For transactions made by referred users, the peer that received the affiliate commission.
[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(17)] public StarsAmountBase starref_amount;
[IfFlag(19)] public int paid_messages;
[IfFlag(20)] public int premium_gift_months;
+ [IfFlag(23)] public DateTime ads_proceeds_from_date;
+ [IfFlag(23)] public DateTime ads_proceeds_to_date;
[Flags] public enum Flags : uint
{
@@ -19653,6 +19671,8 @@ namespace TL
has_premium_gift_months = 0x100000,
business_transfer = 0x200000,
stargift_resale = 0x400000,
+ /// Fields and have a value
+ has_ads_proceeds_from_date = 0x800000,
}
}
@@ -19663,7 +19683,7 @@ namespace TL
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// Current Telegram Star balance.
- public StarsAmount balance;
+ public StarsAmountBase balance;
/// Info about current Telegram Star subscriptions, only returned when invoking Payments_GetStarsTransactions and Payments_GetStarsSubscriptions.
[IfFlag(1)] public StarsSubscription[] subscriptions;
/// Offset for pagination of subscriptions: only usable and returned when invoking Payments_GetStarsSubscriptions.
@@ -19765,11 +19785,11 @@ namespace TL
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// Amount of not-yet-withdrawn Telegram Stars.
- public StarsAmount current_balance;
+ public StarsAmountBase current_balance;
/// Amount of withdrawable Telegram Stars.
- public StarsAmount available_balance;
+ public StarsAmountBase available_balance;
/// Total amount of earned Telegram Stars.
- public StarsAmount overall_revenue;
+ public StarsAmountBase overall_revenue;
/// Unixtime indicating when will withdrawal be available to the user. If not set, withdrawal can be started now.
[IfFlag(1)] public int next_withdrawal_at;
@@ -19783,15 +19803,23 @@ namespace TL
}
/// Star revenue statistics, see here » for more info. See
- [TLDef(0xC92BB73B)]
+ [TLDef(0x6C207376)]
public sealed partial class Payments_StarsRevenueStats : IObject
{
+ public Flags flags;
+ [IfFlag(0)] public StatsGraphBase top_hours_graph;
/// Star revenue graph (number of earned stars)
public StatsGraphBase revenue_graph;
/// Current balance, current withdrawable balance and overall earned Telegram Stars
public StarsRevenueStatus status;
/// Current conversion rate of Telegram Stars to USD
public double usd_rate;
+
+ [Flags] public enum Flags : uint
+ {
+ /// Field has a value
+ has_top_hours_graph = 0x1,
+ }
}
/// Contains the URL to use to withdraw Telegram Star revenue. See
@@ -20228,7 +20256,7 @@ namespace TL
/// 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.
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;
+ [IfFlag(2)] public StarsAmountBase daily_revenue_per_user;
[Flags] public enum Flags : uint
{
@@ -20305,14 +20333,31 @@ namespace TL
}
}
+ /// Describes a real (i.e. possibly decimal) amount of Telegram Stars. See Derived classes:
+ public abstract partial class StarsAmountBase : IObject
+ {
+ /// The integer amount of Telegram Stars.
+ public virtual long Amount => default;
+ }
/// Describes a real (i.e. possibly decimal) amount of Telegram Stars. See
[TLDef(0xBBB6B4A3)]
- public sealed partial class StarsAmount : IObject
+ public sealed partial class StarsAmount : StarsAmountBase
{
/// The integer amount of Telegram Stars.
public long amount;
/// The decimal amount of Telegram Stars, expressed as nanostars (i.e. 1 nanostar is equal to 1/1'000'000'000th of a Telegram Star).
This field may also be negative (the allowed range is -999999999 to 999999999).
public int nanos;
+
+ /// The integer amount of Telegram Stars.
+ public override long Amount => amount;
+ }
+ /// See
+ [TLDef(0x74AEE3E0)]
+ public sealed partial class StarsTonAmount : StarsAmountBase
+ {
+ public long amount;
+
+ public override long Amount => amount;
}
/// Found stickers See Derived classes: ,
@@ -20719,4 +20764,53 @@ namespace TL
public TextWithEntities description;
public string url;
}
+
+ /// See
+ [TLDef(0xCBA9A52F)]
+ public sealed partial class TodoItem : IObject
+ {
+ public int id;
+ public TextWithEntities title;
+ }
+
+ /// See
+ [TLDef(0x49B92A26)]
+ public sealed partial class TodoList : IObject
+ {
+ public Flags flags;
+ public TextWithEntities title;
+ public TodoItem[] list;
+
+ [Flags] public enum Flags : uint
+ {
+ others_can_append = 0x1,
+ others_can_complete = 0x2,
+ }
+ }
+
+ /// See
+ [TLDef(0x4CC120B7)]
+ public sealed partial class TodoCompletion : IObject
+ {
+ public int id;
+ public long completed_by;
+ public DateTime date;
+ }
+
+ /// See
+ [TLDef(0x0E8E37E5)]
+ public sealed partial class SuggestedPost : IObject
+ {
+ public Flags flags;
+ [IfFlag(3)] public StarsAmountBase price;
+ [IfFlag(0)] public DateTime schedule_date;
+
+ [Flags] public enum Flags : uint
+ {
+ has_schedule_date = 0x1,
+ accepted = 0x2,
+ rejected = 0x4,
+ has_price = 0x8,
+ }
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 2cc521c..0845d54 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1433,18 +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
+ /// See
+ public static Task Account_GetPaidMessagesRevenue(this Client client, InputUserBase user_id, InputPeer parent_peer = null)
+ => client.Invoke(new Account_GetPaidMessagesRevenue
{
- flags = (Account_AddNoPaidMessagesException.Flags)(refund_charged ? 0x1 : 0),
+ flags = (Account_GetPaidMessagesRevenue.Flags)(parent_peer != null ? 0x1 : 0),
+ parent_peer = parent_peer,
user_id = user_id,
});
- /// See
- public static Task Account_GetPaidMessagesRevenue(this Client client, InputUserBase user_id)
- => client.Invoke(new Account_GetPaidMessagesRevenue
+ /// See
+ public static Task Account_ToggleNoPaidMessagesException(this Client client, InputUserBase user_id, InputPeer parent_peer = null, bool refund_charged = false, bool require_payment = false)
+ => client.Invoke(new Account_ToggleNoPaidMessagesException
{
+ flags = (Account_ToggleNoPaidMessagesException.Flags)((parent_peer != null ? 0x2 : 0) | (refund_charged ? 0x1 : 0) | (require_payment ? 0x4 : 0)),
+ parent_peer = parent_peer,
user_id = user_id,
});
@@ -1902,10 +1905,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, 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)
+ 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, SuggestedPost suggested_post = 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) | (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)),
+ 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) | (suggested_post != null ? 0x400000 : 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,
@@ -1917,6 +1920,7 @@ namespace TL
quick_reply_shortcut = quick_reply_shortcut,
effect = effect ?? default,
allow_paid_stars = allow_paid_stars ?? default,
+ suggested_post = suggested_post,
});
/// Send a media See [bots: ✓] Possible codes: 400,403,406,420,500 (details)
@@ -1938,10 +1942,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, 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)
+ 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, SuggestedPost suggested_post = 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) | (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)),
+ 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) | (suggested_post != null ? 0x400000 : 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,
@@ -1954,6 +1958,7 @@ namespace TL
quick_reply_shortcut = quick_reply_shortcut,
effect = effect ?? default,
allow_paid_stars = allow_paid_stars ?? default,
+ suggested_post = suggested_post,
});
/// Forwards messages by their IDs. See [bots: ✓] Possible codes: 400,403,406,420,500 (details)
@@ -1972,10 +1977,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, 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)
+ 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, SuggestedPost suggested_post = 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) | (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)),
+ 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) | (suggested_post != null ? 0x800000 : 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,
@@ -1987,6 +1992,7 @@ namespace TL
quick_reply_shortcut = quick_reply_shortcut,
video_timestamp = video_timestamp ?? default,
allow_paid_stars = allow_paid_stars ?? default,
+ suggested_post = suggested_post,
});
/// Report a new incoming chat for spam, if the of the chat allow us to do that See Possible codes: 400 (details)
@@ -2602,16 +2608,17 @@ namespace TL
/// Message entities for styled text
/// Attached media
/// Specifies a message effect » to use for the message.
- public static Task Messages_SaveDraft(this Client client, InputPeer peer, string message, MessageEntity[] entities = null, InputReplyTo reply_to = null, InputMedia media = null, long? effect = null, bool no_webpage = false, bool invert_media = false)
+ public static Task Messages_SaveDraft(this Client client, InputPeer peer, string message, MessageEntity[] entities = null, InputReplyTo reply_to = null, InputMedia media = null, long? effect = null, SuggestedPost suggested_post = null, bool no_webpage = false, bool invert_media = false)
=> client.Invoke(new Messages_SaveDraft
{
- flags = (Messages_SaveDraft.Flags)((entities != null ? 0x8 : 0) | (reply_to != null ? 0x10 : 0) | (media != null ? 0x20 : 0) | (effect != null ? 0x80 : 0) | (no_webpage ? 0x2 : 0) | (invert_media ? 0x40 : 0)),
+ flags = (Messages_SaveDraft.Flags)((entities != null ? 0x8 : 0) | (reply_to != null ? 0x10 : 0) | (media != null ? 0x20 : 0) | (effect != null ? 0x80 : 0) | (suggested_post != null ? 0x100 : 0) | (no_webpage ? 0x2 : 0) | (invert_media ? 0x40 : 0)),
reply_to = reply_to,
peer = peer,
message = message,
entities = entities,
media = media,
effect = effect ?? default,
+ suggested_post = suggested_post,
});
/// Return all message drafts.
Returns all the latest updates related to all chats with drafts. See
@@ -4449,10 +4456,12 @@ namespace TL
/// Get a list of sponsored messages for a peer, see here » for more info. See
/// The currently open channel/bot.
/// a null value means messages.sponsoredMessagesEmpty
- public static Task Messages_GetSponsoredMessages(this Client client, InputPeer peer)
+ public static Task Messages_GetSponsoredMessages(this Client client, InputPeer peer, int? msg_id = null)
=> client.Invoke(new Messages_GetSponsoredMessages
{
+ flags = (Messages_GetSponsoredMessages.Flags)(msg_id != null ? 0x1 : 0),
peer = peer,
+ msg_id = msg_id ?? default,
});
/// Save a prepared inline message, to be shared by the user of the mini app using a web_app_send_prepared_message event See [bots: ✓] Possible codes: 400 (details)
@@ -4525,6 +4534,36 @@ namespace TL
max_id = max_id,
});
+ /// See
+ public static Task Messages_ToggleTodoCompleted(this Client client, InputPeer peer, int msg_id, int[] completed, params int[] incompleted)
+ => client.Invoke(new Messages_ToggleTodoCompleted
+ {
+ peer = peer,
+ msg_id = msg_id,
+ completed = completed,
+ incompleted = incompleted,
+ });
+
+ /// See
+ public static Task Messages_AppendTodoList(this Client client, InputPeer peer, int msg_id, params TodoItem[] list)
+ => client.Invoke(new Messages_AppendTodoList
+ {
+ peer = peer,
+ msg_id = msg_id,
+ list = list,
+ });
+
+ /// See
+ public static Task Messages_ToggleSuggestedPostApproval(this Client client, InputPeer peer, int msg_id, DateTime? schedule_date = null, string reject_comment = null, bool reject = false)
+ => client.Invoke(new Messages_ToggleSuggestedPostApproval
+ {
+ flags = (Messages_ToggleSuggestedPostApproval.Flags)((schedule_date != null ? 0x1 : 0) | (reject_comment != null ? 0x4 : 0) | (reject ? 0x2 : 0)),
+ peer = peer,
+ msg_id = msg_id,
+ schedule_date = schedule_date ?? default,
+ reject_comment = reject_comment,
+ });
+
/// Returns a current state of updates. See [bots: ✓]
public static Task Updates_GetState(this Client client)
=> client.Invoke(new Updates_GetState
@@ -6103,9 +6142,10 @@ namespace TL
/// Get the current Telegram Stars balance of the current account (with peer=), or the stars balance of the bot specified in peer. See Possible codes: 400 (details)
/// Peer of which to get the balance.
- public static Task Payments_GetStarsStatus(this Client client, InputPeer peer)
+ public static Task Payments_GetStarsStatus(this Client client, InputPeer peer, bool ton = false)
=> client.Invoke(new Payments_GetStarsStatus
{
+ flags = (Payments_GetStarsStatus.Flags)(ton ? 0x1 : 0),
peer = peer,
});
@@ -6117,10 +6157,10 @@ namespace TL
/// Fetch the transaction history of the peer ( or a bot we own).
/// Offset for pagination, obtained from the returned next_offset, initially an empty string ».
/// Maximum number of results to return, see pagination
- public static Task Payments_GetStarsTransactions(this Client client, InputPeer peer, string offset, int limit = int.MaxValue, string subscription_id = null, bool inbound = false, bool outbound = false, bool ascending = false)
+ public static Task Payments_GetStarsTransactions(this Client client, InputPeer peer, string offset, int limit = int.MaxValue, string subscription_id = null, bool inbound = false, bool outbound = false, bool ascending = false, bool ton = false)
=> client.Invoke(new Payments_GetStarsTransactions
{
- flags = (Payments_GetStarsTransactions.Flags)((subscription_id != null ? 0x8 : 0) | (inbound ? 0x1 : 0) | (outbound ? 0x2 : 0) | (ascending ? 0x4 : 0)),
+ flags = (Payments_GetStarsTransactions.Flags)((subscription_id != null ? 0x8 : 0) | (inbound ? 0x1 : 0) | (outbound ? 0x2 : 0) | (ascending ? 0x4 : 0) | (ton ? 0x10 : 0)),
subscription_id = subscription_id,
peer = peer,
offset = offset,
@@ -6150,22 +6190,22 @@ namespace TL
/// Get Telegram Star revenue statistics ». See Possible codes: 400 (details)
/// Whether to enable dark theme for graph colors
/// Get statistics for the specified bot, channel or ourselves ().
- public static Task Payments_GetStarsRevenueStats(this Client client, InputPeer peer, bool dark = false)
+ public static Task Payments_GetStarsRevenueStats(this Client client, InputPeer peer, bool dark = false, bool ton = false)
=> client.Invoke(new Payments_GetStarsRevenueStats
{
- flags = (Payments_GetStarsRevenueStats.Flags)(dark ? 0x1 : 0),
+ flags = (Payments_GetStarsRevenueStats.Flags)((dark ? 0x1 : 0) | (ton ? 0x2 : 0)),
peer = peer,
});
/// Withdraw funds from a channel or bot's star balance ». See Possible codes: 400 (details)
/// Channel or bot from which to withdraw funds.
- /// Amount of stars to withdraw.
/// 2FA password, see here » for more info.
- public static Task Payments_GetStarsRevenueWithdrawalUrl(this Client client, InputPeer peer, long stars, InputCheckPasswordSRP password)
+ public static Task Payments_GetStarsRevenueWithdrawalUrl(this Client client, InputPeer peer, InputCheckPasswordSRP password, long? amount = null, bool ton = false)
=> client.Invoke(new Payments_GetStarsRevenueWithdrawalUrl
{
+ flags = (Payments_GetStarsRevenueWithdrawalUrl.Flags)((amount != null ? 0x2 : 0) | (ton ? 0x1 : 0)),
peer = peer,
- stars = stars,
+ amount = amount ?? default,
password = password,
});
@@ -6180,9 +6220,10 @@ namespace TL
/// Obtain info about Telegram Star transactions » using specific transaction IDs. See Possible codes: 400 (details)
/// Channel or bot.
/// Transaction IDs.
- public static Task Payments_GetStarsTransactionsByID(this Client client, InputPeer peer, params InputStarsTransaction[] id)
+ public static Task Payments_GetStarsTransactionsByID(this Client client, InputPeer peer, InputStarsTransaction[] id, bool ton = false)
=> client.Invoke(new Payments_GetStarsTransactionsByID
{
+ flags = (Payments_GetStarsTransactionsByID.Flags)(ton ? 0x1 : 0),
peer = peer,
id = id,
});
@@ -7119,38 +7160,6 @@ namespace TL
limit = limit,
});
- /// Get channel ad revenue statistics ». See Possible codes: 400 (details)
- /// Whether to enable dark theme for graph colors
- /// Get ad revenue stats for the specified channel or bot
- public static Task Stats_GetBroadcastRevenueStats(this Client client, InputPeer peer, bool dark = false)
- => client.Invoke(new Stats_GetBroadcastRevenueStats
- {
- flags = (Stats_GetBroadcastRevenueStats.Flags)(dark ? 0x1 : 0),
- peer = peer,
- });
-
- /// Withdraw funds from a channel's ad revenue balance ». See Possible codes: 400 (details)
- /// Get ad revenue withdrawal URL for the specified channel or bot
- /// 2FA password, see here » for more info.
- public static Task Stats_GetBroadcastRevenueWithdrawalUrl(this Client client, InputPeer peer, InputCheckPasswordSRP password)
- => client.Invoke(new Stats_GetBroadcastRevenueWithdrawalUrl
- {
- peer = peer,
- password = password,
- });
-
- /// Fetch channel ad revenue transaction history ». See Possible codes: 400 (details)
- /// Get ad revenue transactions for the specified channel or bot
- /// Offset for pagination
- /// Maximum number of results to return, see pagination
- public static Task Stats_GetBroadcastRevenueTransactions(this Client client, InputPeer peer, int offset = default, int limit = int.MaxValue)
- => client.Invoke(new Stats_GetBroadcastRevenueTransactions
- {
- peer = peer,
- offset = offset,
- limit = limit,
- });
-
/// Export a folder », creating a chat folder deep link ». See Possible codes: 400 (details)
/// The folder to export
/// An optional name for the link
@@ -8814,24 +8823,34 @@ namespace TL.Methods
public long hash;
}
- [TLDef(0x6F688AA7)]
- public sealed partial class Account_AddNoPaidMessagesException : IMethod
+ [TLDef(0x19BA4A67)]
+ public sealed partial class Account_GetPaidMessagesRevenue : IMethod
{
public Flags flags;
+ [IfFlag(0)] public InputPeer parent_peer;
+ public InputUserBase user_id;
+
+ [Flags] public enum Flags : uint
+ {
+ has_parent_peer = 0x1,
+ }
+ }
+
+ [TLDef(0xFE2EDA76)]
+ public sealed partial class Account_ToggleNoPaidMessagesException : IMethod
+ {
+ public Flags flags;
+ [IfFlag(1)] public InputPeer parent_peer;
public InputUserBase user_id;
[Flags] public enum Flags : uint
{
refund_charged = 0x1,
+ has_parent_peer = 0x2,
+ require_payment = 0x4,
}
}
- [TLDef(0xF1266F38)]
- public sealed partial class Account_GetPaidMessagesRevenue : IMethod
- {
- public InputUserBase user_id;
- }
-
[TLDef(0x0D91A548)]
public sealed partial class Users_GetUsers : IMethod
{
@@ -9203,7 +9222,7 @@ namespace TL.Methods
}
}
- [TLDef(0xFBF2340A)]
+ [TLDef(0xFE05DC9A)]
public sealed partial class Messages_SendMessage : IMethod
{
public Flags flags;
@@ -9218,6 +9237,7 @@ namespace TL.Methods
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(18)] public long effect;
[IfFlag(21)] public long allow_paid_stars;
+ [IfFlag(22)] public SuggestedPost suggested_post;
[Flags] public enum Flags : uint
{
@@ -9237,10 +9257,11 @@ namespace TL.Methods
has_effect = 0x40000,
allow_paid_floodskip = 0x80000,
has_allow_paid_stars = 0x200000,
+ has_suggested_post = 0x400000,
}
}
- [TLDef(0xA550CD78)]
+ [TLDef(0xAC55D9C1)]
public sealed partial class Messages_SendMedia : IMethod
{
public Flags flags;
@@ -9256,6 +9277,7 @@ namespace TL.Methods
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(18)] public long effect;
[IfFlag(21)] public long allow_paid_stars;
+ [IfFlag(22)] public SuggestedPost suggested_post;
[Flags] public enum Flags : uint
{
@@ -9274,10 +9296,11 @@ namespace TL.Methods
has_effect = 0x40000,
allow_paid_floodskip = 0x80000,
has_allow_paid_stars = 0x200000,
+ has_suggested_post = 0x400000,
}
}
- [TLDef(0x38F0188C)]
+ [TLDef(0x978928CA)]
public sealed partial class Messages_ForwardMessages : IMethod
{
public Flags flags;
@@ -9292,6 +9315,7 @@ namespace TL.Methods
[IfFlag(17)] public InputQuickReplyShortcutBase quick_reply_shortcut;
[IfFlag(20)] public int video_timestamp;
[IfFlag(21)] public long allow_paid_stars;
+ [IfFlag(23)] public SuggestedPost suggested_post;
[Flags] public enum Flags : uint
{
@@ -9309,6 +9333,7 @@ namespace TL.Methods
has_video_timestamp = 0x100000,
has_allow_paid_stars = 0x200000,
has_reply_to = 0x400000,
+ has_suggested_post = 0x800000,
}
}
@@ -9824,7 +9849,7 @@ namespace TL.Methods
public InputDialogPeerBase[] peers;
}
- [TLDef(0xD372C5CE)]
+ [TLDef(0x54AE308E)]
public sealed partial class Messages_SaveDraft : IMethod
{
public Flags flags;
@@ -9834,6 +9859,7 @@ namespace TL.Methods
[IfFlag(3)] public MessageEntity[] entities;
[IfFlag(5)] public InputMedia media;
[IfFlag(7)] public long effect;
+ [IfFlag(8)] public SuggestedPost suggested_post;
[Flags] public enum Flags : uint
{
@@ -9843,6 +9869,7 @@ namespace TL.Methods
has_media = 0x20,
invert_media = 0x40,
has_effect = 0x80,
+ has_suggested_post = 0x100,
}
}
@@ -11416,10 +11443,17 @@ namespace TL.Methods
public byte[] option;
}
- [TLDef(0x9BD2F439)]
+ [TLDef(0x3D6CE850)]
public sealed partial class Messages_GetSponsoredMessages : IMethod
{
+ public Flags flags;
public InputPeer peer;
+ [IfFlag(0)] public int msg_id;
+
+ [Flags] public enum Flags : uint
+ {
+ has_msg_id = 0x1,
+ }
}
[TLDef(0xF21F7F2F)]
@@ -11494,6 +11528,40 @@ namespace TL.Methods
public int max_id;
}
+ [TLDef(0xD3E03124)]
+ public sealed partial class Messages_ToggleTodoCompleted : IMethod
+ {
+ public InputPeer peer;
+ public int msg_id;
+ public int[] completed;
+ public int[] incompleted;
+ }
+
+ [TLDef(0x21A61057)]
+ public sealed partial class Messages_AppendTodoList : IMethod
+ {
+ public InputPeer peer;
+ public int msg_id;
+ public TodoItem[] list;
+ }
+
+ [TLDef(0x8107455C)]
+ public sealed partial class Messages_ToggleSuggestedPostApproval : IMethod
+ {
+ public Flags flags;
+ public InputPeer peer;
+ public int msg_id;
+ [IfFlag(0)] public DateTime schedule_date;
+ [IfFlag(2)] public string reject_comment;
+
+ [Flags] public enum Flags : uint
+ {
+ has_schedule_date = 0x1,
+ reject = 0x2,
+ has_reject_comment = 0x4,
+ }
+ }
+
[TLDef(0xEDD4882A)]
public sealed partial class Updates_GetState : IMethod { }
@@ -12740,10 +12808,16 @@ namespace TL.Methods
[TLDef(0xC00EC7D3)]
public sealed partial class Payments_GetStarsTopupOptions : IMethod { }
- [TLDef(0x104FCFA7)]
+ [TLDef(0x4EA9B3BF)]
public sealed partial class Payments_GetStarsStatus : IMethod
{
+ public Flags flags;
public InputPeer peer;
+
+ [Flags] public enum Flags : uint
+ {
+ ton = 0x1,
+ }
}
[TLDef(0x69DA4557)]
@@ -12761,6 +12835,7 @@ namespace TL.Methods
outbound = 0x2,
ascending = 0x4,
has_subscription_id = 0x8,
+ ton = 0x10,
}
}
@@ -12787,15 +12862,23 @@ namespace TL.Methods
[Flags] public enum Flags : uint
{
dark = 0x1,
+ ton = 0x2,
}
}
- [TLDef(0x13BBE8B3)]
+ [TLDef(0x2433DC92)]
public sealed partial class Payments_GetStarsRevenueWithdrawalUrl : IMethod
{
+ public Flags flags;
public InputPeer peer;
- public long stars;
+ [IfFlag(1)] public long amount;
public InputCheckPasswordSRP password;
+
+ [Flags] public enum Flags : uint
+ {
+ ton = 0x1,
+ has_amount = 0x2,
+ }
}
[TLDef(0xD1D7EFC5)]
@@ -12804,11 +12887,17 @@ namespace TL.Methods
public InputPeer peer;
}
- [TLDef(0x27842D2E)]
+ [TLDef(0x2DCA16B8)]
public sealed partial class Payments_GetStarsTransactionsByID : IMethod
{
+ public Flags flags;
public InputPeer peer;
public InputStarsTransaction[] id;
+
+ [Flags] public enum Flags : uint
+ {
+ ton = 0x1,
+ }
}
[TLDef(0xD3C96BC8)]
@@ -13660,33 +13749,6 @@ namespace TL.Methods
public int limit;
}
- [TLDef(0xF788EE19)]
- public sealed partial class Stats_GetBroadcastRevenueStats : IMethod
- {
- public Flags flags;
- public InputPeer peer;
-
- [Flags] public enum Flags : uint
- {
- dark = 0x1,
- }
- }
-
- [TLDef(0x9DF4FAAD)]
- public sealed partial class Stats_GetBroadcastRevenueWithdrawalUrl : IMethod
- {
- public InputPeer peer;
- public InputCheckPasswordSRP password;
- }
-
- [TLDef(0x70990B6D)]
- public sealed partial class Stats_GetBroadcastRevenueTransactions : IMethod
- {
- public InputPeer peer;
- public int offset;
- public int limit;
- }
-
[TLDef(0x8472478E)]
public sealed partial class Chatlists_ExportChatlistInvite : IMethod
{
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 9cba0d9..11bbf49 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 = 204; // fetched 04/06/2025 15:07:47
+ public const int Version = 206; // fetched 02/07/2025 12:40:29
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -103,6 +103,7 @@ namespace TL
[0x89FDD778] = typeof(InputMediaStory),
[0xC21B8849] = typeof(InputMediaWebPage),
[0xC4103386] = typeof(InputMediaPaidMedia),
+ [0x9FC55FDE] = typeof(InputMediaTodo),
[0x1CA48F57] = null,//InputChatPhotoEmpty
[0xBDCDAEC0] = typeof(InputChatUploadedPhoto),
[0x8953AD37] = typeof(InputChatPhoto),
@@ -139,7 +140,7 @@ namespace TL
[0xFE685355] = typeof(Channel),
[0x17D493D5] = typeof(ChannelForbidden),
[0x2633421B] = typeof(ChatFull),
- [0x52D6806B] = typeof(ChannelFull),
+ [0xE07429DE] = typeof(ChannelFull),
[0xC02D4007] = typeof(ChatParticipant),
[0xE46BCEE4] = typeof(ChatParticipantCreator),
[0xA0933F5B] = typeof(ChatParticipantAdmin),
@@ -148,8 +149,8 @@ namespace TL
[0x37C1011C] = null,//ChatPhotoEmpty
[0x1C6E1C11] = typeof(ChatPhoto),
[0x90A6CA84] = typeof(MessageEmpty),
- [0xEABCDD4D] = typeof(Message),
- [0xD3D28540] = typeof(MessageService),
+ [0x9815CEC8] = typeof(Message),
+ [0x7A800E0A] = typeof(MessageService),
[0x3DED6320] = null,//MessageMediaEmpty
[0x695150D7] = typeof(MessageMediaPhoto),
[0x56E0D474] = typeof(MessageMediaGeo),
@@ -167,6 +168,7 @@ namespace TL
[0xAA073BEB] = typeof(MessageMediaGiveaway),
[0xCEAA3EA1] = typeof(MessageMediaGiveawayResults),
[0xA8852491] = typeof(MessageMediaPaidMedia),
+ [0x8A53B014] = typeof(MessageMediaToDo),
[0xB6AEF7B0] = null,//MessageActionEmpty
[0xBD47CBAD] = typeof(MessageActionChatCreate),
[0xB5A1CE5A] = typeof(MessageActionChatEditTitle),
@@ -218,6 +220,12 @@ namespace TL
[0xAC1F1FCD] = typeof(MessageActionPaidMessagesRefunded),
[0x84B88578] = typeof(MessageActionPaidMessagesPrice),
[0x2FFE2F7A] = typeof(MessageActionConferenceCall),
+ [0xCC7C5C89] = typeof(MessageActionTodoCompletions),
+ [0xC7EDBC83] = typeof(MessageActionTodoAppendTasks),
+ [0xEE7A1596] = typeof(MessageActionSuggestedPostApproval),
+ [0x95DDCF69] = typeof(MessageActionSuggestedPostSuccess),
+ [0x69F916F8] = typeof(MessageActionSuggestedPostRefund),
+ [0xA8A3C699] = typeof(MessageActionGiftTon),
[0xD58A08C6] = typeof(Dialog),
[0x71BD134C] = typeof(DialogFolder),
[0x2331B22D] = typeof(PhotoEmpty),
@@ -418,7 +426,6 @@ namespace TL
[0x07DF587C] = typeof(UpdateBotEditBusinessMessage),
[0xA02A982E] = typeof(UpdateBotDeleteBusinessMessage),
[0x1824E40B] = typeof(UpdateNewStoryReaction),
- [0xDFD961F5] = typeof(UpdateBroadcastRevenueTransactions),
[0x4E80A379] = typeof(UpdateStarsBalance),
[0x1EA2FDA7] = typeof(UpdateBusinessBotCallbackQuery),
[0xA584B019] = typeof(UpdateStarsRevenueStatus),
@@ -428,6 +435,7 @@ namespace TL
[0xA477288F] = typeof(UpdateGroupCallChainBlocks),
[0x77B0E372] = typeof(UpdateReadMonoForumInbox),
[0xA4A79376] = typeof(UpdateReadMonoForumOutbox),
+ [0x9F812B08] = typeof(UpdateMonoForumNoPaidException),
[0xA56C2A3E] = typeof(Updates_State),
[0x5D75A138] = typeof(Updates_DifferenceEmpty),
[0x00F49CA0] = typeof(Updates_Difference),
@@ -565,6 +573,7 @@ namespace TL
[0x29D0F5EE] = typeof(InputStickerSetEmojiDefaultStatuses),
[0x44C1F8E9] = typeof(InputStickerSetEmojiDefaultTopicIcons),
[0x49748553] = typeof(InputStickerSetEmojiChannelDefaultStatuses),
+ [0x1CF671A0] = typeof(InputStickerSetTonGifts),
[0x2DD14EDC] = typeof(StickerSet),
[0x6E153F16] = typeof(Messages_StickerSet),
[0xD3F924EB] = null,//Messages_StickerSetNotModified
@@ -691,7 +700,7 @@ namespace TL
[0x70B772A8] = typeof(Contacts_TopPeers),
[0xB52C939D] = typeof(Contacts_TopPeersDisabled),
[0x1B0C841A] = typeof(DraftMessageEmpty),
- [0x2D65321F] = typeof(DraftMessage),
+ [0x96EAA5EB] = typeof(DraftMessage),
[0xC6DC0C66] = typeof(Messages_FeaturedStickersNotModified),
[0xBE382906] = typeof(Messages_FeaturedStickers),
[0x0B17F890] = null,//Messages_RecentStickersNotModified
@@ -1069,8 +1078,8 @@ namespace TL
[0xE3779861] = typeof(Account_ResetPasswordFailedWait),
[0xE9EFFC7D] = typeof(Account_ResetPasswordRequestedWait),
[0xE926D63E] = typeof(Account_ResetPasswordOk),
- [0x4D93A990] = typeof(SponsoredMessage),
- [0xC9EE1D87] = typeof(Messages_SponsoredMessages),
+ [0x7DBF8673] = typeof(SponsoredMessage),
+ [0xFFDA656D] = typeof(Messages_SponsoredMessages),
[0x1839490F] = null,//Messages_SponsoredMessagesEmpty
[0xC9B0539F] = typeof(SearchResultsCalendarPeriod),
[0x147EE23C] = typeof(Messages_SearchResultsCalendar),
@@ -1319,14 +1328,7 @@ namespace TL
[0x846F9E42] = typeof(Channels_SponsoredMessageReportResultChooseOption),
[0x3E3BCF2F] = typeof(Channels_SponsoredMessageReportResultAdsHidden),
[0xAD798849] = typeof(Channels_SponsoredMessageReportResultReported),
- [0x5407E297] = typeof(Stats_BroadcastRevenueStats),
- [0xEC659737] = typeof(Stats_BroadcastRevenueWithdrawalUrl),
- [0x557E2CC4] = typeof(BroadcastRevenueTransactionProceeds),
- [0x5A590978] = typeof(BroadcastRevenueTransactionWithdrawal),
- [0x42D30D2E] = typeof(BroadcastRevenueTransactionRefund),
- [0x87158466] = typeof(Stats_BroadcastRevenueTransactions),
[0x56E34970] = typeof(ReactionsNotifySettings),
- [0xC3FF71E7] = typeof(BroadcastRevenueBalances),
[0x93C3E27E] = typeof(AvailableEffect),
[0xD1ED9A5B] = null,//Messages_AvailableEffectsNotModified
[0xBDDB616E] = typeof(Messages_AvailableEffects),
@@ -1340,13 +1342,13 @@ namespace TL
[0x60682812] = typeof(StarsTransactionPeerAds),
[0xF9677AAD] = typeof(StarsTransactionPeerAPI),
[0x0BD915C0] = typeof(StarsTopupOption),
- [0xA39FD94A] = typeof(StarsTransaction),
+ [0x13659EB0] = typeof(StarsTransaction),
[0x6C9CE8ED] = typeof(Payments_StarsStatus),
[0xE87ACBC0] = typeof(FoundStory),
[0xE2DE7737] = typeof(Stories_FoundStories),
[0xDE4C5D93] = typeof(GeoPointAddress),
[0xFEBE5491] = typeof(StarsRevenueStatus),
- [0xC92BB73B] = typeof(Payments_StarsRevenueStats),
+ [0x6C207376] = typeof(Payments_StarsRevenueStats),
[0x1DAB80B7] = typeof(Payments_StarsRevenueWithdrawalUrl),
[0x394E7F21] = typeof(Payments_StarsRevenueAdsAccountUrl),
[0x206AE6D1] = typeof(InputStarsTransaction),
@@ -1375,6 +1377,7 @@ namespace TL
[0x98D5EA1D] = typeof(Payments_ConnectedStarRefBots),
[0xB4D5D859] = typeof(Payments_SuggestedStarRefBots),
[0xBBB6B4A3] = typeof(StarsAmount),
+ [0x74AEE3E0] = typeof(StarsTonAmount),
[0x6010C534] = typeof(Messages_FoundStickersNotModified),
[0x82C9E290] = typeof(Messages_FoundStickers),
[0xB0CD6617] = typeof(BotVerifierSettings),
@@ -1413,6 +1416,10 @@ namespace TL
[0x947A12DF] = typeof(Payments_ResaleStarGifts),
[0xC387C04E] = typeof(Stories_CanSendStoryCount),
[0xE7E82E12] = typeof(PendingSuggestion),
+ [0xCBA9A52F] = typeof(TodoItem),
+ [0x49B92A26] = typeof(TodoList),
+ [0x4CC120B7] = typeof(TodoCompletion),
+ [0x0E8E37E5] = typeof(SuggestedPost),
// from TL.Secret:
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
[0x020DF5D0] = typeof(Layer101.MessageEntityBlockquote),
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 1c5aa10..8024098 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -11,10 +11,10 @@
snupkg
true
WTelegramClient
- 0.0.0
- layer.204
Wizou
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 204
+ 0.0.0
+ layer.206
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 206
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From 52d948af2a01c28a68f6c52262be030bb2f0a1ec Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 10 Jul 2025 01:49:25 +0200
Subject: [PATCH 13/56] Fix DateTime type of *_at fields
---
.github/workflows/release.yml | 9 +++++++++
src/TL.Schema.cs | 14 +++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5d1519e..42fcb35 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -54,3 +54,12 @@ jobs:
run: |
git tag $VERSION
git push --tags
+ - name: Deployment Notification
+ env:
+ JSON: |
+ {
+ "status": "success", "complete": true, "commitMessage": ${{ toJSON(github.event.head_commit.message) }},
+ "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/TL.Schema.cs b/src/TL.Schema.cs
index 367010b..da22aff 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -2970,14 +2970,14 @@ namespace TL
{
public Flags flags;
public StarGiftBase gift;
- [IfFlag(3)] public int can_export_at;
+ [IfFlag(3)] public DateTime 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;
[IfFlag(8)] public long resale_stars;
- [IfFlag(9)] public int can_transfer_at;
- [IfFlag(10)] public int can_resell_at;
+ [IfFlag(9)] public DateTime can_transfer_at;
+ [IfFlag(10)] public DateTime can_resell_at;
[Flags] public enum Flags : uint
{
@@ -19791,7 +19791,7 @@ namespace TL
/// Total amount of earned Telegram Stars.
public StarsAmountBase overall_revenue;
/// Unixtime indicating when will withdrawal be available to the user. If not set, withdrawal can be started now.
- [IfFlag(1)] public int next_withdrawal_at;
+ [IfFlag(1)] public DateTime next_withdrawal_at;
[Flags] public enum Flags : uint
{
@@ -20518,10 +20518,10 @@ namespace TL
[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(7)] public DateTime can_export_at;
[IfFlag(8)] public long transfer_stars;
- [IfFlag(13)] public int can_transfer_at;
- [IfFlag(14)] public int can_resell_at;
+ [IfFlag(13)] public DateTime can_transfer_at;
+ [IfFlag(14)] public DateTime can_resell_at;
[Flags] public enum Flags : uint
{
From a3f41330b55c27b7c67de6e37d12d01674c7a88e Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Thu, 10 Jul 2025 01:50:09 +0200
Subject: [PATCH 14/56] API Layer 207: StarGift.ReleaseBy
(that might not be the most recent layer. check https://patreon.com/wizou for the latest layers)
---
README.md | 2 +-
src/TL.Schema.cs | 20 ++++++++++++++++----
src/TL.Table.cs | 8 ++++----
src/WTelegramClient.csproj | 4 ++--
4 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/README.md b/README.md
index 838b958..089b923 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 da22aff..d7f3678 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -20050,9 +20050,10 @@ namespace TL
/// 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;
+ public virtual Peer ReleasedBy => default;
}
/// Represents a star gift, see here » for more info. See
- [TLDef(0xC62ACA28)]
+ [TLDef(0x7F853C12)]
public sealed partial class StarGift : StarGiftBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -20077,6 +20078,7 @@ namespace TL
[IfFlag(3)] public long upgrade_stars;
[IfFlag(4)] public long resell_min_stars;
[IfFlag(5)] public string title;
+ [IfFlag(6)] public Peer released_by;
[Flags] public enum Flags : uint
{
@@ -20092,6 +20094,8 @@ namespace TL
has_availability_resale = 0x10,
/// Field has a value
has_title = 0x20,
+ /// Field has a value
+ has_released_by = 0x40,
}
/// Identifier of the gift
@@ -20099,9 +20103,10 @@ namespace TL
/// 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;
+ public override Peer ReleasedBy => released_by;
}
/// See
- [TLDef(0x6411DB89)]
+ [TLDef(0xF63778AE)]
public sealed partial class StarGiftUnique : StarGiftBase
{
public Flags flags;
@@ -20117,6 +20122,7 @@ namespace TL
public int availability_total;
[IfFlag(3)] public string gift_address;
[IfFlag(4)] public long resell_stars;
+ [IfFlag(5)] public Peer released_by;
[Flags] public enum Flags : uint
{
@@ -20125,22 +20131,28 @@ namespace TL
has_owner_address = 0x4,
has_gift_address = 0x8,
has_resell_stars = 0x10,
+ has_released_by = 0x20,
}
public override long ID => id;
public override int AvailabilityTotal => availability_total;
public override string Title => title;
+ public override Peer ReleasedBy => released_by;
}
/// Available gifts ». See
/// a value means payments.starGiftsNotModified
- [TLDef(0x901689EA)]
- public sealed partial class Payments_StarGifts : IObject
+ [TLDef(0x2ED82995)]
+ public sealed partial class Payments_StarGifts : IObject, IPeerResolver
{
/// Hash used for caching, for more info click here
public int hash;
/// List of available gifts.
public StarGiftBase[] gifts;
+ public Dictionary chats;
+ public Dictionary users;
+ /// returns a or for the given Peer
+ public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
}
/// Report menu option See
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index 11bbf49..bbb604f 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 = 206; // fetched 02/07/2025 12:40:29
+ public const int Version = 207; // fetched 08/07/2025 17:40:58
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -1361,10 +1361,10 @@ namespace TL
[0x4BA3A95A] = typeof(MessageReactor),
[0x94CE852A] = typeof(StarsGiveawayOption),
[0x54236209] = typeof(StarsGiveawayWinnersOption),
- [0xC62ACA28] = typeof(StarGift),
- [0x6411DB89] = typeof(StarGiftUnique),
+ [0x7F853C12] = typeof(StarGift),
+ [0xF63778AE] = typeof(StarGiftUnique),
[0xA388A368] = null,//Payments_StarGiftsNotModified
- [0x901689EA] = typeof(Payments_StarGifts),
+ [0x2ED82995] = typeof(Payments_StarGifts),
[0x7903E3D9] = typeof(MessageReportOption),
[0xF0E4E0B6] = typeof(ReportResultChooseOption),
[0x6F09AC31] = typeof(ReportResultAddComment),
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 8024098..3d55ae8 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,8 +13,8 @@
WTelegramClient
Wizou
0.0.0
- layer.206
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 206
+ layer.207
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 207
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From 56ba15bc13405500cd5f29999f6882dec095080f Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Mon, 14 Jul 2025 22:27:30 +0200
Subject: [PATCH 15/56] API Layer 209: Reply-to specific ToDo item
(that might not be the most recent layer. check https://patreon.com/wizou for the latest layers)
---
README.md | 2 +-
src/TL.Schema.cs | 136 +++++++++++++++++++++++++++++--------
src/TL.SchemaFuncs.cs | 73 ++++++++++----------
src/TL.Table.cs | 6 +-
src/WTelegramClient.csproj | 4 +-
5 files changed, 152 insertions(+), 69 deletions(-)
diff --git a/README.md b/README.md
index 089b923..4da3f32 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 d7f3678..281d067 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -163,7 +163,7 @@ namespace TL
public InputDocument id;
}
- /// Defines media content of a message. See Derived classes: , , , , , , , , , , , , , , , ,
+ /// Defines media content of a message. See Derived classes: , , , , , , , , , , , , , , , , ,
/// a value means inputMediaEmpty
public abstract partial class InputMedia : IObject { }
/// Photo See
@@ -257,7 +257,7 @@ namespace TL
has_ttl_seconds = 0x2,
/// Field has a value
has_thumb = 0x4,
- /// 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)
+ /// 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,
@@ -2012,7 +2012,7 @@ namespace TL
public override int TtlPeriod => ttl_period;
}
- /// Media See Derived classes: , , , , , , , , , , , , , , ,
+ /// Media See Derived classes: , , , , , , , , , , , , , , , ,
/// a value means messageMediaEmpty
public abstract partial class MessageMedia : IObject { }
/// Attached photo. See
@@ -2337,17 +2337,19 @@ namespace TL
[TLDef(0x8A53B014)]
public sealed partial class MessageMediaToDo : MessageMedia
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public TodoList todo;
[IfFlag(0)] public TodoCompletion[] completions;
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_completions = 0x1,
}
}
- /// Object describing actions connected to a service message. See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
+ /// Object describing actions connected to a service message. See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
/// a value means messageActionEmpty
public abstract partial class MessageAction : IObject { }
/// Group created See
@@ -2968,6 +2970,7 @@ namespace TL
[TLDef(0x2E3AE60E)]
public sealed partial class MessageActionStarGiftUnique : MessageAction
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public StarGiftBase gift;
[IfFlag(3)] public DateTime can_export_at;
@@ -2984,13 +2987,20 @@ namespace TL
upgrade = 0x1,
transferred = 0x2,
saved = 0x4,
+ /// Field has a value
has_can_export_at = 0x8,
+ /// Field has a value
has_transfer_stars = 0x10,
refunded = 0x20,
+ /// Field has a value
has_from_id = 0x40,
+ /// Fields and have a value
has_peer = 0x80,
+ /// Field has a value
has_resale_stars = 0x100,
+ /// Field has a value
has_can_transfer_at = 0x200,
+ /// Field has a value
has_can_resell_at = 0x400,
}
}
@@ -3005,6 +3015,7 @@ namespace TL
[TLDef(0x84B88578)]
public sealed partial class MessageActionPaidMessagesPrice : MessageAction
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long stars;
@@ -3017,6 +3028,7 @@ namespace TL
[TLDef(0x2FFE2F7A)]
public sealed partial class MessageActionConferenceCall : MessageAction
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long call_id;
[IfFlag(2)] public int duration;
@@ -3026,7 +3038,9 @@ namespace TL
{
missed = 0x1,
active = 0x2,
+ /// Field has a value
has_duration = 0x4,
+ /// Field has a value
has_other_participants = 0x8,
video = 0x10,
}
@@ -3048,6 +3062,7 @@ namespace TL
[TLDef(0xEE7A1596)]
public sealed partial class MessageActionSuggestedPostApproval : MessageAction
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[IfFlag(2)] public string reject_comment;
[IfFlag(3)] public DateTime schedule_date;
@@ -3057,8 +3072,11 @@ namespace TL
{
rejected = 0x1,
balance_too_low = 0x2,
+ /// Field has a value
has_reject_comment = 0x4,
+ /// Field has a value
has_schedule_date = 0x8,
+ /// Field has a value
has_price = 0x10,
}
}
@@ -3072,6 +3090,7 @@ namespace TL
[TLDef(0x69F916F8)]
public sealed partial class MessageActionSuggestedPostRefund : MessageAction
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[Flags] public enum Flags : uint
@@ -3083,6 +3102,7 @@ namespace TL
[TLDef(0xA8A3C699)]
public sealed partial class MessageActionGiftTon : MessageAction
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public string currency;
public long amount;
@@ -3092,6 +3112,7 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_transaction_id = 0x1,
}
}
@@ -3342,7 +3363,7 @@ namespace TL
}
}
- /// Contains info on a confirmation code message sent via SMS, phone call or Telegram. See Derived classes: ,
+ /// Contains info on a confirmation code message sent via SMS, phone call or Telegram. See Derived classes: , ,
public abstract partial class Auth_SentCodeBase : IObject { }
/// Contains info about a sent verification code. See
[TLDef(0x5E002502)]
@@ -4197,7 +4218,7 @@ namespace TL
[TLDef(0x1BB00451)]
public sealed partial class InputMessagesFilterPinned : MessagesFilter { }
- /// Object contains info on events occurred. See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
+ /// Object contains info on events occurred. See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
public abstract partial class Update : IObject
{
public virtual (long mbox_id, int pts, int pts_count) GetMBox() => default;
@@ -5279,6 +5300,7 @@ namespace TL
[TLDef(0x97D64341)]
public sealed partial class UpdateGroupCall : Update
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// The channel/supergroup where this group call or livestream takes place
[IfFlag(0)] public long chat_id;
@@ -5986,6 +6008,7 @@ namespace TL
[TLDef(0x9F812B08)]
public sealed partial class UpdateMonoForumNoPaidException : Update
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long channel_id;
public Peer saved_peer_id;
@@ -7355,7 +7378,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
@@ -7541,7 +7564,7 @@ namespace TL
public string display_url;
/// Hash used for caching, for more info click here
public int hash;
- /// Type of the web page. One of the following:
- video
- gif
- photo
- document
- profile
- telegram_background
- telegram_theme
- telegram_story
- telegram_channel
- telegram_channel_request
- telegram_megagroup
- telegram_chat
- telegram_megagroup_request
- telegram_chat_request
- telegram_album
- telegram_message
- telegram_bot
- telegram_voicechat
- telegram_livestream
- telegram_user
- telegram_botapp
- telegram_channel_boost
- telegram_group_boost
- telegram_giftcode
- telegram_stickerset
+ /// Type of the web page. One of the following:
- video
- gif
- photo
- document
- profile
- telegram_background
- telegram_theme
- telegram_story
- telegram_channel
- telegram_channel_request
- telegram_megagroup
- telegram_chat
- telegram_megagroup_request
- telegram_chat_request
- telegram_album
- telegram_message
- telegram_bot
- telegram_voicechat
- telegram_livestream
- telegram_call
- telegram_user
- telegram_botapp
- telegram_channel_boost
- telegram_group_boost
- telegram_giftcode
- telegram_stickerset
[IfFlag(0)] public string type;
/// Short name of the site (e.g., Google Docs, App Store)
[IfFlag(1)] public string site_name;
@@ -7928,7 +7951,7 @@ namespace TL
public DateTime expires;
}
- /// Represents a stickerset See Derived classes: , , , , , , , , ,
+ /// Represents a stickerset See Derived classes: , , , , , , , , , ,
/// a value means inputStickerSetEmpty
public abstract partial class InputStickerSet : IObject { }
/// Stickerset by ID See
@@ -10698,7 +10721,7 @@ namespace TL
public PageCaption caption;
}
- /// Why was the phone call discarded? See Derived classes: , , ,
+ /// Why was the phone call discarded? See Derived classes: , , , ,
public abstract partial class PhoneCallDiscardReason : IObject { }
/// The phone call was missed See
[TLDef(0x85E42301)]
@@ -11897,7 +11920,7 @@ namespace TL
}
}
- /// Channel admin log event See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
+ /// Channel admin log event See Derived classes: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
public abstract partial class ChannelAdminLogEventAction : IObject { }
/// Channel/supergroup title was changed See
[TLDef(0xE6DFB825)]
@@ -14166,7 +14189,7 @@ namespace TL
}
}
- /// Webpage attributes See Derived classes: , ,
+ /// Webpage attributes See Derived classes: , , ,
public abstract partial class WebPageAttribute : IObject { }
/// Page theme See
[TLDef(0x54B56617)]
@@ -14851,7 +14874,7 @@ namespace TL
/// Reply information See Derived classes: ,
public abstract partial class MessageReplyHeaderBase : IObject { }
/// Message replies and thread information See
- [TLDef(0xAFBC09DB)]
+ [TLDef(0x6917560B)]
public sealed partial class MessageReplyHeader : MessageReplyHeaderBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -14872,6 +14895,7 @@ namespace TL
[IfFlag(7)] public MessageEntity[] quote_entities;
/// Offset of the message quote_text within the original message (in UTF-16 code units).
[IfFlag(10)] public int quote_offset;
+ [IfFlag(11)] public int todo_item_id;
[Flags] public enum Flags : uint
{
@@ -14897,6 +14921,8 @@ namespace TL
quote = 0x200,
/// Field has a value
has_quote_offset = 0x400,
+ /// Field has a value
+ has_todo_item_id = 0x800,
}
}
/// Represents a reply to a story See
@@ -15053,7 +15079,7 @@ namespace TL
public override long AccessHash => access_hash;
}
- /// Indicates a group call See Derived classes:
+ /// Indicates a group call See Derived classes: , ,
public abstract partial class InputGroupCallBase : IObject { }
/// Points to a specific group call See
[TLDef(0xD8AA840F)]
@@ -16054,7 +16080,7 @@ namespace TL
Broadcast = 0x7BFBDEFC,
}
- /// An invoice See Derived classes: , , , , ,
+ /// An invoice See Derived classes: , , , , , , , , , ,
public abstract partial class InputInvoice : IObject { }
/// An invoice contained in a message or paid media ». See
[TLDef(0xC5B56859)]
@@ -16120,6 +16146,7 @@ namespace TL
[TLDef(0x4D818D5D)]
public sealed partial class InputInvoiceStarGiftUpgrade : InputInvoice
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public InputSavedStarGift stargift;
@@ -16139,6 +16166,7 @@ namespace TL
[TLDef(0xDABAB2EF)]
public sealed partial class InputInvoicePremiumGiftStars : InputInvoice
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public InputUserBase user_id;
public int months;
@@ -16146,6 +16174,7 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_message = 0x1,
}
}
@@ -16214,7 +16243,7 @@ namespace TL
public Dictionary users;
}
- /// Info about a Telegram Premium purchase See Derived classes: , , , , , ,
+ /// Info about a Telegram Premium purchase See Derived classes: , , , , , , ,
public abstract partial class InputStorePaymentPurpose : IObject { }
/// Info about a Telegram Premium purchase See
[TLDef(0xA6751E66)]
@@ -16373,6 +16402,7 @@ namespace TL
[TLDef(0x9BB2636D)]
public sealed partial class InputStorePaymentAuthCode : InputStorePaymentPurpose
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public string phone_number;
public string phone_code_hash;
@@ -16395,7 +16425,7 @@ namespace TL
public string title;
}
- /// Emoji status See Derived classes: ,
+ /// Emoji status See Derived classes: , ,
/// a value means emojiStatusEmpty
public abstract partial class EmojiStatusBase : IObject
{
@@ -16405,6 +16435,7 @@ namespace TL
[TLDef(0xE7FF068A)]
public sealed partial class EmojiStatus : EmojiStatusBase
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
/// Custom emoji document ID
public long document_id;
@@ -16422,6 +16453,7 @@ namespace TL
[TLDef(0x7184603B)]
public sealed partial class EmojiStatusCollectible : EmojiStatusBase
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long collectible_id;
public long document_id;
@@ -16436,6 +16468,7 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_until = 0x1,
}
@@ -16445,12 +16478,14 @@ namespace TL
[TLDef(0x07141DBF)]
public sealed partial class InputEmojiStatusCollectible : EmojiStatusBase
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long collectible_id;
[IfFlag(0)] public DateTime until;
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_until = 0x1,
}
@@ -17641,10 +17676,10 @@ namespace TL
public Dictionary users;
}
- /// Contains info about a message or story to reply to. See Derived classes: ,
+ /// 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(0xB07038B0)]
+ [TLDef(0x869FBE10)]
public sealed partial class InputReplyToMessage : InputReplyTo
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -17662,6 +17697,7 @@ namespace TL
/// 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;
+ [IfFlag(6)] public int todo_item_id;
[Flags] public enum Flags : uint
{
@@ -17677,6 +17713,8 @@ namespace TL
has_quote_offset = 0x10,
/// Field has a value
has_monoforum_peer_id = 0x20,
+ /// Field has a value
+ has_todo_item_id = 0x40,
}
}
/// Reply to a story. See
@@ -17749,7 +17787,7 @@ namespace TL
}
}
- /// Represents a story media area » See Derived classes: , , , , , , ,
+ /// Represents a story media area » See Derived classes: , , , , , , , ,
public abstract partial class MediaArea : IObject { }
/// Represents a location tag attached to a story, with additional venue information. See
[TLDef(0xBE82DB9C)]
@@ -18505,7 +18543,7 @@ namespace TL
public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
}
- /// Represents a saved message dialog ». See Derived classes:
+ /// Represents a saved message dialog ». See Derived classes: ,
public abstract partial class SavedDialogBase : IObject
{
/// The dialog
@@ -18539,6 +18577,7 @@ namespace TL
[TLDef(0x64407EA7)]
public sealed partial class MonoForumDialog : SavedDialogBase
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public Peer peer;
public int top_message;
@@ -18550,6 +18589,7 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_draft = 0x2,
unread_mark = 0x8,
nopaid_messages_exception = 0x10,
@@ -19806,6 +19846,7 @@ namespace TL
[TLDef(0x6C207376)]
public sealed partial class Payments_StarsRevenueStats : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[IfFlag(0)] public StatsGraphBase top_hours_graph;
/// Star revenue graph (number of earned stars)
@@ -20042,7 +20083,7 @@ namespace TL
}
}
- /// Represents a star gift, see here » for more info. See Derived classes:
+ /// Represents a star gift, see here » for more info. See Derived classes: ,
public abstract partial class StarGiftBase : IObject
{
/// Identifier of the gift
@@ -20109,6 +20150,7 @@ namespace TL
[TLDef(0xF63778AE)]
public sealed partial class StarGiftUnique : StarGiftBase
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long id;
public string title;
@@ -20126,11 +20168,17 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_owner_id = 0x1,
+ /// Field has a value
has_owner_name = 0x2,
+ /// Field has a value
has_owner_address = 0x4,
+ /// Field has a value
has_gift_address = 0x8,
+ /// Field has a value
has_resell_stars = 0x10,
+ /// Field has a value
has_released_by = 0x20,
}
@@ -20345,7 +20393,7 @@ namespace TL
}
}
- /// Describes a real (i.e. possibly decimal) amount of Telegram Stars. See Derived classes:
+ /// Describes a real (i.e. possibly decimal) amount of Telegram Stars. See Derived classes: ,
public abstract partial class StarsAmountBase : IObject
{
/// The integer amount of Telegram Stars.
@@ -20413,6 +20461,7 @@ namespace TL
[TLDef(0xB0CD6617)]
public sealed partial class BotVerifierSettings : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public long icon;
public string company;
@@ -20420,6 +20469,7 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_custom_description = 0x1,
can_modify_custom_description = 0x2,
}
@@ -20434,7 +20484,7 @@ namespace TL
public string description;
}
- /// See
+ /// See Derived classes: , , ,
public abstract partial class StarGiftAttribute : IObject { }
/// See
[TLDef(0x39D99013)]
@@ -20468,6 +20518,7 @@ namespace TL
[TLDef(0xE0BFF26C)]
public sealed partial class StarGiftAttributeOriginalDetails : StarGiftAttribute
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[IfFlag(0)] public Peer sender_id;
public Peer recipient_id;
@@ -20476,7 +20527,9 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_sender_id = 0x1,
+ /// Field has a value
has_message = 0x2,
}
}
@@ -20521,6 +20574,7 @@ namespace TL
[TLDef(0xDFDA0499)]
public sealed partial class SavedStarGift : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[IfFlag(1)] public Peer from_id;
public DateTime date;
@@ -20538,19 +20592,29 @@ namespace TL
[Flags] public enum Flags : uint
{
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,
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,
+ /// Field has a value
has_saved_id = 0x800,
pinned_to_top = 0x1000,
+ /// Field has a value
has_can_transfer_at = 0x2000,
+ /// Field has a value
has_can_resell_at = 0x4000,
}
}
@@ -20559,6 +20623,7 @@ namespace TL
[TLDef(0x95F389B1)]
public sealed partial class Payments_SavedStarGifts : IObject, IPeerResolver
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public int count;
[IfFlag(1)] public bool chat_notifications_enabled;
@@ -20569,14 +20634,16 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_next_offset = 0x1,
+ /// Field has a value
has_chat_notifications_enabled = 0x2,
}
/// returns a or for the given Peer
public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
}
- /// See
+ /// See Derived classes: , ,
public abstract partial class InputSavedStarGift : IObject { }
/// See
[TLDef(0x69279795)]
@@ -20605,7 +20672,7 @@ namespace TL
public string url;
}
- /// See
+ /// See Derived classes: ,
/// a value means paidReactionPrivacyDefault
public abstract partial class PaidReactionPrivacy : IObject { }
/// See
@@ -20625,7 +20692,7 @@ namespace TL
public long stars_amount;
}
- /// See
+ /// See Derived classes: ,
/// a value means requirementToContactEmpty
public abstract partial class RequirementToContact : IObject { }
/// See
@@ -20642,6 +20709,7 @@ namespace TL
[TLDef(0xA0624CF7)]
public sealed partial class BusinessBotRights : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[Flags] public enum Flags : uint
@@ -20667,6 +20735,7 @@ namespace TL
[TLDef(0x71F276C4)]
public sealed partial class DisallowedGiftsSettings : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[Flags] public enum Flags : uint
@@ -20682,6 +20751,7 @@ namespace TL
[TLDef(0xC69708D3)]
public sealed partial class SponsoredPeer : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public byte[] random_id;
public Peer peer;
@@ -20690,7 +20760,9 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_sponsor_info = 0x1,
+ /// Field has a value
has_additional_info = 0x2,
}
}
@@ -20707,7 +20779,7 @@ namespace TL
public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats);
}
- /// See
+ /// See Derived classes: , ,
public abstract partial class StarGiftAttributeId : IObject { }
/// See
[TLDef(0x48AAAE3C)]
@@ -20740,6 +20812,7 @@ namespace TL
[TLDef(0x947A12DF)]
public sealed partial class Payments_ResaleStarGifts : IObject, IPeerResolver
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public int count;
public StarGiftBase[] gifts;
@@ -20752,8 +20825,11 @@ namespace TL
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_next_offset = 0x1,
+ /// Fields and have a value
has_attributes = 0x2,
+ /// Field has a value
has_counters = 0x4,
}
/// returns a or for the given Peer
@@ -20789,6 +20865,7 @@ namespace TL
[TLDef(0x49B92A26)]
public sealed partial class TodoList : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
public TextWithEntities title;
public TodoItem[] list;
@@ -20813,15 +20890,18 @@ namespace TL
[TLDef(0x0E8E37E5)]
public sealed partial class SuggestedPost : IObject
{
+ /// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
[IfFlag(3)] public StarsAmountBase price;
[IfFlag(0)] public DateTime schedule_date;
[Flags] public enum Flags : uint
{
+ /// Field has a value
has_schedule_date = 0x1,
accepted = 0x2,
rejected = 0x4,
+ /// Field has a value
has_price = 0x8,
}
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 0845d54..6c1c3b5 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1425,7 +1425,7 @@ namespace TL
settings = settings,
});
- /// See
+ /// See [bots: ✓]
/// a null value means account.emojiStatusesNotModified
public static Task Account_GetCollectibleEmojiStatuses(this Client client, long hash = default)
=> client.Invoke(new Account_GetCollectibleEmojiStatuses
@@ -1433,7 +1433,7 @@ namespace TL
hash = hash,
});
- /// See
+ /// See [bots: ✓]
public static Task Account_GetPaidMessagesRevenue(this Client client, InputUserBase user_id, InputPeer parent_peer = null)
=> client.Invoke(new Account_GetPaidMessagesRevenue
{
@@ -1442,7 +1442,7 @@ namespace TL
user_id = user_id,
});
- /// See
+ /// See [bots: ✓]
public static Task Account_ToggleNoPaidMessagesException(this Client client, InputUserBase user_id, InputPeer parent_peer = null, bool refund_charged = false, bool require_payment = false)
=> client.Invoke(new Account_ToggleNoPaidMessagesException
{
@@ -1477,7 +1477,7 @@ namespace TL
errors = errors,
});
- /// See
+ /// See [bots: ✓]
public static Task Users_GetRequirementsToContact(this Client client, params InputUserBase[] id)
=> client.Invoke(new Users_GetRequirementsToContact
{
@@ -1733,7 +1733,7 @@ namespace TL
{
});
- /// See
+ /// See [bots: ✓]
/// a null value means contacts.sponsoredPeersEmpty
public static Task Contacts_GetSponsoredPeers(this Client client, string q)
=> client.Invoke(new Contacts_GetSponsoredPeers
@@ -4389,12 +4389,12 @@ 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) 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.
+ /// 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
{
@@ -4507,7 +4507,7 @@ namespace TL
hash = hash,
});
- /// See
+ /// See Possible codes: 400 (details)
public static Task Messages_ReportMessagesDelivery(this Client client, InputPeer peer, int[] id, bool push = false)
=> client.Invoke(new Messages_ReportMessagesDelivery
{
@@ -4516,7 +4516,7 @@ namespace TL
id = id,
});
- /// See
+ /// See [bots: ✓]
public static Task Messages_GetSavedDialogsByID(this Client client, InputPeer[] ids, InputPeer parent_peer = null)
=> client.Invoke(new Messages_GetSavedDialogsByID
{
@@ -4525,7 +4525,7 @@ namespace TL
ids = ids,
});
- /// See
+ /// See [bots: ✓]
public static Task Messages_ReadSavedHistory(this Client client, InputPeer parent_peer, InputPeer peer, int max_id = default)
=> client.Invoke(new Messages_ReadSavedHistory
{
@@ -4534,7 +4534,7 @@ namespace TL
max_id = max_id,
});
- /// See
+ /// See [bots: ✓]
public static Task Messages_ToggleTodoCompleted(this Client client, InputPeer peer, int msg_id, int[] completed, params int[] incompleted)
=> client.Invoke(new Messages_ToggleTodoCompleted
{
@@ -4544,7 +4544,7 @@ namespace TL
incompleted = incompleted,
});
- /// See
+ /// See [bots: ✓]
public static Task Messages_AppendTodoList(this Client client, InputPeer peer, int msg_id, params TodoItem[] list)
=> client.Invoke(new Messages_AppendTodoList
{
@@ -4553,7 +4553,7 @@ namespace TL
list = list,
});
- /// See
+ /// See [bots: ✓]
public static Task Messages_ToggleSuggestedPostApproval(this Client client, InputPeer peer, int msg_id, DateTime? schedule_date = null, string reject_comment = null, bool reject = false)
=> client.Invoke(new Messages_ToggleSuggestedPostApproval
{
@@ -5648,7 +5648,7 @@ namespace TL
limit = limit,
});
- /// See
+ /// See [bots: ✓]
public static Task Channels_UpdatePaidMessagesPrice(this Client client, InputChannelBase channel, long send_paid_messages_stars, bool broadcast_messages_allowed = false)
=> client.Invoke(new Channels_UpdatePaidMessagesPrice
{
@@ -5657,7 +5657,7 @@ namespace TL
send_paid_messages_stars = send_paid_messages_stars,
});
- /// See
+ /// See [bots: ✓]
public static Task Channels_ToggleAutotranslation(this Client client, InputChannelBase channel, bool enabled)
=> client.Invoke(new Channels_ToggleAutotranslation
{
@@ -5665,7 +5665,7 @@ namespace TL
enabled = enabled,
});
- /// See
+ /// See [bots: ✓]
public static Task Channels_GetMessageAuthor(this Client client, InputChannelBase channel, int id)
=> client.Invoke(new Channels_GetMessageAuthor
{
@@ -5967,7 +5967,7 @@ namespace TL
duration_months = duration_months ?? default,
});
- /// See
+ /// See [bots: ✓] Possible codes: 400 (details)
public static Task Bots_SetCustomVerification(this Client client, InputPeer peer, InputUserBase bot = null, string custom_description = null, bool enabled = false)
=> client.Invoke(new Bots_SetCustomVerification
{
@@ -5977,7 +5977,7 @@ namespace TL
custom_description = custom_description,
});
- /// See
+ /// See Possible codes: 400 (details)
public static Task Bots_GetBotRecommendations(this Client client, InputUserBase bot)
=> client.Invoke(new Bots_GetBotRecommendations
{
@@ -6384,7 +6384,7 @@ namespace TL
gift_id = gift_id,
});
- /// See
+ /// See Possible codes: 400 (details)
public static Task Payments_UpgradeStarGift(this Client client, InputSavedStarGift stargift, bool keep_original_details = false)
=> client.Invoke(new Payments_UpgradeStarGift
{
@@ -6392,7 +6392,7 @@ namespace TL
stargift = stargift,
});
- /// See
+ /// See Possible codes: 400 (details)
public static Task Payments_TransferStarGift(this Client client, InputSavedStarGift stargift, InputPeer to_id)
=> client.Invoke(new Payments_TransferStarGift
{
@@ -6400,14 +6400,15 @@ namespace TL
to_id = to_id,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_GetUniqueStarGift(this Client client, string slug)
=> client.Invoke(new Payments_GetUniqueStarGift
{
slug = slug,
});
- /// See
+ /// See [bots: ✓]
+ /// Maximum number of results to return, see pagination
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
{
@@ -6417,14 +6418,14 @@ namespace TL
limit = limit,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_GetSavedStarGift(this Client client, params InputSavedStarGift[] stargift)
=> client.Invoke(new Payments_GetSavedStarGift
{
stargift = stargift,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_GetStarGiftWithdrawalUrl(this Client client, InputSavedStarGift stargift, InputCheckPasswordSRP password)
=> client.Invoke(new Payments_GetStarGiftWithdrawalUrl
{
@@ -6432,7 +6433,7 @@ namespace TL
password = password,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_ToggleChatStarGiftNotifications(this Client client, InputPeer peer, bool enabled = false)
=> client.Invoke(new Payments_ToggleChatStarGiftNotifications
{
@@ -6440,7 +6441,7 @@ namespace TL
peer = peer,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_ToggleStarGiftsPinnedToTop(this Client client, InputPeer peer, params InputSavedStarGift[] stargift)
=> client.Invoke(new Payments_ToggleStarGiftsPinnedToTop
{
@@ -6448,14 +6449,15 @@ namespace TL
stargift = stargift,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_CanPurchaseStore(this Client client, InputStorePaymentPurpose purpose)
=> client.Invoke(new Payments_CanPurchaseStore
{
purpose = purpose,
});
- /// See
+ /// See [bots: ✓]
+ /// Maximum number of results to return, see pagination
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
{
@@ -6467,7 +6469,7 @@ namespace TL
limit = limit,
});
- /// See
+ /// See [bots: ✓]
public static Task Payments_UpdateStarGiftPrice(this Client client, InputSavedStarGift stargift, long resell_stars)
=> client.Invoke(new Payments_UpdateStarGiftPrice
{
@@ -6962,7 +6964,7 @@ namespace TL
file = file,
});
- /// See
+ /// See [bots: ✓]
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
{
@@ -6973,7 +6975,7 @@ namespace TL
params_ = params_,
});
- /// See
+ /// See [bots: ✓]
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
{
@@ -6983,7 +6985,7 @@ namespace TL
block = block,
});
- /// See
+ /// See [bots: ✓]
public static Task Phone_SendConferenceCallBroadcast(this Client client, InputGroupCallBase call, byte[] block)
=> client.Invoke(new Phone_SendConferenceCallBroadcast
{
@@ -6991,7 +6993,7 @@ namespace TL
block = block,
});
- /// See
+ /// See [bots: ✓]
public static Task Phone_InviteConferenceCallParticipant(this Client client, InputGroupCallBase call, InputUserBase user_id, bool video = false)
=> client.Invoke(new Phone_InviteConferenceCallParticipant
{
@@ -7000,14 +7002,15 @@ namespace TL
user_id = user_id,
});
- /// See
+ /// See [bots: ✓]
public static Task Phone_DeclineConferenceCallInvite(this Client client, int msg_id)
=> client.Invoke(new Phone_DeclineConferenceCallInvite
{
msg_id = msg_id,
});
- /// See
+ /// See [bots: ✓]
+ /// Maximum number of results to return, see pagination
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
{
diff --git a/src/TL.Table.cs b/src/TL.Table.cs
index bbb604f..cf405eb 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 = 207; // fetched 08/07/2025 17:40:58
+ public const int Version = 209; // fetched 14/07/2025 20:10:02
internal const int SecretChats = 144;
internal const int MTProto2 = 73;
internal const uint VectorCtor = 0x1CB5C415;
@@ -1039,7 +1039,7 @@ namespace TL
[0x455B853D] = typeof(MessageViews),
[0xB6C4F543] = typeof(Messages_MessageViews),
[0xA6341782] = typeof(Messages_DiscussionMessage),
- [0xAFBC09DB] = typeof(MessageReplyHeader),
+ [0x6917560B] = typeof(MessageReplyHeader),
[0x0E5AF939] = typeof(MessageReplyStoryHeader),
[0x83D60FC2] = typeof(MessageReplies),
[0xE8FD8014] = typeof(PeerBlocked),
@@ -1222,7 +1222,7 @@ namespace TL
[0xBD74CF49] = typeof(StoryViewPublicRepost),
[0x59D78FC5] = typeof(Stories_StoryViewsList),
[0xDE9EED1D] = typeof(Stories_StoryViews),
- [0xB07038B0] = typeof(InputReplyToMessage),
+ [0x869FBE10] = typeof(InputReplyToMessage),
[0x5881323A] = typeof(InputReplyToStory),
[0x69D66C45] = typeof(InputReplyToMonoForum),
[0x3FC9053B] = typeof(ExportedStoryLink),
diff --git a/src/WTelegramClient.csproj b/src/WTelegramClient.csproj
index 3d55ae8..8ab7179 100644
--- a/src/WTelegramClient.csproj
+++ b/src/WTelegramClient.csproj
@@ -13,8 +13,8 @@
WTelegramClient
Wizou
0.0.0
- layer.207
- Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 207
+ layer.209
+ Telegram Client API (MTProto) library written 100% in C# and .NET Standard | Latest API layer: 209
Release Notes:
$(ReleaseNotes.Replace("|", "%0D%0A").Replace(" - ","%0D%0A- ").Replace(" ", "%0D%0A%0D%0A"))
From a8fa32dfd5bc558dffcb5728f77022a33f7c8998 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Fri, 18 Jul 2025 02:28:43 +0200
Subject: [PATCH 16/56] Support single-quote arguments in HTML
---
src/Services.cs | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/Services.cs b/src/Services.cs
index d62b877..bb536d2 100644
--- a/src/Services.cs
+++ b/src/Services.cs
@@ -401,6 +401,7 @@ namespace TL
case "u": case "ins": ProcessEntity(); break;
case "s": case "strike": case "del": ProcessEntity(); break;
case "span class=\"tg-spoiler\"":
+ case "span class='tg-spoiler'":
case "span" when closing:
case "tg-spoiler": ProcessEntity(); break;
case "code": ProcessEntity(); break;
@@ -420,7 +421,8 @@ namespace TL
prevEntity.length = offset - prevEntity.offset;
}
}
- else if (tag.StartsWith("a href=\"") && tag[^1] == '"')
+ else if ((tag[^1] == '"' && tag.StartsWith("a href=\""))
+ || (tag[^1] == '\'' && tag.StartsWith("a href='")))
{
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)
@@ -428,12 +430,13 @@ namespace TL
else
entities.Add(new MessageEntityTextUrl { offset = offset, length = -1, url = tag });
}
- else if (tag.StartsWith("code class=\"language-") && tag[^1] == '"')
+ else if ((tag[^1] == '"' && tag.StartsWith("code class=\"language-"))
+ || (tag[^1] == '\'' && tag.StartsWith("code class='language-")))
{
if (entities.LastOrDefault(e => e.length == -1) is MessageEntityPre prevEntity)
prevEntity.language = tag[21..^1];
}
- else if (premium && (tag.StartsWith("tg-emoji emoji-id=\"") || tag.StartsWith("tg-emoji id=\"")))
+ else if (premium && (tag.StartsWith("tg-emoji emoji-id=\"") || tag.StartsWith("tg-emoji emoji-id='")))
entities.Add(new MessageEntityCustomEmoji { offset = offset, length = -1, document_id = long.Parse(tag[(tag.IndexOf('=') + 2)..^1]) });
break;
}
From e9543a690b1a332727d8ac1d054b59c48a3efe07 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Fri, 25 Jul 2025 01:03:30 +0200
Subject: [PATCH 17/56] Examples for download abort, and uploading streamable
video (fix #325, thx @patelriki13)
---
.github/workflows/telegram-api.yml | 3 ++-
EXAMPLES.md | 37 +++++++++++++++++++++++++++++-
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/telegram-api.yml b/.github/workflows/telegram-api.yml
index 9a69fd9..efd921a 100644
--- a/.github/workflows/telegram-api.yml
+++ b/.github/workflows/telegram-api.yml
@@ -12,7 +12,7 @@ jobs:
if: contains(github.event.issue.labels.*.name, 'telegram api')
runs-on: ubuntu-latest
steps:
- - uses: dessant/support-requests@v3.0.0
+ - uses: dessant/support-requests@v4
with:
support-label: 'telegram api'
issue-comment: >
@@ -26,3 +26,4 @@ jobs:
If the above links didn't answer your problem, [click here to ask your question on **StackOverflow**](https://stackoverflow.com/questions/ask?tags=c%23+wtelegramclient+telegram-api) so the whole community can help and benefit.
close-issue: true
+ issue-close-reason: 'not planned'
diff --git a/EXAMPLES.md b/EXAMPLES.md
index e32e10d..ac2daf1 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -210,7 +210,7 @@ that simplifies the download of a photo/document/file once you get a reference t
See [Examples/Program_DownloadSavedMedia.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_DownloadSavedMedia.cs?ts=4#L28) that download all media files you forward to yourself (Saved Messages)
-_Note: To abort an ongoing download, you can throw an exception via the `progress` callback argument._
+_Note: To abort an ongoing download, you can throw an exception via the `progress` callback argument. Example: `(t,s) => ct.ThrowIfCancellationRequested()`_
## Upload a media file and post it with caption to a chat
@@ -224,6 +224,41 @@ var inputFile = await client.UploadFileAsync(Filepath);
await client.SendMediaAsync(peer, "Here is the photo", inputFile);
```
+
+## Upload a streamable video with optional custom thumbnail
+```csharp
+var chats = await client.Messages_GetAllChats();
+InputPeer peer = chats.chats[1234567890]; // the chat we want
+const string videoPath = @"C:\...\video.mp4";
+const string thumbnailPath = @"C:\...\thumbnail.jpg";
+
+// Extract video information using FFMpegCore or similar library
+var mediaInfo = await FFmpeg.GetMediaInfo(videoPath);
+var videoStream = mediaInfo.VideoStreams.FirstOrDefault();
+int width = videoStream?.Width ?? 0;
+int height = videoStream?.Height ?? 0;
+int duration = (int)mediaInfo.Duration.TotalSeconds;
+
+// Upload video file
+var inputFile = await Client.UploadFileAsync(videoPath);
+
+// Prepare InputMedia structure with video attributes
+var media = new InputMediaUploadedDocument(inputFile, "video/mp4",
+ new DocumentAttributeVideo { w = width, h = height, duration = duration,
+ flags = DocumentAttributeVideo.Flags.supports_streaming });
+if (thumbnailPath != null)
+{
+ // upload custom thumbnail and complete InputMedia structure
+ var inputThumb = await client.UploadFileAsync(thumbnailPath);
+ media.thumb = inputThumb;
+ media.flags |= InputMediaUploadedDocument.Flags.has_thumb;
+}
+
+// Send the media message
+await client.SendMessageAsync(peer, "caption", media);
+```
+*Note: This example requires FFMpegCore NuGet package for video metadata extraction. You can also manually set width, height, and duration if you know the video properties.*
+
## Send a grouped media album using photos from various sources
```csharp
From 30a982b0ac16d1f1f637d0675b46eef6e4421412 Mon Sep 17 00:00:00 2001
From: Wizou <11647984+wiz0u@users.noreply.github.com>
Date: Fri, 25 Jul 2025 17:01:58 +0200
Subject: [PATCH 18/56] API Layer 210: user's Stars Rating, StarGift
collections management & more characteristics...
(that might not be the most recent layer. check https://patreon.com/wizou for the latest layers)
---
README.md | 2 +-
src/TL.Schema.cs | 63 +++++++++++++++++--
src/TL.SchemaFuncs.cs | 122 ++++++++++++++++++++++++++++++++++---
src/TL.Table.cs | 13 ++--
src/WTelegramClient.csproj | 4 +-
5 files changed, 185 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
index 4da3f32..a89d3b9 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 281d067..c887407 100644
--- a/src/TL.Schema.cs
+++ b/src/TL.Schema.cs
@@ -898,7 +898,7 @@ namespace TL
has_color = 0x100,
/// Field has a value
has_profile_color = 0x200,
- /// If set, we can only write to this user if they have already sent some messages to us, if we are subscribed to Telegram Premium, or if they're a mutual contact (.mutual_contact).
All the secondary conditions listed above must be checked separately to verify whether we can still write to the user, even if this flag is set (i.e. a mutual contact will have this flag set even if we can still write to them, and so on...); to avoid doing these extra checks if we haven't yet cached all the required information (for example while displaying the chat list in the sharing UI) the Users_GetIsPremiumRequiredToContact method may be invoked instead, 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; alternatively, the .contact_require_premium flag contains the same (fully checked, i.e. it's not just a copy of this flag) info returned by Users_GetIsPremiumRequiredToContact.
To set this flag for ourselves invoke Account_SetGlobalPrivacySettings, setting the settings.new_noncontact_peers_require_premium flag.
+ /// See here for more info on this flag ».
contact_require_premium = 0x400,
/// Whether this bot can be connected to a user as specified here ».
bot_business = 0x800,
@@ -3742,7 +3742,7 @@ namespace TL
}
/// Extended user info See
- [TLDef(0x99E78045)]
+ [TLDef(0x29DE80BE)]
public sealed partial class UserFull : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -3808,6 +3808,7 @@ namespace TL
[IfFlag(44)] public BotVerification bot_verification;
[IfFlag(46)] public long send_paid_messages_stars;
[IfFlag(47)] public DisallowedGiftsSettings disallowed_gifts;
+ [IfFlag(49)] public StarsRating stars_rating;
[Flags] public enum Flags : uint
{
@@ -3900,6 +3901,8 @@ namespace TL
/// Field has a value
has_disallowed_gifts = 0x8000,
display_gifts_button = 0x10000,
+ /// Field has a value
+ has_stars_rating = 0x20000,
}
}
@@ -14719,6 +14722,7 @@ namespace TL
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
public Flags flags;
+ /// If configured, specifies the number of stars users must pay us to send us a message, see here » for more info on paid messages.
[IfFlag(5)] public long noncontact_peers_paid_stars;
[IfFlag(6)] public DisallowedGiftsSettings disallowed_gifts;
@@ -14732,7 +14736,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.
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.
+ /// See here for more info on this flag ».
new_noncontact_peers_require_premium = 0x10,
/// Field has a value
has_noncontact_peers_paid_stars = 0x20,
@@ -20094,7 +20098,7 @@ namespace TL
public virtual Peer ReleasedBy => default;
}
/// Represents a star gift, see here » for more info. See
- [TLDef(0x7F853C12)]
+ [TLDef(0x00BCFF5B)]
public sealed partial class StarGift : StarGiftBase
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -20120,6 +20124,8 @@ namespace TL
[IfFlag(4)] public long resell_min_stars;
[IfFlag(5)] public string title;
[IfFlag(6)] public Peer released_by;
+ [IfFlag(8)] public int per_user_total;
+ [IfFlag(8)] public int per_user_remains;
[Flags] public enum Flags : uint
{
@@ -20137,6 +20143,8 @@ namespace TL
has_title = 0x20,
/// Field has a value
has_released_by = 0x40,
+ require_premium = 0x80,
+ limited_per_user = 0x100,
}
/// Identifier of the gift
@@ -20180,6 +20188,7 @@ namespace TL
has_resell_stars = 0x10,
/// Field has a value
has_released_by = 0x20,
+ require_premium = 0x40,
}
public override long ID => id;
@@ -20571,7 +20580,7 @@ namespace TL
}
/// See
- [TLDef(0xDFDA0499)]
+ [TLDef(0x1EA646DF)]
public sealed partial class SavedStarGift : IObject
{
/// Extra bits of information, use flags.HasFlag(...) to test for those
@@ -20588,6 +20597,7 @@ namespace TL
[IfFlag(8)] public long transfer_stars;
[IfFlag(13)] public DateTime can_transfer_at;
[IfFlag(14)] public DateTime can_resell_at;
+ [IfFlag(15)] public int[] collection_id;
[Flags] public enum Flags : uint
{
@@ -20616,6 +20626,8 @@ namespace TL
has_can_transfer_at = 0x2000,
/// Field has a value
has_can_resell_at = 0x4000,
+ /// Field has a value
+ has_collection_id = 0x8000,
}
}
@@ -20905,4 +20917,45 @@ namespace TL
has_price = 0x8,
}
}
+
+ /// See
+ [TLDef(0x1B0E4F07)]
+ public sealed partial class StarsRating : IObject
+ {
+ public Flags flags;
+ public int level;
+ public long current_level_stars;
+ public long stars;
+ [IfFlag(0)] public long next_level_stars;
+
+ [Flags] public enum Flags : uint
+ {
+ has_next_level_stars = 0x1,
+ }
+ }
+
+ /// See
+ [TLDef(0x9D6B13B0)]
+ public sealed partial class StarGiftCollection : IObject
+ {
+ public Flags flags;
+ public int collection_id;
+ public string title;
+ [IfFlag(0)] public DocumentBase icon;
+ public int gifts_count;
+ public long hash;
+
+ [Flags] public enum Flags : uint
+ {
+ has_icon = 0x1,
+ }
+ }
+
+ /// See
+ /// a value means payments.starGiftCollectionsNotModified
+ [TLDef(0x8A2932F3)]
+ public sealed partial class Payments_StarGiftCollections : IObject
+ {
+ public StarGiftCollection[] collections;
+ }
}
diff --git a/src/TL.SchemaFuncs.cs b/src/TL.SchemaFuncs.cs
index 6c1c3b5..a066365 100644
--- a/src/TL.SchemaFuncs.cs
+++ b/src/TL.SchemaFuncs.cs
@@ -1433,7 +1433,9 @@ namespace TL
hash = hash,
});
- /// See [bots: ✓]
+ /// Get the number of stars we have received from the specified user thanks to paid messages »; the received amount will be equal to the sent amount multiplied by stars_paid_message_commission_permille divided by 1000. See [bots: ✓]
+ /// If set, can contain the ID of a monoforum (channel direct messages) to obtain the number of stars the user has spent to send us direct messages via the channel.
+ /// The user that paid to send us messages.
public static Task Account_GetPaidMessagesRevenue(this Client client, InputUserBase user_id, InputPeer parent_peer = null)
=> client.Invoke(new Account_GetPaidMessagesRevenue
{
@@ -1442,7 +1444,11 @@ namespace TL
user_id = user_id,
});
- /// See [bots: ✓]
+ /// Allow a user to send us messages without paying if paid messages » are enabled. See [bots: ✓]
+ /// If set and require_payment is not set, refunds the amounts the user has already paid us to send us messages (directly or via a monoforum).
+ /// Allow or disallow a user to send us messages without paying.
+ /// If set, applies the setting within the monoforum aka direct messages » (pass the ID of the monoforum, not the ID of the associated channel).
+ /// The user to exempt or unexempt.
public static Task Account_ToggleNoPaidMessagesException(this Client client, InputUserBase user_id, InputPeer parent_peer = null, bool refund_charged = false, bool require_payment = false)
=> client.Invoke(new Account_ToggleNoPaidMessagesException
{
@@ -4659,7 +4665,7 @@ namespace TL
/// Upload a custom profile picture for a contact, or suggest a new profile picture to a contact. See Possible codes: 400 (details)
/// If set, will send a service message to user_id, suggesting them to use the specified profile picture; otherwise, will set a personal profile picture for the user (only visible to the current user).
- /// If set, removes a previously set personal profile picture (does not affect suggested profile pictures, to remove them simply deleted the service message with Messages_DeleteMessages).
+ /// If set, removes a previously set personal profile picture (does not affect suggested profile pictures, to remove them simply delete the service message with Messages_DeleteMessages).
/// The contact
/// Profile photo
/// Animated profile picture video
@@ -5648,7 +5654,10 @@ namespace TL
limit = limit,
});
- /// See [bots: ✓]
+ /// Enable or disable paid messages » in this supergroup or monoforum. See [bots: ✓]
+ /// Only usable for channels, enables or disables the associated monoforum aka direct messages.
+ /// Pass the supergroup ID for supergroups and the ID of the channel to modify the setting in the associated monoforum.
+ /// Specifies the required amount of Telegram Stars users must pay to send messages to the supergroup or monoforum.
public static Task Channels_UpdatePaidMessagesPrice(this Client client, InputChannelBase channel, long send_paid_messages_stars, bool broadcast_messages_allowed = false)
=> client.Invoke(new Channels_UpdatePaidMessagesPrice
{
@@ -6409,11 +6418,12 @@ namespace TL
/// See