mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Improved Secret Chats:
Support layer 144 : big documents, silent (layer not yet supported by other clients) List of ISecretChat with detailed properties Fix PFS issue losing a message...
This commit is contained in:
parent
8fa00a8cc6
commit
a038be87af
2
.github/dev.yml
vendored
2
.github/dev.yml
vendored
|
|
@ -2,7 +2,7 @@ pr: none
|
||||||
trigger:
|
trigger:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
name: 3.0.4-dev.$(Rev:r)
|
name: 3.1.1-dev.$(Rev:r)
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: ubuntu-latest
|
vmImage: ubuntu-latest
|
||||||
|
|
|
||||||
2
.github/release.yml
vendored
2
.github/release.yml
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
pr: none
|
pr: none
|
||||||
trigger: none
|
trigger: none
|
||||||
|
|
||||||
name: 3.0.$(Rev:r)
|
name: 3.1.$(Rev:r)
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: ubuntu-latest
|
vmImage: ubuntu-latest
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,24 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TL;
|
using TL;
|
||||||
|
using WTelegram;
|
||||||
|
|
||||||
namespace WTelegramClientTest
|
namespace WTelegramClientTest
|
||||||
{
|
{
|
||||||
static class Program_SecretChats
|
static class Program_SecretChats
|
||||||
{
|
{
|
||||||
static WTelegram.Client Client;
|
static Client Client;
|
||||||
static WTelegram.SecretChats Secrets;
|
static SecretChats Secrets;
|
||||||
static InputEncryptedChat ActiveChat; // the secret chat currently selected
|
static ISecretChat ActiveChat; // the secret chat currently selected
|
||||||
static readonly Dictionary<long, User> Users = new();
|
static readonly Dictionary<long, User> Users = new();
|
||||||
static readonly Dictionary<long, ChatBase> Chats = new();
|
static readonly Dictionary<long, ChatBase> Chats = new();
|
||||||
|
|
||||||
// go to Project Properties > Debug > Environment variables and add at least these: api_id, api_hash, phone_number
|
// go to Project Properties > Debug > Environment variables and add at least these: api_id, api_hash, phone_number
|
||||||
static async Task Main()
|
static async Task Main()
|
||||||
{
|
{
|
||||||
WTelegram.Helpers.Log = (l, s) => System.Diagnostics.Debug.WriteLine(s);
|
Helpers.Log = (l, s) => System.Diagnostics.Debug.WriteLine(s);
|
||||||
Client = new WTelegram.Client(Environment.GetEnvironmentVariable);
|
Client = new Client(Environment.GetEnvironmentVariable);
|
||||||
Secrets = new WTelegram.SecretChats(Client, "Secrets.bin");
|
Secrets = new SecretChats(Client, "Secrets.bin");
|
||||||
AppDomain.CurrentDomain.ProcessExit += (s, e) => { Secrets.Dispose(); Client.Dispose(); };
|
AppDomain.CurrentDomain.ProcessExit += (s, e) => { Secrets.Dispose(); Client.Dispose(); };
|
||||||
SelectActiveChat();
|
SelectActiveChat();
|
||||||
|
|
||||||
|
|
@ -46,9 +47,9 @@ Type a command, or a message to send to the active secret chat:");
|
||||||
var line = Console.ReadLine();
|
var line = Console.ReadLine();
|
||||||
if (line.StartsWith('/'))
|
if (line.StartsWith('/'))
|
||||||
{
|
{
|
||||||
if (line == "/discard delete") { await Secrets.Discard(ActiveChat, true); SelectActiveChat(); }
|
if (line == "/discard delete") { await Secrets.Discard(ActiveChat.ChatId, true); SelectActiveChat(); }
|
||||||
else if (line == "/discard") { await Secrets.Discard(ActiveChat, false); SelectActiveChat(); }
|
else if (line == "/discard") { await Secrets.Discard(ActiveChat.ChatId, false); SelectActiveChat(); }
|
||||||
else if (line == "/read") await Client.Messages_ReadEncryptedHistory(ActiveChat, DateTime.UtcNow);
|
else if (line == "/read") await Client.Messages_ReadEncryptedHistory(ActiveChat.Peer, DateTime.UtcNow);
|
||||||
else if (line == "/users") foreach (var user in Users.Values) Console.WriteLine($"{user.id,-10} {user}");
|
else if (line == "/users") foreach (var user in Users.Values) Console.WriteLine($"{user.id,-10} {user}");
|
||||||
else if (line.StartsWith("/select ")) SelectActiveChat(int.Parse(line[8..]));
|
else if (line.StartsWith("/select ")) SelectActiveChat(int.Parse(line[8..]));
|
||||||
else if (line.StartsWith("/request "))
|
else if (line.StartsWith("/request "))
|
||||||
|
|
@ -58,15 +59,15 @@ Type a command, or a message to send to the active secret chat:");
|
||||||
Console.WriteLine("User not found");
|
Console.WriteLine("User not found");
|
||||||
else if (line.StartsWith("/photo "))
|
else if (line.StartsWith("/photo "))
|
||||||
{
|
{
|
||||||
var media = new TL.Layer45.DecryptedMessageMediaPhoto { caption = line[7..] };
|
var media = new TL.Layer46.DecryptedMessageMediaPhoto { caption = line[7..] };
|
||||||
var file = await Secrets.UploadFile(File.OpenRead(line[7..]), media);
|
var file = await Secrets.UploadFile(File.OpenRead(line[7..]), media);
|
||||||
var sent = await Secrets.SendMessage(ActiveChat, new TL.Layer73.DecryptedMessage { random_id = WTelegram.Helpers.RandomLong(),
|
var sent = await Secrets.SendMessage(ActiveChat.ChatId, new TL.Layer73.DecryptedMessage { random_id = Helpers.RandomLong(),
|
||||||
media = media, flags = TL.Layer73.DecryptedMessage.Flags.has_media }, file: file);
|
media = media, flags = TL.Layer73.DecryptedMessage.Flags.has_media }, file: file);
|
||||||
}
|
}
|
||||||
else Console.WriteLine("Unrecognized command");
|
else Console.WriteLine("Unrecognized command");
|
||||||
}
|
}
|
||||||
else if (ActiveChat == null) Console.WriteLine("No active secret chat");
|
else if (ActiveChat == null) Console.WriteLine("No active secret chat");
|
||||||
else await Secrets.SendMessage(ActiveChat, new TL.Layer73.DecryptedMessage { message = line, random_id = WTelegram.Helpers.RandomLong() });
|
else await Secrets.SendMessage(ActiveChat.ChatId, new TL.Layer73.DecryptedMessage { message = line, random_id = Helpers.RandomLong() });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -86,7 +87,7 @@ Type a command, or a message to send to the active secret chat:");
|
||||||
await Secrets.HandleUpdate(ue);
|
await Secrets.HandleUpdate(ue);
|
||||||
break;
|
break;
|
||||||
case UpdateNewEncryptedMessage unem: // Encrypted message or service message:
|
case UpdateNewEncryptedMessage unem: // Encrypted message or service message:
|
||||||
if (unem.message.ChatId != ActiveChat?.chat_id) SelectActiveChat(unem.message.ChatId);
|
if (unem.message.ChatId != ActiveChat?.ChatId) SelectActiveChat(unem.message.ChatId);
|
||||||
foreach (var msg in Secrets.DecryptMessage(unem.message))
|
foreach (var msg in Secrets.DecryptMessage(unem.message))
|
||||||
{
|
{
|
||||||
if (msg.Media != null && unem.message is EncryptedMessage { file: EncryptedFile ef })
|
if (msg.Media != null && unem.message is EncryptedMessage { file: EncryptedFile ef })
|
||||||
|
|
@ -110,8 +111,8 @@ Type a command, or a message to send to the active secret chat:");
|
||||||
|
|
||||||
private static void SelectActiveChat(int newActiveChat = 0)
|
private static void SelectActiveChat(int newActiveChat = 0)
|
||||||
{
|
{
|
||||||
ActiveChat = Secrets.Peers.FirstOrDefault(sc => newActiveChat == 0 || sc.chat_id == newActiveChat);
|
ActiveChat = Secrets.Chats.FirstOrDefault(sc => newActiveChat == 0 || sc.ChatId == newActiveChat);
|
||||||
Console.WriteLine("Active secret chat ID: " + ActiveChat?.chat_id);
|
Console.WriteLine("Active secret chat ID: " + ActiveChat?.ChatId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
FAQ.md
2
FAQ.md
|
|
@ -140,7 +140,7 @@ Some additional advices from me:
|
||||||
|
|
||||||
5. Avoid repetitive polling or repetitive sequence of actions/requests: Save the initial results of your queries, and update those results when you're informed of a change through `OnUpdate` events.
|
5. Avoid repetitive polling or repetitive sequence of actions/requests: Save the initial results of your queries, and update those results when you're informed of a change through `OnUpdate` events.
|
||||||
6. Don't buy fake user accounts/sessions and don't extract api_id/hash/authkey/sessions from official clients, this is [specifically forbidden by API TOS](https://core.telegram.org/api/terms#2-transparency). You must use your own api_id and create your own sessions associated with it.
|
6. Don't buy fake user accounts/sessions and don't extract api_id/hash/authkey/sessions from official clients, this is [specifically forbidden by API TOS](https://core.telegram.org/api/terms#2-transparency). You must use your own api_id and create your own sessions associated with it.
|
||||||
7. If a phone number is brand new, it will be closely monitored by Telegram for abuse, and it can even already be considered a bad user due to bad behavior from the previous owner of that phone number (which may happens often with VoIP or other easy-to-buy-online numbers, so expect fast ban)
|
7. If a phone number is brand new, it will be closely monitored by Telegram for abuse, and it can even already be considered a bad user due to bad behavior from the previous owner of that phone number (which may happen often with VoIP or other easy-to-buy-online numbers, so expect fast ban)
|
||||||
8. You may want to use your new phone number account with an official Telegram client and act like a normal user for some time (some weeks/months), before using it for automation with WTelegramClient.
|
8. You may want to use your new phone number account with an official Telegram client and act like a normal user for some time (some weeks/months), before using it for automation with WTelegramClient.
|
||||||
9. When creating a new API ID/Hash, I recommend you use your own phone number with long history of normal Telegram usage, rather than a brand new phone number with short history.
|
9. When creating a new API ID/Hash, I recommend you use your own phone number with long history of normal Telegram usage, rather than a brand new phone number with short history.
|
||||||
In particular, DON'T create an API ID/Hash for every phone numbers you will control. One API ID/Hash represents your application, which can be used to control several user accounts.
|
In particular, DON'T create an API ID/Hash for every phone numbers you will control. One API ID/Hash represents your application, which can be used to control several user accounts.
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
||||||
private readonly ICryptoTransform aesCrypto;
|
private readonly ICryptoTransform aesCrypto;
|
||||||
private readonly byte[] prevBytes;
|
private readonly byte[] prevBytes;
|
||||||
|
|
||||||
public AES_IGE_Stream(Stream stream, int size, byte[] key, byte[] iv) : this(stream, key, iv, false) { ContentLength = size; }
|
public AES_IGE_Stream(Stream stream, long size, byte[] key, byte[] iv) : this(stream, key, iv, false) { ContentLength = size; }
|
||||||
public AES_IGE_Stream(Stream stream, byte[] key, byte[] iv, bool encrypt) : base(stream)
|
public AES_IGE_Stream(Stream stream, byte[] key, byte[] iv, bool encrypt) : base(stream)
|
||||||
{
|
{
|
||||||
aesCrypto = encrypt ? Encryption.AesECB.CreateEncryptor(key, null) : Encryption.AesECB.CreateDecryptor(key, null);
|
aesCrypto = encrypt ? Encryption.AesECB.CreateEncryptor(key, null) : Encryption.AesECB.CreateDecryptor(key, null);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@ using static WTelegram.Encryption;
|
||||||
|
|
||||||
namespace WTelegram
|
namespace WTelegram
|
||||||
{
|
{
|
||||||
|
public interface ISecretChat
|
||||||
|
{
|
||||||
|
int ChatId { get; }
|
||||||
|
long RemoteUserId { get; }
|
||||||
|
InputEncryptedChat Peer { get; }
|
||||||
|
int RemoteLayer { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class SecretChats : IDisposable
|
public sealed class SecretChats : IDisposable
|
||||||
{
|
{
|
||||||
public event Action OnChanged;
|
public event Action OnChanged;
|
||||||
|
|
@ -28,7 +36,7 @@ namespace WTelegram
|
||||||
private const int ThresholdPFS = 100;
|
private const int ThresholdPFS = 100;
|
||||||
|
|
||||||
[TLDef(0xFEFEFEFE)]
|
[TLDef(0xFEFEFEFE)]
|
||||||
internal class SecretChat : IObject
|
internal class SecretChat : IObject, ISecretChat
|
||||||
{
|
{
|
||||||
[Flags] public enum Flags : uint { requestChat = 1, renewKey = 2, acceptKey = 4, originator = 8, commitKey = 16 }
|
[Flags] public enum Flags : uint { requestChat = 1, renewKey = 2, acceptKey = 4, originator = 8, commitKey = 16 }
|
||||||
public Flags flags;
|
public Flags flags;
|
||||||
|
|
@ -43,8 +51,12 @@ namespace WTelegram
|
||||||
public long exchange_id;
|
public long exchange_id;
|
||||||
|
|
||||||
public int ChatId => peer.chat_id;
|
public int ChatId => peer.chat_id;
|
||||||
|
public long RemoteUserId => participant_id;
|
||||||
|
public InputEncryptedChat Peer => peer;
|
||||||
|
public int RemoteLayer => remoteLayer;
|
||||||
|
|
||||||
internal long key_fingerprint;
|
internal long key_fingerprint;
|
||||||
internal SortedList<int, TL.Layer17.DecryptedMessageLayer> pendingMsgs = new();
|
internal SortedList<int, TL.Layer23.DecryptedMessageLayer> pendingMsgs = new();
|
||||||
internal void Discarded() // clear out fields for more security
|
internal void Discarded() // clear out fields for more security
|
||||||
{
|
{
|
||||||
Array.Clear(authKey, 0, authKey.Length);
|
Array.Clear(authKey, 0, authKey.Length);
|
||||||
|
|
@ -67,13 +79,7 @@ namespace WTelegram
|
||||||
}
|
}
|
||||||
public void Dispose() { OnChanged?.Invoke(); storage?.Dispose(); sha256.Dispose(); sha1.Dispose(); }
|
public void Dispose() { OnChanged?.Invoke(); storage?.Dispose(); sha256.Dispose(); sha1.Dispose(); }
|
||||||
|
|
||||||
public List<InputEncryptedChat> Peers => chats.Values.Select(sc => sc.peer).ToList();
|
public List<ISecretChat> Chats => chats.Values.ToList<ISecretChat>();
|
||||||
|
|
||||||
/// <summary>Return secret chats with the given remote user ID</summary>
|
|
||||||
/// <param name="participant_id">remote user ID</param>
|
|
||||||
/// <returns>List of matching secret chat ids/access_hash</returns>
|
|
||||||
public List<InputEncryptedChat> FindChatsByParticipant(long participant_id)
|
|
||||||
=> chats.Where(kvp => kvp.Value.participant_id == participant_id).Select(kvp => kvp.Value.peer).ToList();
|
|
||||||
|
|
||||||
public bool IsChatActive(int chat_id) => !(chats.GetValueOrDefault(chat_id)?.flags.HasFlag(SecretChat.Flags.requestChat) ?? true);
|
public bool IsChatActive(int chat_id) => !(chats.GetValueOrDefault(chat_id)?.flags.HasFlag(SecretChat.Flags.requestChat) ?? true);
|
||||||
|
|
||||||
|
|
@ -253,16 +259,16 @@ namespace WTelegram
|
||||||
|
|
||||||
private async Task SendNotifyLayer(SecretChat chat)
|
private async Task SendNotifyLayer(SecretChat chat)
|
||||||
{
|
{
|
||||||
await SendMessage(chat.ChatId, new TL.Layer17.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
await SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||||
action = new TL.Layer17.DecryptedMessageActionNotifyLayer { layer = Layer.SecretChats } });
|
action = new TL.Layer23.DecryptedMessageActionNotifyLayer { layer = Layer.SecretChats } });
|
||||||
if (chat.remoteLayer < Layer.MTProto2) chat.remoteLayer = Layer.MTProto2;
|
if (chat.remoteLayer < Layer.MTProto2) chat.remoteLayer = Layer.MTProto2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Encrypt and send a message on a secret chat</summary>
|
/// <summary>Encrypt and send a message on a secret chat</summary>
|
||||||
/// <remarks>You would typically pass an instance of <see cref="TL.Layer73.DecryptedMessage"/> or <see cref="TL.Layer17.DecryptedMessageService"/> that you created and filled
|
/// <remarks>You would typically pass an instance of <see cref="TL.Layer73.DecryptedMessage"/> or <see cref="TL.Layer23.DecryptedMessageService"/> that you created and filled
|
||||||
/// <br/>Remember to fill <c>random_id</c> with <see cref="WTelegram.Helpers.RandomLong"/>, and the <c>flags</c> field if necessary</remarks>
|
/// <br/>Remember to fill <c>random_id</c> with <see cref="WTelegram.Helpers.RandomLong"/>, and the <c>flags</c> field if necessary</remarks>
|
||||||
/// <param name="chatId">Secret Chat ID</param>
|
/// <param name="chatId">Secret Chat ID</param>
|
||||||
/// <param name="msg">The pre-filled <see cref="TL.Layer73.DecryptedMessage">DecryptedMessage</see> or <see cref="TL.Layer17.DecryptedMessageService">DecryptedMessageService </see> to send</param>
|
/// <param name="msg">The pre-filled <see cref="TL.Layer73.DecryptedMessage">DecryptedMessage</see> or <see cref="TL.Layer23.DecryptedMessageService">DecryptedMessageService </see> to send</param>
|
||||||
/// <param name="silent">Send encrypted message without a notification</param>
|
/// <param name="silent">Send encrypted message without a notification</param>
|
||||||
/// <param name="file">Optional file attachment. See method <see cref="UploadFile">UploadFile</see></param>
|
/// <param name="file">Optional file attachment. See method <see cref="UploadFile">UploadFile</see></param>
|
||||||
/// <returns>Confirmation of sent message</returns>
|
/// <returns>Confirmation of sent message</returns>
|
||||||
|
|
@ -271,7 +277,7 @@ namespace WTelegram
|
||||||
if (!chats.TryGetValue(chatId, out var chat)) throw new ApplicationException("Secret chat not found");
|
if (!chats.TryGetValue(chatId, out var chat)) throw new ApplicationException("Secret chat not found");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dml = new TL.Layer17.DecryptedMessageLayer
|
var dml = new TL.Layer23.DecryptedMessageLayer
|
||||||
{
|
{
|
||||||
layer = Math.Min(chat.remoteLayer, Layer.SecretChats),
|
layer = Math.Min(chat.remoteLayer, Layer.SecretChats),
|
||||||
random_bytes = new byte[15],
|
random_bytes = new byte[15],
|
||||||
|
|
@ -290,7 +296,7 @@ namespace WTelegram
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Messages_SentEncryptedMessage> SendMessage(SecretChat chat, TL.Layer17.DecryptedMessageLayer dml, bool silent = false, InputEncryptedFileBase file = null)
|
private async Task<Messages_SentEncryptedMessage> SendMessage(SecretChat chat, TL.Layer23.DecryptedMessageLayer dml, bool silent = false, InputEncryptedFileBase file = null)
|
||||||
{
|
{
|
||||||
RNG.GetBytes(dml.random_bytes);
|
RNG.GetBytes(dml.random_bytes);
|
||||||
int x = 8 - (int)(chat.flags & SecretChat.Flags.originator);
|
int x = 8 - (int)(chat.flags & SecretChat.Flags.originator);
|
||||||
|
|
@ -321,7 +327,7 @@ namespace WTelegram
|
||||||
CheckPFS(chat);
|
CheckPFS(chat);
|
||||||
if (file != null)
|
if (file != null)
|
||||||
return await client.Messages_SendEncryptedFile(chat.peer, dml.message.RandomId, data, file, silent);
|
return await client.Messages_SendEncryptedFile(chat.peer, dml.message.RandomId, data, file, silent);
|
||||||
else if (dml.message is TL.Layer17.DecryptedMessageService or TL.Layer8.DecryptedMessageService)
|
else if (dml.message is TL.Layer23.DecryptedMessageService or TL.Layer8.DecryptedMessageService)
|
||||||
return await client.Messages_SendEncryptedService(chat.peer, dml.message.RandomId, data);
|
return await client.Messages_SendEncryptedService(chat.peer, dml.message.RandomId, data);
|
||||||
else
|
else
|
||||||
return await client.Messages_SendEncrypted(chat.peer, dml.message.RandomId, data, silent);
|
return await client.Messages_SendEncrypted(chat.peer, dml.message.RandomId, data, silent);
|
||||||
|
|
@ -360,7 +366,7 @@ namespace WTelegram
|
||||||
/// <summary>Decrypt an encrypted message obtained in <see cref="UpdateNewEncryptedMessage"/></summary>
|
/// <summary>Decrypt an encrypted message obtained in <see cref="UpdateNewEncryptedMessage"/></summary>
|
||||||
/// <param name="msg">Encrypted <see cref="UpdateNewEncryptedMessage.message"/></param>
|
/// <param name="msg">Encrypted <see cref="UpdateNewEncryptedMessage.message"/></param>
|
||||||
/// <param name="fillGaps">If messages are missing or received in wrong order, automatically request to resend missing messages</param>
|
/// <param name="fillGaps">If messages are missing or received in wrong order, automatically request to resend missing messages</param>
|
||||||
/// <returns>An array of <see cref="TL.Layer73.DecryptedMessage">DecryptedMessage</see> or <see cref="TL.Layer17.DecryptedMessageService">DecryptedMessageService </see> from various TL.LayerXX namespaces.<br/>
|
/// <returns>An array of <see cref="TL.Layer73.DecryptedMessage">DecryptedMessage</see> or <see cref="TL.Layer23.DecryptedMessageService">DecryptedMessageService </see> from various TL.LayerXX namespaces.<br/>
|
||||||
/// You can use the generic properties to access their fields
|
/// You can use the generic properties to access their fields
|
||||||
/// <para>May return an empty array if msg was already previously received or is not the next message in sequence.
|
/// <para>May return an empty array if msg was already previously received or is not the next message in sequence.
|
||||||
/// <br/>May return multiple messages if missing messages are finally received (using <paramref name="fillGaps"/> = true)</para></returns>
|
/// <br/>May return multiple messages if missing messages are finally received (using <paramref name="fillGaps"/> = true)</para></returns>
|
||||||
|
|
@ -371,7 +377,7 @@ namespace WTelegram
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var obj = Decrypt(chat, msg.Bytes, msg.Bytes.Length);
|
var obj = Decrypt(chat, msg.Bytes, msg.Bytes.Length);
|
||||||
if (obj is not TL.Layer17.DecryptedMessageLayer dml) throw new ApplicationException("Decrypted object is not DecryptedMessageLayer");
|
if (obj is not TL.Layer23.DecryptedMessageLayer dml) throw new ApplicationException("Decrypted object is not DecryptedMessageLayer");
|
||||||
if (dml.random_bytes.Length < 15) throw new ApplicationException("Not enough random_bytes");
|
if (dml.random_bytes.Length < 15) throw new ApplicationException("Not enough random_bytes");
|
||||||
if (((dml.out_seq_no ^ dml.in_seq_no) & 1) != 1 || ((dml.out_seq_no ^ chat.in_seq_no) & 1) != 0) throw new ApplicationException("Invalid seq_no parities");
|
if (((dml.out_seq_no ^ dml.in_seq_no) & 1) != 1 || ((dml.out_seq_no ^ chat.in_seq_no) & 1) != 0) throw new ApplicationException("Invalid seq_no parities");
|
||||||
if (dml.layer > chat.remoteLayer) chat.remoteLayer = dml.layer;
|
if (dml.layer > chat.remoteLayer) chat.remoteLayer = dml.layer;
|
||||||
|
|
@ -384,8 +390,8 @@ namespace WTelegram
|
||||||
if (lastPending == 0) lastPending = chat.in_seq_no;
|
if (lastPending == 0) lastPending = chat.in_seq_no;
|
||||||
chat.pendingMsgs[dml.out_seq_no] = dml;
|
chat.pendingMsgs[dml.out_seq_no] = dml;
|
||||||
if (dml.out_seq_no > lastPending + 2) // send request to resend missing gap asynchronously
|
if (dml.out_seq_no > lastPending + 2) // send request to resend missing gap asynchronously
|
||||||
_ = SendMessage(chat.ChatId, new TL.Layer17.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
_ = SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||||
action = new TL.Layer17.DecryptedMessageActionResend { start_seq_no = lastPending + 2, end_seq_no = dml.out_seq_no - 2 } });
|
action = new TL.Layer23.DecryptedMessageActionResend { start_seq_no = lastPending + 2, end_seq_no = dml.out_seq_no - 2 } });
|
||||||
return Array.Empty<DecryptedMessageBase>();
|
return Array.Empty<DecryptedMessageBase>();
|
||||||
}
|
}
|
||||||
chat.in_seq_no = dml.out_seq_no;
|
chat.in_seq_no = dml.out_seq_no;
|
||||||
|
|
@ -423,13 +429,13 @@ namespace WTelegram
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case TL.Layer17.DecryptedMessageActionNotifyLayer dmanl:
|
case TL.Layer23.DecryptedMessageActionNotifyLayer dmanl:
|
||||||
chat.remoteLayer = dmanl.layer;
|
chat.remoteLayer = dmanl.layer;
|
||||||
return true;
|
return true;
|
||||||
case TL.Layer17.DecryptedMessageActionResend resend:
|
case TL.Layer23.DecryptedMessageActionResend resend:
|
||||||
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> Resend {resend.start_seq_no}-{resend.end_seq_no}");
|
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> Resend {resend.start_seq_no}-{resend.end_seq_no}");
|
||||||
var msgSvc = new TL.Layer17.DecryptedMessageService { action = new TL.Layer20.DecryptedMessageActionNoop() };
|
var msgSvc = new TL.Layer23.DecryptedMessageService { action = new TL.Layer23.DecryptedMessageActionNoop() };
|
||||||
var dml = new TL.Layer17.DecryptedMessageLayer
|
var dml = new TL.Layer23.DecryptedMessageLayer
|
||||||
{
|
{
|
||||||
layer = Math.Min(chat.remoteLayer, Layer.SecretChats),
|
layer = Math.Min(chat.remoteLayer, Layer.SecretChats),
|
||||||
random_bytes = new byte[15],
|
random_bytes = new byte[15],
|
||||||
|
|
@ -442,13 +448,13 @@ namespace WTelegram
|
||||||
_ = SendMessage(chat, dml);
|
_ = SendMessage(chat, dml);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case TL.Layer20.DecryptedMessageActionNoop:
|
case TL.Layer23.DecryptedMessageActionNoop:
|
||||||
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> Noop");
|
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> Noop");
|
||||||
return true;
|
return true;
|
||||||
case TL.Layer20.DecryptedMessageActionRequestKey:
|
case TL.Layer23.DecryptedMessageActionRequestKey:
|
||||||
case TL.Layer20.DecryptedMessageActionAcceptKey:
|
case TL.Layer23.DecryptedMessageActionAcceptKey:
|
||||||
case TL.Layer20.DecryptedMessageActionCommitKey:
|
case TL.Layer23.DecryptedMessageActionCommitKey:
|
||||||
case TL.Layer20.DecryptedMessageActionAbortKey:
|
case TL.Layer23.DecryptedMessageActionAbortKey:
|
||||||
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> PFS {action.GetType().Name[22..]}");
|
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> PFS {action.GetType().Name[22..]}");
|
||||||
HandlePFS(chat, action);
|
HandlePFS(chat, action);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -465,16 +471,17 @@ namespace WTelegram
|
||||||
else { Helpers.Log(4, "SC{(short)chat.ChatId:X4}> PFS Failure"); _ = Discard(chat.ChatId); return; }
|
else { Helpers.Log(4, "SC{(short)chat.ChatId:X4}> PFS Failure"); _ = Discard(chat.ChatId); return; }
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
chat.flags |= SecretChat.Flags.renewKey;
|
||||||
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> PFS RenewKey");
|
Helpers.Log(1, $"SC{(short)chat.ChatId:X4}> PFS RenewKey");
|
||||||
|
await Task.Delay(100);
|
||||||
chat.salt = new byte[256];
|
chat.salt = new byte[256];
|
||||||
RNG.GetBytes(chat.salt);
|
RNG.GetBytes(chat.salt);
|
||||||
var a = BigEndianInteger(chat.salt);
|
var a = BigEndianInteger(chat.salt);
|
||||||
var g_a = BigInteger.ModPow(dh.g, a, dh_prime);
|
var g_a = BigInteger.ModPow(dh.g, a, dh_prime);
|
||||||
CheckGoodGaAndGb(g_a, dh_prime);
|
CheckGoodGaAndGb(g_a, dh_prime);
|
||||||
chat.flags |= SecretChat.Flags.renewKey;
|
|
||||||
chat.exchange_id = Helpers.RandomLong();
|
chat.exchange_id = Helpers.RandomLong();
|
||||||
await SendMessage(chat.ChatId, new TL.Layer17.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
await SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||||
action = new TL.Layer20.DecryptedMessageActionRequestKey { exchange_id = chat.exchange_id, g_a = g_a.To256Bytes() } });
|
action = new TL.Layer23.DecryptedMessageActionRequestKey { exchange_id = chat.exchange_id, g_a = g_a.To256Bytes() } });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -489,7 +496,7 @@ namespace WTelegram
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case TL.Layer20.DecryptedMessageActionRequestKey request:
|
case TL.Layer23.DecryptedMessageActionRequestKey request:
|
||||||
switch (chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey))
|
switch (chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey))
|
||||||
{
|
{
|
||||||
case SecretChat.Flags.renewKey: // Concurrent Re-Keying
|
case SecretChat.Flags.renewKey: // Concurrent Re-Keying
|
||||||
|
|
@ -517,10 +524,10 @@ namespace WTelegram
|
||||||
chat.salt = gab.To256Bytes();
|
chat.salt = gab.To256Bytes();
|
||||||
chat.exchange_id = request.exchange_id;
|
chat.exchange_id = request.exchange_id;
|
||||||
var key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(chat.salt).AsSpan(12));
|
var key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(chat.salt).AsSpan(12));
|
||||||
await SendMessage(chat.ChatId, new TL.Layer17.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
await SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||||
action = new TL.Layer20.DecryptedMessageActionAcceptKey { exchange_id = request.exchange_id, g_b = g_b.To256Bytes(), key_fingerprint = key_fingerprint } });
|
action = new TL.Layer23.DecryptedMessageActionAcceptKey { exchange_id = request.exchange_id, g_b = g_b.To256Bytes(), key_fingerprint = key_fingerprint } });
|
||||||
break;
|
break;
|
||||||
case TL.Layer20.DecryptedMessageActionAcceptKey accept:
|
case TL.Layer23.DecryptedMessageActionAcceptKey accept:
|
||||||
if ((chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) != SecretChat.Flags.renewKey)
|
if ((chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) != SecretChat.Flags.renewKey)
|
||||||
throw new ApplicationException("Invalid AcceptKey");
|
throw new ApplicationException("Invalid AcceptKey");
|
||||||
if (accept.exchange_id != chat.exchange_id)
|
if (accept.exchange_id != chat.exchange_id)
|
||||||
|
|
@ -533,13 +540,13 @@ namespace WTelegram
|
||||||
key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(authKey).AsSpan(12));
|
key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(authKey).AsSpan(12));
|
||||||
if (accept.key_fingerprint != key_fingerprint)
|
if (accept.key_fingerprint != key_fingerprint)
|
||||||
throw new ApplicationException("AcceptKey: key_fingerprint mismatch");
|
throw new ApplicationException("AcceptKey: key_fingerprint mismatch");
|
||||||
_ = SendMessage(chat.ChatId, new TL.Layer17.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
_ = SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||||
action = new TL.Layer20.DecryptedMessageActionCommitKey { exchange_id = accept.exchange_id, key_fingerprint = accept.key_fingerprint } });
|
action = new TL.Layer23.DecryptedMessageActionCommitKey { exchange_id = accept.exchange_id, key_fingerprint = accept.key_fingerprint } });
|
||||||
chat.salt = chat.authKey; // A may only discard the previous key after a message encrypted with the new key has been received.
|
chat.salt = chat.authKey; // A may only discard the previous key after a message encrypted with the new key has been received.
|
||||||
SetAuthKey(chat, authKey);
|
SetAuthKey(chat, authKey);
|
||||||
chat.flags = chat.flags & ~SecretChat.Flags.renewKey | SecretChat.Flags.commitKey;
|
chat.flags = chat.flags & ~SecretChat.Flags.renewKey | SecretChat.Flags.commitKey;
|
||||||
break;
|
break;
|
||||||
case TL.Layer20.DecryptedMessageActionCommitKey commit:
|
case TL.Layer23.DecryptedMessageActionCommitKey commit:
|
||||||
if ((chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) != SecretChat.Flags.acceptKey)
|
if ((chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) != SecretChat.Flags.acceptKey)
|
||||||
throw new ApplicationException("Invalid RequestKey");
|
throw new ApplicationException("Invalid RequestKey");
|
||||||
key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(chat.salt).AsSpan(12));
|
key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(chat.salt).AsSpan(12));
|
||||||
|
|
@ -549,10 +556,10 @@ namespace WTelegram
|
||||||
authKey = chat.authKey;
|
authKey = chat.authKey;
|
||||||
SetAuthKey(chat, chat.salt);
|
SetAuthKey(chat, chat.salt);
|
||||||
Array.Clear(authKey, 0, authKey.Length); // the old key must be securely discarded
|
Array.Clear(authKey, 0, authKey.Length); // the old key must be securely discarded
|
||||||
await SendMessage(chat.ChatId, new TL.Layer17.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
await SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||||
action = new TL.Layer20.DecryptedMessageActionNoop() });
|
action = new TL.Layer23.DecryptedMessageActionNoop() });
|
||||||
break;
|
break;
|
||||||
case TL.Layer20.DecryptedMessageActionAbortKey abort:
|
case TL.Layer23.DecryptedMessageActionAbortKey abort:
|
||||||
if ((chat.flags & (SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) == 0 ||
|
if ((chat.flags & (SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) == 0 ||
|
||||||
chat.flags.HasFlag(SecretChat.Flags.commitKey) || abort.exchange_id != chat.exchange_id)
|
chat.flags.HasFlag(SecretChat.Flags.commitKey) || abort.exchange_id != chat.exchange_id)
|
||||||
return;
|
return;
|
||||||
|
|
@ -579,7 +586,7 @@ namespace WTelegram
|
||||||
byte[] aes_key = new byte[32], aes_iv = new byte[32];
|
byte[] aes_key = new byte[32], aes_iv = new byte[32];
|
||||||
RNG.GetBytes(aes_key);
|
RNG.GetBytes(aes_key);
|
||||||
RNG.GetBytes(aes_iv);
|
RNG.GetBytes(aes_iv);
|
||||||
media.SizeKeyIV = (checked((int)stream.Length), aes_key, aes_iv);
|
media.SizeKeyIV = (stream.Length, aes_key, aes_iv);
|
||||||
|
|
||||||
using var md5 = MD5.Create();
|
using var md5 = MD5.Create();
|
||||||
md5.TransformBlock(aes_key, 0, 32, null, 0);
|
md5.TransformBlock(aes_key, 0, 32, null, 0);
|
||||||
|
|
|
||||||
|
|
@ -13179,7 +13179,7 @@ namespace TL
|
||||||
public DocumentBase static_icon;
|
public DocumentBase static_icon;
|
||||||
/// <summary>The animated sticker to show when the user opens the reaction dropdown</summary>
|
/// <summary>The animated sticker to show when the user opens the reaction dropdown</summary>
|
||||||
public DocumentBase appear_animation;
|
public DocumentBase appear_animation;
|
||||||
/// <summary>The animated sticker to show when the user selects this reaction</summary>
|
/// <summary>The animated sticker to show when the user hovers over the reaction</summary>
|
||||||
public DocumentBase select_animation;
|
public DocumentBase select_animation;
|
||||||
/// <summary>The animated sticker to show when the reaction is chosen and activated</summary>
|
/// <summary>The animated sticker to show when the reaction is chosen and activated</summary>
|
||||||
public DocumentBase activate_animation;
|
public DocumentBase activate_animation;
|
||||||
|
|
|
||||||
411
src/TL.Secret.cs
411
src/TL.Secret.cs
|
|
@ -32,7 +32,7 @@ namespace TL
|
||||||
public abstract class DecryptedMessageMedia : IObject
|
public abstract class DecryptedMessageMedia : IObject
|
||||||
{
|
{
|
||||||
public virtual string MimeType { get; }
|
public virtual string MimeType { get; }
|
||||||
internal virtual (int size, byte[] key, byte[] iv) SizeKeyIV { get => default; set => throw new ApplicationException("Incompatible DecryptedMessageMedia"); }
|
internal virtual (long size, byte[] key, byte[] iv) SizeKeyIV { get => default; set => throw new ApplicationException("Incompatible DecryptedMessageMedia"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Object describes the action to which a service message is linked. <para>See <a href="https://corefork.telegram.org/type/DecryptedMessageAction"/></para></summary>
|
/// <summary>Object describes the action to which a service message is linked. <para>See <a href="https://corefork.telegram.org/type/DecryptedMessageAction"/></para></summary>
|
||||||
|
|
@ -110,7 +110,7 @@ namespace TL
|
||||||
public byte[] iv;
|
public byte[] iv;
|
||||||
|
|
||||||
public override string MimeType => "image/jpeg";
|
public override string MimeType => "image/jpeg";
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>Video attached to an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaVideo"/></para></summary>
|
/// <summary>Video attached to an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaVideo"/></para></summary>
|
||||||
[TLDef(0x4CEE6EF3)]
|
[TLDef(0x4CEE6EF3)]
|
||||||
|
|
@ -135,7 +135,7 @@ namespace TL
|
||||||
/// <summary>Initialization vector</summary>
|
/// <summary>Initialization vector</summary>
|
||||||
public byte[] iv;
|
public byte[] iv;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>GeoPoint attached to an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaGeoPoint"/></para></summary>
|
/// <summary>GeoPoint attached to an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaGeoPoint"/></para></summary>
|
||||||
[TLDef(0x35480A59)]
|
[TLDef(0x35480A59)]
|
||||||
|
|
@ -182,7 +182,7 @@ namespace TL
|
||||||
/// <summary>File MIME-type</summary>
|
/// <summary>File MIME-type</summary>
|
||||||
public override string MimeType => mime_type;
|
public override string MimeType => mime_type;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>Audio file attached to a secret chat message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaAudio"/></para></summary>
|
/// <summary>Audio file attached to a secret chat message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaAudio"/></para></summary>
|
||||||
[TLDef(0x6080758F)]
|
[TLDef(0x6080758F)]
|
||||||
|
|
@ -197,7 +197,7 @@ namespace TL
|
||||||
/// <summary>Initialization vector</summary>
|
/// <summary>Initialization vector</summary>
|
||||||
public byte[] iv;
|
public byte[] iv;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Setting of a message lifetime after reading. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionSetMessageTTL"/></para></summary>
|
/// <summary>Setting of a message lifetime after reading. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionSetMessageTTL"/></para></summary>
|
||||||
|
|
@ -233,8 +233,43 @@ namespace TL
|
||||||
public class DecryptedMessageActionFlushHistory : DecryptedMessageAction { }
|
public class DecryptedMessageActionFlushHistory : DecryptedMessageAction { }
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Layer17
|
namespace Layer23
|
||||||
{
|
{
|
||||||
|
/// <summary>Image description. <para>See <a href="https://corefork.telegram.org/constructor/photoSize"/></para></summary>
|
||||||
|
[TLDef(0x77BFB61B)]
|
||||||
|
public partial class PhotoSize : PhotoSizeBase
|
||||||
|
{
|
||||||
|
/// <summary><a href="https://corefork.telegram.org/api/files#image-thumbnail-types">Thumbnail type »</a></summary>
|
||||||
|
public string type;
|
||||||
|
public FileLocationBase location;
|
||||||
|
/// <summary>Image width</summary>
|
||||||
|
public int w;
|
||||||
|
/// <summary>Image height</summary>
|
||||||
|
public int h;
|
||||||
|
/// <summary>File size</summary>
|
||||||
|
public int size;
|
||||||
|
|
||||||
|
/// <summary><a href="https://corefork.telegram.org/api/files#image-thumbnail-types">Thumbnail type »</a></summary>
|
||||||
|
public override string Type => type;
|
||||||
|
}
|
||||||
|
/// <summary>Description of an image and its content. <para>See <a href="https://corefork.telegram.org/constructor/photoCachedSize"/></para></summary>
|
||||||
|
[TLDef(0xE9A734FA)]
|
||||||
|
public partial class PhotoCachedSize : PhotoSizeBase
|
||||||
|
{
|
||||||
|
/// <summary>Thumbnail type</summary>
|
||||||
|
public string type;
|
||||||
|
public FileLocationBase location;
|
||||||
|
/// <summary>Image width</summary>
|
||||||
|
public int w;
|
||||||
|
/// <summary>Image height</summary>
|
||||||
|
public int h;
|
||||||
|
/// <summary>Binary data, file content</summary>
|
||||||
|
public byte[] bytes;
|
||||||
|
|
||||||
|
/// <summary>Thumbnail type</summary>
|
||||||
|
public override string Type => type;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>User is uploading a video. <para>See <a href="https://corefork.telegram.org/constructor/sendMessageUploadVideoAction"/></para></summary>
|
/// <summary>User is uploading a video. <para>See <a href="https://corefork.telegram.org/constructor/sendMessageUploadVideoAction"/></para></summary>
|
||||||
[TLDef(0x92042FF7)]
|
[TLDef(0x92042FF7)]
|
||||||
public class SendMessageUploadVideoAction : SendMessageAction { }
|
public class SendMessageUploadVideoAction : SendMessageAction { }
|
||||||
|
|
@ -248,6 +283,28 @@ namespace TL
|
||||||
[TLDef(0x8FAEE98E)]
|
[TLDef(0x8FAEE98E)]
|
||||||
public class SendMessageUploadDocumentAction : SendMessageAction { }
|
public class SendMessageUploadDocumentAction : SendMessageAction { }
|
||||||
|
|
||||||
|
/// <summary>Defines a sticker <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeSticker"/></para></summary>
|
||||||
|
[TLDef(0xFB0A5727)]
|
||||||
|
public class DocumentAttributeSticker : DocumentAttribute { }
|
||||||
|
/// <summary>Defines a video <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeVideo"/></para></summary>
|
||||||
|
[TLDef(0x5910CCCB)]
|
||||||
|
public class DocumentAttributeVideo : DocumentAttribute
|
||||||
|
{
|
||||||
|
/// <summary>Duration in seconds</summary>
|
||||||
|
public int duration;
|
||||||
|
/// <summary>Video width</summary>
|
||||||
|
public int w;
|
||||||
|
/// <summary>Video height</summary>
|
||||||
|
public int h;
|
||||||
|
}
|
||||||
|
/// <summary>Represents an audio file <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeAudio"/></para></summary>
|
||||||
|
[TLDef(0x051448E5)]
|
||||||
|
public class DocumentAttributeAudio : DocumentAttribute
|
||||||
|
{
|
||||||
|
/// <summary>Duration in seconds</summary>
|
||||||
|
public int duration;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessage"/></para></summary>
|
/// <summary>Contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessage"/></para></summary>
|
||||||
[TLDef(0x204D3878)]
|
[TLDef(0x204D3878)]
|
||||||
public class DecryptedMessage : DecryptedMessageBase
|
public class DecryptedMessage : DecryptedMessageBase
|
||||||
|
|
@ -313,7 +370,7 @@ namespace TL
|
||||||
/// <summary>MIME-type of the video file<br/>Parameter added in Layer 17.</summary>
|
/// <summary>MIME-type of the video file<br/>Parameter added in Layer 17.</summary>
|
||||||
public override string MimeType => mime_type;
|
public override string MimeType => mime_type;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>Audio file attached to a secret chat message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaAudio"/></para></summary>
|
/// <summary>Audio file attached to a secret chat message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaAudio"/></para></summary>
|
||||||
[TLDef(0x57E0A9CB)]
|
[TLDef(0x57E0A9CB)]
|
||||||
|
|
@ -333,7 +390,31 @@ namespace TL
|
||||||
/// <summary>MIME-type of the audio file<br/>Parameter added in Layer 13.</summary>
|
/// <summary>MIME-type of the audio file<br/>Parameter added in Layer 13.</summary>
|
||||||
public override string MimeType => mime_type;
|
public override string MimeType => mime_type;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
|
}
|
||||||
|
/// <summary>Non-e2e documented forwarded from non-secret chat <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaExternalDocument"/></para></summary>
|
||||||
|
[TLDef(0xFA95B0DD)]
|
||||||
|
public class DecryptedMessageMediaExternalDocument : DecryptedMessageMedia
|
||||||
|
{
|
||||||
|
/// <summary>Document ID</summary>
|
||||||
|
public long id;
|
||||||
|
/// <summary>access hash</summary>
|
||||||
|
public long access_hash;
|
||||||
|
/// <summary>Date</summary>
|
||||||
|
public DateTime date;
|
||||||
|
/// <summary>Mime type</summary>
|
||||||
|
public string mime_type;
|
||||||
|
/// <summary>Size</summary>
|
||||||
|
public int size;
|
||||||
|
/// <summary>Thumbnail</summary>
|
||||||
|
public PhotoSizeBase thumb;
|
||||||
|
/// <summary>DC ID</summary>
|
||||||
|
public int dc_id;
|
||||||
|
/// <summary>Attributes for media types</summary>
|
||||||
|
public DocumentAttribute[] attributes;
|
||||||
|
|
||||||
|
/// <summary>Mime type</summary>
|
||||||
|
public override string MimeType => mime_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Request for the other party in a Secret Chat to automatically resend a contiguous range of previously sent messages, as explained in <a href="https://corefork.telegram.org/api/end-to-end/seq_no">Sequence number is Secret Chats</a>. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionResend"/></para></summary>
|
/// <summary>Request for the other party in a Secret Chat to automatically resend a contiguous range of previously sent messages, as explained in <a href="https://corefork.telegram.org/api/end-to-end/seq_no">Sequence number is Secret Chats</a>. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionResend"/></para></summary>
|
||||||
|
|
@ -359,6 +440,45 @@ namespace TL
|
||||||
/// <summary>Type of action</summary>
|
/// <summary>Type of action</summary>
|
||||||
public SendMessageAction action;
|
public SendMessageAction action;
|
||||||
}
|
}
|
||||||
|
/// <summary>Request rekeying, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a> <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionRequestKey"/></para></summary>
|
||||||
|
[TLDef(0xF3C9611B)]
|
||||||
|
public class DecryptedMessageActionRequestKey : DecryptedMessageAction
|
||||||
|
{
|
||||||
|
/// <summary>Exchange ID</summary>
|
||||||
|
public long exchange_id;
|
||||||
|
/// <summary>g_a, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
||||||
|
public byte[] g_a;
|
||||||
|
}
|
||||||
|
/// <summary>Accept new key <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionAcceptKey"/></para></summary>
|
||||||
|
[TLDef(0x6FE1735B)]
|
||||||
|
public class DecryptedMessageActionAcceptKey : DecryptedMessageAction
|
||||||
|
{
|
||||||
|
/// <summary>Exchange ID</summary>
|
||||||
|
public long exchange_id;
|
||||||
|
/// <summary>B parameter, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
||||||
|
public byte[] g_b;
|
||||||
|
/// <summary>Key fingerprint, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
||||||
|
public long key_fingerprint;
|
||||||
|
}
|
||||||
|
/// <summary>Abort rekeying <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionAbortKey"/></para></summary>
|
||||||
|
[TLDef(0xDD05EC6B)]
|
||||||
|
public class DecryptedMessageActionAbortKey : DecryptedMessageAction
|
||||||
|
{
|
||||||
|
/// <summary>Exchange ID</summary>
|
||||||
|
public long exchange_id;
|
||||||
|
}
|
||||||
|
/// <summary>Commit new key, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a> <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionCommitKey"/></para></summary>
|
||||||
|
[TLDef(0xEC2E0B9B)]
|
||||||
|
public class DecryptedMessageActionCommitKey : DecryptedMessageAction
|
||||||
|
{
|
||||||
|
/// <summary>Exchange ID, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
||||||
|
public long exchange_id;
|
||||||
|
/// <summary>Key fingerprint, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
||||||
|
public long key_fingerprint;
|
||||||
|
}
|
||||||
|
/// <summary>NOOP action <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionNoop"/></para></summary>
|
||||||
|
[TLDef(0xA82FDD63)]
|
||||||
|
public class DecryptedMessageActionNoop : DecryptedMessageAction { }
|
||||||
|
|
||||||
/// <summary>Sets the layer number for the contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageLayer"/></para></summary>
|
/// <summary>Sets the layer number for the contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageLayer"/></para></summary>
|
||||||
[TLDef(0x1BE31789)]
|
[TLDef(0x1BE31789)]
|
||||||
|
|
@ -375,19 +495,49 @@ namespace TL
|
||||||
/// <summary>The content of message itself</summary>
|
/// <summary>The content of message itself</summary>
|
||||||
public DecryptedMessageBase message;
|
public DecryptedMessageBase message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>File is currently unavailable. <para>See <a href="https://corefork.telegram.org/constructor/fileLocationUnavailable"/></para></summary>
|
||||||
|
[TLDef(0x7C596B46)]
|
||||||
|
public class FileLocationUnavailable : FileLocationBase
|
||||||
|
{
|
||||||
|
/// <summary>Server volume</summary>
|
||||||
|
public long volume_id;
|
||||||
|
/// <summary>File ID</summary>
|
||||||
|
public int local_id;
|
||||||
|
/// <summary>Checksum to access the file</summary>
|
||||||
|
public long secret;
|
||||||
|
|
||||||
|
/// <summary>Server volume</summary>
|
||||||
|
public override long VolumeId => volume_id;
|
||||||
|
/// <summary>File ID</summary>
|
||||||
|
public override int LocalId => local_id;
|
||||||
|
/// <summary>Checksum to access the file</summary>
|
||||||
|
public override long Secret => secret;
|
||||||
|
}
|
||||||
|
/// <summary>File location. <para>See <a href="https://corefork.telegram.org/constructor/fileLocation"/></para></summary>
|
||||||
|
[TLDef(0x53D69076)]
|
||||||
|
public class FileLocation : FileLocationBase
|
||||||
|
{
|
||||||
|
/// <summary>Number of the data center holding the file</summary>
|
||||||
|
public int dc_id;
|
||||||
|
/// <summary>Server volume</summary>
|
||||||
|
public long volume_id;
|
||||||
|
/// <summary>File ID</summary>
|
||||||
|
public int local_id;
|
||||||
|
/// <summary>Checksum to access the file</summary>
|
||||||
|
public long secret;
|
||||||
|
|
||||||
|
/// <summary>Server volume</summary>
|
||||||
|
public override long VolumeId => volume_id;
|
||||||
|
/// <summary>File ID</summary>
|
||||||
|
public override int LocalId => local_id;
|
||||||
|
/// <summary>Checksum to access the file</summary>
|
||||||
|
public override long Secret => secret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Layer45
|
namespace Layer45
|
||||||
{
|
{
|
||||||
/// <summary>Defines a sticker <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeSticker"/></para></summary>
|
|
||||||
[TLDef(0x3A556302)]
|
|
||||||
public class DocumentAttributeSticker : DocumentAttribute
|
|
||||||
{
|
|
||||||
/// <summary>Alternative emoji representation of sticker</summary>
|
|
||||||
public string alt;
|
|
||||||
/// <summary>Associated stickerset</summary>
|
|
||||||
public InputStickerSet stickerset;
|
|
||||||
}
|
|
||||||
/// <summary>Represents an audio file <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeAudio"/></para></summary>
|
/// <summary>Represents an audio file <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeAudio"/></para></summary>
|
||||||
[TLDef(0xDED218E0)]
|
[TLDef(0xDED218E0)]
|
||||||
public class DocumentAttributeAudio : DocumentAttribute
|
public class DocumentAttributeAudio : DocumentAttribute
|
||||||
|
|
@ -399,6 +549,27 @@ namespace TL
|
||||||
/// <summary>Performer</summary>
|
/// <summary>Performer</summary>
|
||||||
public string performer;
|
public string performer;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Layer46
|
||||||
|
{
|
||||||
|
/// <summary>Defines a sticker <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeSticker"/></para></summary>
|
||||||
|
[TLDef(0x3A556302)]
|
||||||
|
public class DocumentAttributeSticker : DocumentAttribute
|
||||||
|
{
|
||||||
|
/// <summary>Alternative emoji representation of sticker</summary>
|
||||||
|
public string alt;
|
||||||
|
/// <summary>Associated stickerset</summary>
|
||||||
|
public InputStickerSet stickerset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Message entity representing a <a href="https://corefork.telegram.org/api/mentions">user mention</a>: for <em>creating</em> a mention use <see cref="InputMessageEntityMentionName"/>. <para>See <a href="https://corefork.telegram.org/constructor/messageEntityMentionName"/></para></summary>
|
||||||
|
[TLDef(0x352DCA58, inheritBefore = true)]
|
||||||
|
public class MessageEntityMentionName : MessageEntityMention
|
||||||
|
{
|
||||||
|
/// <summary>Identifier of the user that was mentioned</summary>
|
||||||
|
public int user_id;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessage"/></para></summary>
|
/// <summary>Contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessage"/></para></summary>
|
||||||
[TLDef(0x36B091DE)]
|
[TLDef(0x36B091DE)]
|
||||||
|
|
@ -475,7 +646,7 @@ namespace TL
|
||||||
public string caption;
|
public string caption;
|
||||||
|
|
||||||
public override string MimeType => "image/jpeg";
|
public override string MimeType => "image/jpeg";
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>Video attached to an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaVideo"/></para></summary>
|
/// <summary>Video attached to an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaVideo"/></para></summary>
|
||||||
[TLDef(0x970C8C0E)]
|
[TLDef(0x970C8C0E)]
|
||||||
|
|
@ -507,7 +678,7 @@ namespace TL
|
||||||
/// <summary>MIME-type of the video file<br/>Parameter added in Layer 17.</summary>
|
/// <summary>MIME-type of the video file<br/>Parameter added in Layer 17.</summary>
|
||||||
public override string MimeType => mime_type;
|
public override string MimeType => mime_type;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>Document attached to a message in a secret chat. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaDocument"/></para></summary>
|
/// <summary>Document attached to a message in a secret chat. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaDocument"/></para></summary>
|
||||||
[TLDef(0x7AFE8AE2)]
|
[TLDef(0x7AFE8AE2)]
|
||||||
|
|
@ -535,7 +706,7 @@ namespace TL
|
||||||
/// <summary>File MIME-type</summary>
|
/// <summary>File MIME-type</summary>
|
||||||
public override string MimeType => mime_type;
|
public override string MimeType => mime_type;
|
||||||
|
|
||||||
internal override (int, byte[], byte[]) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = (checked((int)value.size), value.key, value.iv); }
|
||||||
}
|
}
|
||||||
/// <summary>Venue <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaVenue"/></para></summary>
|
/// <summary>Venue <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaVenue"/></para></summary>
|
||||||
[TLDef(0x8A0DF56F)]
|
[TLDef(0x8A0DF56F)]
|
||||||
|
|
@ -563,6 +734,13 @@ namespace TL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Layer66
|
||||||
|
{
|
||||||
|
/// <summary>User is uploading a round video <para>See <a href="https://corefork.telegram.org/constructor/sendMessageUploadRoundAction"/></para></summary>
|
||||||
|
[TLDef(0xBB718624)]
|
||||||
|
public class SendMessageUploadRoundAction : SendMessageAction { }
|
||||||
|
}
|
||||||
|
|
||||||
namespace Layer73
|
namespace Layer73
|
||||||
{
|
{
|
||||||
/// <summary>Contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessage"/></para></summary>
|
/// <summary>Contents of an encrypted message. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessage"/></para></summary>
|
||||||
|
|
@ -592,6 +770,8 @@ namespace TL
|
||||||
{
|
{
|
||||||
/// <summary>Field <see cref="reply_to_random_id"/> has a value</summary>
|
/// <summary>Field <see cref="reply_to_random_id"/> has a value</summary>
|
||||||
has_reply_to_random_id = 0x8,
|
has_reply_to_random_id = 0x8,
|
||||||
|
/// <summary>Whether this is a silent message (no notification triggered)</summary>
|
||||||
|
silent = 0x20,
|
||||||
/// <summary>Field <see cref="entities"/> has a value</summary>
|
/// <summary>Field <see cref="entities"/> has a value</summary>
|
||||||
has_entities = 0x80,
|
has_entities = 0x80,
|
||||||
/// <summary>Field <see cref="media"/> has a value</summary>
|
/// <summary>Field <see cref="media"/> has a value</summary>
|
||||||
|
|
@ -623,180 +803,41 @@ namespace TL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Layer20
|
namespace Layer101
|
||||||
|
{ }
|
||||||
|
|
||||||
|
namespace Layer143
|
||||||
{
|
{
|
||||||
/// <summary>Request rekeying, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a> <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionRequestKey"/></para></summary>
|
/// <summary>Document attached to a message in a secret chat. <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaDocument"/></para></summary>
|
||||||
[TLDef(0xF3C9611B)]
|
[TLDef(0x6ABD9782)]
|
||||||
public class DecryptedMessageActionRequestKey : DecryptedMessageAction
|
public class DecryptedMessageMediaDocument : DecryptedMessageMedia
|
||||||
{
|
{
|
||||||
/// <summary>Exchange ID</summary>
|
/// <summary>Thumbnail-file contents (JPEG-file, quality 55, set in a 90x90 square)</summary>
|
||||||
public long exchange_id;
|
public byte[] thumb;
|
||||||
/// <summary>g_a, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
/// <summary>Thumbnail width</summary>
|
||||||
public byte[] g_a;
|
public int thumb_w;
|
||||||
}
|
/// <summary>Thumbnail height</summary>
|
||||||
/// <summary>Accept new key <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionAcceptKey"/></para></summary>
|
public int thumb_h;
|
||||||
[TLDef(0x6FE1735B)]
|
/// <summary>File MIME-type</summary>
|
||||||
public class DecryptedMessageActionAcceptKey : DecryptedMessageAction
|
|
||||||
{
|
|
||||||
/// <summary>Exchange ID</summary>
|
|
||||||
public long exchange_id;
|
|
||||||
/// <summary>B parameter, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
|
||||||
public byte[] g_b;
|
|
||||||
/// <summary>Key fingerprint, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
|
||||||
public long key_fingerprint;
|
|
||||||
}
|
|
||||||
/// <summary>Abort rekeying <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionAbortKey"/></para></summary>
|
|
||||||
[TLDef(0xDD05EC6B)]
|
|
||||||
public class DecryptedMessageActionAbortKey : DecryptedMessageAction
|
|
||||||
{
|
|
||||||
/// <summary>Exchange ID</summary>
|
|
||||||
public long exchange_id;
|
|
||||||
}
|
|
||||||
/// <summary>Commit new key, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a> <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionCommitKey"/></para></summary>
|
|
||||||
[TLDef(0xEC2E0B9B)]
|
|
||||||
public class DecryptedMessageActionCommitKey : DecryptedMessageAction
|
|
||||||
{
|
|
||||||
/// <summary>Exchange ID, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
|
||||||
public long exchange_id;
|
|
||||||
/// <summary>Key fingerprint, see <a href="https://corefork.telegram.org/api/end-to-end/pfs">rekeying process</a></summary>
|
|
||||||
public long key_fingerprint;
|
|
||||||
}
|
|
||||||
/// <summary>NOOP action <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageActionNoop"/></para></summary>
|
|
||||||
[TLDef(0xA82FDD63)]
|
|
||||||
public class DecryptedMessageActionNoop : DecryptedMessageAction { }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Layer23
|
|
||||||
{
|
|
||||||
/// <summary>Image description. <para>See <a href="https://corefork.telegram.org/constructor/photoSize"/></para></summary>
|
|
||||||
[TLDef(0x77BFB61B)]
|
|
||||||
public partial class PhotoSize : PhotoSizeBase
|
|
||||||
{
|
|
||||||
/// <summary><a href="https://corefork.telegram.org/api/files#image-thumbnail-types">Thumbnail type »</a></summary>
|
|
||||||
public string type;
|
|
||||||
public FileLocationBase location;
|
|
||||||
/// <summary>Image width</summary>
|
|
||||||
public int w;
|
|
||||||
/// <summary>Image height</summary>
|
|
||||||
public int h;
|
|
||||||
/// <summary>File size</summary>
|
|
||||||
public int size;
|
|
||||||
|
|
||||||
/// <summary><a href="https://corefork.telegram.org/api/files#image-thumbnail-types">Thumbnail type »</a></summary>
|
|
||||||
public override string Type => type;
|
|
||||||
}
|
|
||||||
/// <summary>Description of an image and its content. <para>See <a href="https://corefork.telegram.org/constructor/photoCachedSize"/></para></summary>
|
|
||||||
[TLDef(0xE9A734FA)]
|
|
||||||
public partial class PhotoCachedSize : PhotoSizeBase
|
|
||||||
{
|
|
||||||
/// <summary>Thumbnail type</summary>
|
|
||||||
public string type;
|
|
||||||
public FileLocationBase location;
|
|
||||||
/// <summary>Image width</summary>
|
|
||||||
public int w;
|
|
||||||
/// <summary>Image height</summary>
|
|
||||||
public int h;
|
|
||||||
/// <summary>Binary data, file content</summary>
|
|
||||||
public byte[] bytes;
|
|
||||||
|
|
||||||
/// <summary>Thumbnail type</summary>
|
|
||||||
public override string Type => type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Defines a sticker <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeSticker"/></para></summary>
|
|
||||||
[TLDef(0xFB0A5727)]
|
|
||||||
public class DocumentAttributeSticker : DocumentAttribute { }
|
|
||||||
/// <summary>Defines a video <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeVideo"/></para></summary>
|
|
||||||
[TLDef(0x5910CCCB)]
|
|
||||||
public class DocumentAttributeVideo : DocumentAttribute
|
|
||||||
{
|
|
||||||
/// <summary>Duration in seconds</summary>
|
|
||||||
public int duration;
|
|
||||||
/// <summary>Video width</summary>
|
|
||||||
public int w;
|
|
||||||
/// <summary>Video height</summary>
|
|
||||||
public int h;
|
|
||||||
}
|
|
||||||
/// <summary>Represents an audio file <para>See <a href="https://corefork.telegram.org/constructor/documentAttributeAudio"/></para></summary>
|
|
||||||
[TLDef(0x051448E5)]
|
|
||||||
public class DocumentAttributeAudio : DocumentAttribute
|
|
||||||
{
|
|
||||||
/// <summary>Duration in seconds</summary>
|
|
||||||
public int duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Non-e2e documented forwarded from non-secret chat <para>See <a href="https://corefork.telegram.org/constructor/decryptedMessageMediaExternalDocument"/></para></summary>
|
|
||||||
[TLDef(0xFA95B0DD)]
|
|
||||||
public class DecryptedMessageMediaExternalDocument : DecryptedMessageMedia
|
|
||||||
{
|
|
||||||
/// <summary>Document ID</summary>
|
|
||||||
public long id;
|
|
||||||
/// <summary>access hash</summary>
|
|
||||||
public long access_hash;
|
|
||||||
/// <summary>Date</summary>
|
|
||||||
public DateTime date;
|
|
||||||
/// <summary>Mime type</summary>
|
|
||||||
public string mime_type;
|
public string mime_type;
|
||||||
/// <summary>Size</summary>
|
/// <summary>Document size (<see cref="int"/> on layer <143, <see cref="long"/> on layer >=143)</summary>
|
||||||
public int size;
|
public long size;
|
||||||
/// <summary>Thumbnail</summary>
|
/// <summary>Key to decrypt the attached document file</summary>
|
||||||
public PhotoSizeBase thumb;
|
public byte[] key;
|
||||||
/// <summary>DC ID</summary>
|
/// <summary>Initialization</summary>
|
||||||
public int dc_id;
|
public byte[] iv;
|
||||||
/// <summary>Attributes for media types</summary>
|
/// <summary>Document attributes for media types</summary>
|
||||||
public DocumentAttribute[] attributes;
|
public DocumentAttribute[] attributes;
|
||||||
|
/// <summary>Caption</summary>
|
||||||
|
public string caption;
|
||||||
|
|
||||||
/// <summary>Mime type</summary>
|
/// <summary>File MIME-type</summary>
|
||||||
public override string MimeType => mime_type;
|
public override string MimeType => mime_type;
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>File is currently unavailable. <para>See <a href="https://corefork.telegram.org/constructor/fileLocationUnavailable"/></para></summary>
|
internal override (long size, byte[] key, byte[] iv) SizeKeyIV { get => (size, key, iv); set => (size, key, iv) = value; }
|
||||||
[TLDef(0x7C596B46)]
|
|
||||||
public class FileLocationUnavailable : FileLocationBase
|
|
||||||
{
|
|
||||||
/// <summary>Server volume</summary>
|
|
||||||
public long volume_id;
|
|
||||||
/// <summary>File ID</summary>
|
|
||||||
public int local_id;
|
|
||||||
/// <summary>Checksum to access the file</summary>
|
|
||||||
public long secret;
|
|
||||||
|
|
||||||
/// <summary>Server volume</summary>
|
|
||||||
public override long VolumeId => volume_id;
|
|
||||||
/// <summary>File ID</summary>
|
|
||||||
public override int LocalId => local_id;
|
|
||||||
/// <summary>Checksum to access the file</summary>
|
|
||||||
public override long Secret => secret;
|
|
||||||
}
|
|
||||||
/// <summary>File location. <para>See <a href="https://corefork.telegram.org/constructor/fileLocation"/></para></summary>
|
|
||||||
[TLDef(0x53D69076)]
|
|
||||||
public class FileLocation : FileLocationBase
|
|
||||||
{
|
|
||||||
/// <summary>Number of the data center holding the file</summary>
|
|
||||||
public int dc_id;
|
|
||||||
/// <summary>Server volume</summary>
|
|
||||||
public long volume_id;
|
|
||||||
/// <summary>File ID</summary>
|
|
||||||
public int local_id;
|
|
||||||
/// <summary>Checksum to access the file</summary>
|
|
||||||
public long secret;
|
|
||||||
|
|
||||||
/// <summary>Server volume</summary>
|
|
||||||
public override long VolumeId => volume_id;
|
|
||||||
/// <summary>File ID</summary>
|
|
||||||
public override int LocalId => local_id;
|
|
||||||
/// <summary>Checksum to access the file</summary>
|
|
||||||
public override long Secret => secret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Layer66
|
namespace Layer144
|
||||||
{
|
|
||||||
/// <summary>User is uploading a round video <para>See <a href="https://corefork.telegram.org/constructor/sendMessageUploadRoundAction"/></para></summary>
|
|
||||||
[TLDef(0xBB718624)]
|
|
||||||
public class SendMessageUploadRoundAction : SendMessageAction { }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Layer46
|
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace TL
|
||||||
public static class Layer
|
public static class Layer
|
||||||
{
|
{
|
||||||
public const int Version = 148; // fetched 01/11/2022 17:33:23
|
public const int Version = 148; // fetched 01/11/2022 17:33:23
|
||||||
internal const int SecretChats = 101;
|
internal const int SecretChats = 144;
|
||||||
internal const int MTProto2 = 73;
|
internal const int MTProto2 = 73;
|
||||||
internal const uint VectorCtor = 0x1CB5C415;
|
internal const uint VectorCtor = 0x1CB5C415;
|
||||||
internal const uint NullCtor = 0x56730BCC;
|
internal const uint NullCtor = 0x56730BCC;
|
||||||
|
|
@ -1047,54 +1047,56 @@ namespace TL
|
||||||
[0x71701DA9] = typeof(ForumTopic),
|
[0x71701DA9] = typeof(ForumTopic),
|
||||||
[0x367617D3] = typeof(Messages_ForumTopics),
|
[0x367617D3] = typeof(Messages_ForumTopics),
|
||||||
// from TL.Secret:
|
// from TL.Secret:
|
||||||
|
[0x6ABD9782] = typeof(Layer143.DecryptedMessageMediaDocument),
|
||||||
|
[0x91CC4674] = typeof(Layer73.DecryptedMessage),
|
||||||
[0xBB718624] = typeof(Layer66.SendMessageUploadRoundAction),
|
[0xBB718624] = typeof(Layer66.SendMessageUploadRoundAction),
|
||||||
[0xE50511D8] = typeof(Layer45.DecryptedMessageMediaWebPage),
|
[0xE50511D8] = typeof(Layer46.DecryptedMessageMediaWebPage),
|
||||||
[0x8A0DF56F] = typeof(Layer45.DecryptedMessageMediaVenue),
|
[0x8A0DF56F] = typeof(Layer46.DecryptedMessageMediaVenue),
|
||||||
|
[0x352DCA58] = typeof(Layer46.MessageEntityMentionName),
|
||||||
|
[0x3A556302] = typeof(Layer46.DocumentAttributeSticker),
|
||||||
|
[0x7AFE8AE2] = typeof(Layer46.DecryptedMessageMediaDocument),
|
||||||
|
[0x970C8C0E] = typeof(Layer46.DecryptedMessageMediaVideo),
|
||||||
|
[0xF1FA8D78] = typeof(Layer46.DecryptedMessageMediaPhoto),
|
||||||
|
[0x36B091DE] = typeof(Layer46.DecryptedMessage),
|
||||||
|
[0xDED218E0] = typeof(Layer45.DocumentAttributeAudio),
|
||||||
[0xFA95B0DD] = typeof(Layer23.DecryptedMessageMediaExternalDocument),
|
[0xFA95B0DD] = typeof(Layer23.DecryptedMessageMediaExternalDocument),
|
||||||
[0x53D69076] = typeof(Layer23.FileLocation),
|
[0x53D69076] = typeof(Layer23.FileLocation),
|
||||||
[0x7C596B46] = typeof(Layer23.FileLocationUnavailable),
|
[0x7C596B46] = typeof(Layer23.FileLocationUnavailable),
|
||||||
[0xE9A734FA] = typeof(Layer23.PhotoCachedSize),
|
[0xE9A734FA] = typeof(Layer23.PhotoCachedSize),
|
||||||
[0x77BFB61B] = typeof(Layer23.PhotoSize),
|
[0x77BFB61B] = typeof(Layer23.PhotoSize),
|
||||||
[0xDED218E0] = typeof(Layer45.DocumentAttributeAudio),
|
|
||||||
[0x051448E5] = typeof(Layer23.DocumentAttributeAudio),
|
[0x051448E5] = typeof(Layer23.DocumentAttributeAudio),
|
||||||
[0x5910CCCB] = typeof(Layer23.DocumentAttributeVideo),
|
[0x5910CCCB] = typeof(Layer23.DocumentAttributeVideo),
|
||||||
[0x3A556302] = typeof(Layer45.DocumentAttributeSticker),
|
|
||||||
[0xFB0A5727] = typeof(Layer23.DocumentAttributeSticker),
|
[0xFB0A5727] = typeof(Layer23.DocumentAttributeSticker),
|
||||||
[0xA82FDD63] = typeof(Layer20.DecryptedMessageActionNoop),
|
[0xA82FDD63] = typeof(Layer23.DecryptedMessageActionNoop),
|
||||||
[0xEC2E0B9B] = typeof(Layer20.DecryptedMessageActionCommitKey),
|
[0xEC2E0B9B] = typeof(Layer23.DecryptedMessageActionCommitKey),
|
||||||
[0xDD05EC6B] = typeof(Layer20.DecryptedMessageActionAbortKey),
|
[0xDD05EC6B] = typeof(Layer23.DecryptedMessageActionAbortKey),
|
||||||
[0x6FE1735B] = typeof(Layer20.DecryptedMessageActionAcceptKey),
|
[0x6FE1735B] = typeof(Layer23.DecryptedMessageActionAcceptKey),
|
||||||
[0xF3C9611B] = typeof(Layer20.DecryptedMessageActionRequestKey),
|
[0xF3C9611B] = typeof(Layer23.DecryptedMessageActionRequestKey),
|
||||||
[0xCCB27641] = typeof(Layer17.DecryptedMessageActionTyping),
|
[0xCCB27641] = typeof(Layer23.DecryptedMessageActionTyping),
|
||||||
[0xF3048883] = typeof(Layer17.DecryptedMessageActionNotifyLayer),
|
[0xF3048883] = typeof(Layer23.DecryptedMessageActionNotifyLayer),
|
||||||
[0x511110B0] = typeof(Layer17.DecryptedMessageActionResend),
|
[0x511110B0] = typeof(Layer23.DecryptedMessageActionResend),
|
||||||
[0x8FAEE98E] = typeof(Layer17.SendMessageUploadDocumentAction),
|
[0x8FAEE98E] = typeof(Layer23.SendMessageUploadDocumentAction),
|
||||||
[0x990A3C1A] = typeof(Layer17.SendMessageUploadPhotoAction),
|
[0x990A3C1A] = typeof(Layer23.SendMessageUploadPhotoAction),
|
||||||
[0xE6AC8A6F] = typeof(Layer17.SendMessageUploadAudioAction),
|
[0xE6AC8A6F] = typeof(Layer23.SendMessageUploadAudioAction),
|
||||||
[0x92042FF7] = typeof(Layer17.SendMessageUploadVideoAction),
|
[0x92042FF7] = typeof(Layer23.SendMessageUploadVideoAction),
|
||||||
[0x1BE31789] = typeof(Layer17.DecryptedMessageLayer),
|
[0x1BE31789] = typeof(Layer23.DecryptedMessageLayer),
|
||||||
|
[0x57E0A9CB] = typeof(Layer23.DecryptedMessageMediaAudio),
|
||||||
|
[0x524A415D] = typeof(Layer23.DecryptedMessageMediaVideo),
|
||||||
|
[0x73164160] = typeof(Layer23.DecryptedMessageService),
|
||||||
|
[0x204D3878] = typeof(Layer23.DecryptedMessage),
|
||||||
[0x6719E45C] = typeof(Layer8.DecryptedMessageActionFlushHistory),
|
[0x6719E45C] = typeof(Layer8.DecryptedMessageActionFlushHistory),
|
||||||
[0x8AC1F475] = typeof(Layer8.DecryptedMessageActionScreenshotMessages),
|
[0x8AC1F475] = typeof(Layer8.DecryptedMessageActionScreenshotMessages),
|
||||||
[0x65614304] = typeof(Layer8.DecryptedMessageActionDeleteMessages),
|
[0x65614304] = typeof(Layer8.DecryptedMessageActionDeleteMessages),
|
||||||
[0x0C4F40BE] = typeof(Layer8.DecryptedMessageActionReadMessages),
|
[0x0C4F40BE] = typeof(Layer8.DecryptedMessageActionReadMessages),
|
||||||
[0x57E0A9CB] = typeof(Layer17.DecryptedMessageMediaAudio),
|
|
||||||
[0x6080758F] = typeof(Layer8.DecryptedMessageMediaAudio),
|
[0x6080758F] = typeof(Layer8.DecryptedMessageMediaAudio),
|
||||||
[0x7AFE8AE2] = typeof(Layer45.DecryptedMessageMediaDocument),
|
|
||||||
[0xB095434B] = typeof(Layer8.DecryptedMessageMediaDocument),
|
[0xB095434B] = typeof(Layer8.DecryptedMessageMediaDocument),
|
||||||
[0xA1733AEC] = typeof(Layer8.DecryptedMessageActionSetMessageTTL),
|
[0xA1733AEC] = typeof(Layer8.DecryptedMessageActionSetMessageTTL),
|
||||||
[0x588A0A97] = typeof(Layer8.DecryptedMessageMediaContact),
|
[0x588A0A97] = typeof(Layer8.DecryptedMessageMediaContact),
|
||||||
[0x35480A59] = typeof(Layer8.DecryptedMessageMediaGeoPoint),
|
[0x35480A59] = typeof(Layer8.DecryptedMessageMediaGeoPoint),
|
||||||
[0x970C8C0E] = typeof(Layer45.DecryptedMessageMediaVideo),
|
|
||||||
[0x524A415D] = typeof(Layer17.DecryptedMessageMediaVideo),
|
|
||||||
[0x4CEE6EF3] = typeof(Layer8.DecryptedMessageMediaVideo),
|
[0x4CEE6EF3] = typeof(Layer8.DecryptedMessageMediaVideo),
|
||||||
[0xF1FA8D78] = typeof(Layer45.DecryptedMessageMediaPhoto),
|
|
||||||
[0x32798A8C] = typeof(Layer8.DecryptedMessageMediaPhoto),
|
[0x32798A8C] = typeof(Layer8.DecryptedMessageMediaPhoto),
|
||||||
[0x089F5C4A] = null,//Layer8.DecryptedMessageMediaEmpty
|
[0x089F5C4A] = null,//Layer8.DecryptedMessageMediaEmpty
|
||||||
[0x73164160] = typeof(Layer17.DecryptedMessageService),
|
|
||||||
[0xAA48327D] = typeof(Layer8.DecryptedMessageService),
|
[0xAA48327D] = typeof(Layer8.DecryptedMessageService),
|
||||||
[0x91CC4674] = typeof(Layer73.DecryptedMessage),
|
|
||||||
[0x36B091DE] = typeof(Layer45.DecryptedMessage),
|
|
||||||
[0x204D3878] = typeof(Layer17.DecryptedMessage),
|
|
||||||
[0x1F814F1F] = typeof(Layer8.DecryptedMessage),
|
[0x1F814F1F] = typeof(Layer8.DecryptedMessage),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue