Convert TL functions to extension methods

This commit is contained in:
Wizou 2021-09-17 04:53:02 +02:00
parent 77a44a86a6
commit 37974c70b7
7 changed files with 881 additions and 882 deletions

View file

@ -20,7 +20,7 @@ using static WTelegram.Encryption;
namespace WTelegram
{
public sealed partial class Client : IDisposable
public sealed class Client : IDisposable
{
public event Action<ITLObject> Update;
public Config TLConfig { get; private set; }
@ -130,15 +130,15 @@ namespace WTelegram
if (_session.AuthKey == null)
await CreateAuthorizationKey(this, _session);
TLConfig = await InvokeWithLayer<Config>(Schema.Layer,
InitConnection(_apiId,
TLConfig = await this.InvokeWithLayer<Config>(Layer.Version,
Schema.InitConnection(_apiId,
Config("device_model"),
Config("system_version"),
Config("app_version"),
Config("system_lang_code"),
Config("lang_pack"),
Config("lang_code"),
Help_GetConfig));
Schema.Help_GetConfig));
Helpers.Log(2, $"Connected to {(TLConfig.test_mode ? "Test DC" : "DC")} {TLConfig.this_dc}... {TLConfig.flags & (Config.Flags)~0xE00}");
}
@ -147,7 +147,7 @@ namespace WTelegram
Helpers.Log(2, $"Migrate to DC {dcId}...");
Auth_ExportedAuthorization exported = null;
if (_session.User != null)
exported = await Auth_ExportAuthorization(dcId);
exported = await this.Auth_ExportAuthorization(dcId);
var prevFamily = _tcpClient.Client.RemoteEndPoint.AddressFamily;
Reset(false);
var dcOptions = TLConfig.dc_options.Where(dc => dc.id == dcId && (dc.flags & (DcOption.Flags.media_only | DcOption.Flags.cdn)) == 0);
@ -160,7 +160,7 @@ namespace WTelegram
await ConnectAsync();
if (exported != null)
{
var authorization = await Auth_ImportAuthorization(exported.id, exported.bytes);
var authorization = await this.Auth_ImportAuthorization(exported.id, exported.bytes);
if (authorization is not Auth_Authorization { user: User user })
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
_session.User = user.Serialize();
@ -173,7 +173,7 @@ namespace WTelegram
while (!ct.IsCancellationRequested)
{
await Task.Delay(60000, ct);
await PingDelayDisconnect(ping_id++, 75);
await this.PingDelayDisconnect(ping_id++, 75);
}
}
@ -292,12 +292,12 @@ namespace WTelegram
throw new ApplicationException($"Mismatch between MsgKey & decrypted SHA1");
#endif
var ctorNb = reader.ReadUInt32();
if (ctorNb == Schema.MsgContainer)
if (ctorNb == Layer.MsgContainerCtor)
{
Helpers.Log(1, $"Receiving {"MsgContainer",-50} {msgStamp:u} (svc)");
return ReadMsgContainer(reader);
}
else if (ctorNb == Schema.RpcResult)
else if (ctorNb == Layer.RpcResultCtor)
{
Helpers.Log(1, $"Receiving {"RpcResult",-50} {msgStamp:u}");
return ReadRpcResult(reader);
@ -451,7 +451,7 @@ namespace WTelegram
try
{
var ctorNb = reader.ReadUInt32();
if (ctorNb == Schema.RpcResult)
if (ctorNb == Layer.RpcResultCtor)
{
Helpers.Log(1, $" → {"RpcResult",-48} {_session.MsgIdToStamp(msg.msg_id):u}");
msg.body = ReadRpcResult(reader);
@ -695,7 +695,7 @@ namespace WTelegram
{
try
{
var prevUser = Schema.Deserialize<User>(_session.User);
var prevUser = Serialization.Deserialize<User>(_session.User);
if (prevUser?.id == int.Parse(botToken.Split(':')[0]))
return prevUser;
}
@ -703,9 +703,9 @@ namespace WTelegram
{
Helpers.Log(4, $"Error deserializing User! ({ex.Message}) Proceeding to login...");
}
await Auth_LogOut();
await this.Auth_LogOut();
}
var authorization = await Auth_ImportBotAuthorization(0, _apiId, _apiHash, botToken);
var authorization = await this.Auth_ImportBotAuthorization(0, _apiId, _apiHash, botToken);
if (authorization is not Auth_Authorization { user: User user })
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
_session.User = user.Serialize();
@ -727,7 +727,7 @@ namespace WTelegram
{
try
{
var prevUser = Schema.Deserialize<User>(_session.User);
var prevUser = Serialization.Deserialize<User>(_session.User);
var userId = _config("user_id"); // if config prefers to validate current user by its id, use it
if (userId == null || !int.TryParse(userId, out int id) || id != -1 && prevUser.id != id)
{
@ -738,7 +738,7 @@ namespace WTelegram
if (prevUser != null)
{
// TODO: implement a more complete Updates gaps handling system? https://core.telegram.org/api/updates
var udpatesState = await Updates_GetState();
var udpatesState = await this.Updates_GetState();
OnUpdate(udpatesState);
return prevUser;
}
@ -747,23 +747,23 @@ namespace WTelegram
{
Helpers.Log(4, $"Error deserializing User! ({ex.Message}) Proceeding to login...");
}
await Auth_LogOut();
await this.Auth_LogOut();
}
phone_number ??= Config("phone_number");
var sentCode = await Auth_SendCode(phone_number, _apiId, _apiHash, settings ?? new());
var sentCode = await this.Auth_SendCode(phone_number, _apiId, _apiHash, settings ?? new());
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
var verification_code = Config("verification_code");
Auth_AuthorizationBase authorization;
try
{
authorization = await Auth_SignIn(phone_number, sentCode.phone_code_hash, verification_code);
authorization = await this.Auth_SignIn(phone_number, sentCode.phone_code_hash, verification_code);
}
catch (RpcException e) when (e.Code == 401 && e.Message == "SESSION_PASSWORD_NEEDED")
{
var accountPassword = await Account_GetPassword();
var accountPassword = await this.Account_GetPassword();
Helpers.Log(3, $"This account has enabled 2FA. A password is needed. {accountPassword.hint}");
var checkPasswordSRP = Check2FA(accountPassword, Config("password"));
authorization = await Auth_CheckPassword(checkPasswordSRP);
authorization = await this.Auth_CheckPassword(checkPasswordSRP);
}
if (authorization is Auth_AuthorizationSignUpRequired signUpRequired)
{
@ -774,7 +774,7 @@ namespace WTelegram
var last_name = Config("last_name");
var wait = waitUntil - DateTime.UtcNow;
if (wait > TimeSpan.Zero) await Task.Delay(wait); // we get a FLOOD_WAIT_3 if we SignUp too fast
authorization = await Auth_SignUp(phone_number, sentCode.phone_code_hash, first_name, last_name);
authorization = await this.Auth_SignUp(phone_number, sentCode.phone_code_hash, first_name, last_name);
}
if (authorization is not Auth_Authorization { user: User user })
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
@ -822,9 +822,9 @@ namespace WTelegram
try
{
if (isBig)
await Upload_SaveBigFilePart(file_id, file_part, file_total_parts, bytes);
await this.Upload_SaveBigFilePart(file_id, file_part, file_total_parts, bytes);
else
await Upload_SaveFilePart(file_id, file_part, bytes);
await this.Upload_SaveFilePart(file_id, file_part, bytes);
lock (tasks) tasks.Remove(file_part);
}
catch (Exception)
@ -881,10 +881,10 @@ namespace WTelegram
public Task<UpdatesBase> SendMessageAsync(InputPeer peer, string text, InputMedia media = null, int reply_to_msg_id = 0, MessageEntity[] entities = null, DateTime schedule_date = default, bool disable_preview = false)
{
if (media == null)
return Messages_SendMessage(peer, text, Helpers.RandomLong(),
return this.Messages_SendMessage(peer, text, Helpers.RandomLong(),
no_webpage: disable_preview, reply_to_msg_id: reply_to_msg_id, entities: entities, schedule_date: schedule_date);
else
return Messages_SendMedia(peer, media, text, Helpers.RandomLong(),
return this.Messages_SendMedia(peer, media, text, Helpers.RandomLong(),
reply_to_msg_id: reply_to_msg_id, entities: entities, schedule_date: schedule_date);
}
#endregion

View file

@ -25,7 +25,7 @@ namespace WTelegram
{
Console.WriteLine("Fetch web pages...");
#if DEBUG
currentLayer = await Task.FromResult(TL.Schema.Layer);
currentLayer = await Task.FromResult(TL.Layer.Version);
#else
using var http = new HttpClient();
//var html = await http.GetStringAsync("https://core.telegram.org/api/layers");
@ -96,12 +96,14 @@ namespace WTelegram
{
currentJson = Path.GetFileNameWithoutExtension(outputCs);
using var sw = new StreamWriter(outputCs, false, Encoding.UTF8);
sw.WriteLine("// This file is (mainly) generated automatically using the Generator class");
sw.WriteLine("// This file is generated automatically using the Generator class");
sw.WriteLine("using System;");
if (schema.methods.Count != 0) sw.WriteLine("using System.Threading.Tasks;");
sw.WriteLine();
sw.WriteLine("namespace TL");
sw.Write("{");
sw.WriteLine("{");
sw.WriteLine("\tusing BinaryWriter = System.IO.BinaryWriter;");
sw.WriteLine("\tusing Client = WTelegram.Client;");
tabIndent = "\t";
var layers = schema.constructors.GroupBy(c => c.layer).OrderBy(g => g.Key);
foreach (var layer in layers)
@ -189,14 +191,10 @@ namespace WTelegram
ctorToTypes[int.Parse(ping.id)] = CSharpName(ping.method);
WriteTypeInfo(sw, typeInfo, "", false);
}
sw.WriteLine("}");
sw.WriteLine("");
sw.WriteLine("namespace WTelegram\t\t// ---functions---");
sw.WriteLine("{");
sw.WriteLine("\tusing System.IO;");
sw.WriteLine("\tusing TL;");
sw.WriteLine();
sw.WriteLine("\tpublic partial class Client");
sw.WriteLine("\t// ---functions---");
sw.WriteLine();
sw.WriteLine($"\tpublic static class {currentJson[3..]}");
//sw.WriteLine("\tpublic static partial class Fn // ---functions---");
sw.Write("\t{");
tabIndent = "\t\t";
@ -428,11 +426,11 @@ namespace WTelegram
sw.WriteLine($"= {method.type}");
}
if (style == 0) sw.WriteLine($"{tabIndent}public Task<{returnType}> {funcName}() => {callAsync}<{returnType}>({funcName});");
if (style == 0) sw.WriteLine($"{tabIndent}public static Task<{returnType}> {funcName}(this Client client) => client.{callAsync}<{returnType}>({funcName});");
if (style == 0) sw.Write($"{tabIndent}public static string {funcName}(BinaryWriter writer");
if (style == 1) sw.Write($"{tabIndent}public static ITLFunction {funcName}(");
if (style == 2) sw.Write($"{tabIndent}public Task<{returnType}> {funcName}(");
bool first = style != 0;
if (style == 2) sw.Write($"{tabIndent}public static Task<{returnType}> {funcName}(this Client client");
bool first = style == 1;
foreach (var parm in method.@params) // output non-optional parameters
{
if (parm.type == "#" || parm.type.StartsWith("flags.")) continue;
@ -462,7 +460,7 @@ namespace WTelegram
sw.WriteLine(")");
if (style != 0) tabIndent += "\t";
if (style == 1) sw.WriteLine($"{tabIndent}=> writer =>");
if (style == 2) sw.WriteLine($"{tabIndent}=> {callAsync}<{returnType}>(writer =>");
if (style == 2) sw.WriteLine($"{tabIndent}=> client.{callAsync}<{returnType}>(writer =>");
sw.WriteLine(tabIndent + "{");
sw.WriteLine($"{tabIndent}\twriter.Write(0x{ctorNb:X8});");
foreach (var parm in method.@params) // serialize request

View file

@ -1,9 +1,12 @@
// This file is (mainly) generated automatically using the Generator class
// This file is generated automatically using the Generator class
using System;
using System.Threading.Tasks;
namespace TL
{
using BinaryWriter = System.IO.BinaryWriter;
using Client = WTelegram.Client;
[TLDef(0x05162463)] //resPQ#05162463 nonce:int128 server_nonce:int128 pq:bytes server_public_key_fingerprints:Vector<long> = ResPQ
public partial class ResPQ : ITLObject
{
@ -237,18 +240,14 @@ namespace TL
[TLDef(0x7ABE77EC)] //ping#7abe77ec ping_id:long = Pong
public partial class Ping : ITLObject { public long ping_id; }
}
namespace WTelegram // ---functions---
{
using System.IO;
using TL;
// ---functions---
public partial class Client
public static class MTProto
{
//req_pq#60469778 nonce:int128 = ResPQ
public Task<ResPQ> ReqPq(Int128 nonce)
=> CallBareAsync<ResPQ>(writer =>
public static Task<ResPQ> ReqPq(this Client client, Int128 nonce)
=> client.CallBareAsync<ResPQ>(writer =>
{
writer.Write(0x60469778);
writer.Write(nonce);
@ -256,8 +255,8 @@ namespace WTelegram // ---functions---
});
//req_pq_multi#be7e8ef1 nonce:int128 = ResPQ
public Task<ResPQ> ReqPqMulti(Int128 nonce)
=> CallBareAsync<ResPQ>(writer =>
public static Task<ResPQ> ReqPqMulti(this Client client, Int128 nonce)
=> client.CallBareAsync<ResPQ>(writer =>
{
writer.Write(0xBE7E8EF1);
writer.Write(nonce);
@ -265,8 +264,8 @@ namespace WTelegram // ---functions---
});
//req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:bytes q:bytes public_key_fingerprint:long encrypted_data:bytes = Server_DH_Params
public Task<ServerDHParams> ReqDHParams(Int128 nonce, Int128 server_nonce, byte[] p, byte[] q, long public_key_fingerprint, byte[] encrypted_data)
=> CallBareAsync<ServerDHParams>(writer =>
public static Task<ServerDHParams> ReqDHParams(this Client client, Int128 nonce, Int128 server_nonce, byte[] p, byte[] q, long public_key_fingerprint, byte[] encrypted_data)
=> client.CallBareAsync<ServerDHParams>(writer =>
{
writer.Write(0xD712E4BE);
writer.Write(nonce);
@ -279,8 +278,8 @@ namespace WTelegram // ---functions---
});
//set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer
public Task<SetClientDHParamsAnswer> SetClientDHParams(Int128 nonce, Int128 server_nonce, byte[] encrypted_data)
=> CallBareAsync<SetClientDHParamsAnswer>(writer =>
public static Task<SetClientDHParamsAnswer> SetClientDHParams(this Client client, Int128 nonce, Int128 server_nonce, byte[] encrypted_data)
=> client.CallBareAsync<SetClientDHParamsAnswer>(writer =>
{
writer.Write(0xF5045F1F);
writer.Write(nonce);
@ -290,16 +289,16 @@ namespace WTelegram // ---functions---
});
//destroy_auth_key#d1435160 = DestroyAuthKeyRes
public Task<DestroyAuthKeyRes> DestroyAuthKey()
=> CallBareAsync<DestroyAuthKeyRes>(writer =>
public static Task<DestroyAuthKeyRes> DestroyAuthKey(this Client client)
=> client.CallBareAsync<DestroyAuthKeyRes>(writer =>
{
writer.Write(0xD1435160);
return "DestroyAuthKey";
});
//rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer
public Task<RpcDropAnswer> RpcDropAnswer(long req_msg_id)
=> CallBareAsync<RpcDropAnswer>(writer =>
public static Task<RpcDropAnswer> RpcDropAnswer(this Client client, long req_msg_id)
=> client.CallBareAsync<RpcDropAnswer>(writer =>
{
writer.Write(0x58E4A740);
writer.Write(req_msg_id);
@ -307,8 +306,8 @@ namespace WTelegram // ---functions---
});
//get_future_salts#b921bd04 num:int = FutureSalts
public Task<FutureSalts> GetFutureSalts(int num)
=> CallAsync<FutureSalts>(writer =>
public static Task<FutureSalts> GetFutureSalts(this Client client, int num)
=> client.CallAsync<FutureSalts>(writer =>
{
writer.Write(0xB921BD04);
writer.Write(num);
@ -316,8 +315,8 @@ namespace WTelegram // ---functions---
});
//ping#7abe77ec ping_id:long = Pong
public Task<Pong> Ping(long ping_id)
=> CallAsync<Pong>(writer =>
public static Task<Pong> Ping(this Client client, long ping_id)
=> client.CallAsync<Pong>(writer =>
{
writer.Write(0x7ABE77EC);
writer.Write(ping_id);
@ -325,8 +324,8 @@ namespace WTelegram // ---functions---
});
//ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong
public Task<Pong> PingDelayDisconnect(long ping_id, int disconnect_delay)
=> CallAsync<Pong>(writer =>
public static Task<Pong> PingDelayDisconnect(this Client client, long ping_id, int disconnect_delay)
=> client.CallAsync<Pong>(writer =>
{
writer.Write(0xF3427B8C);
writer.Write(ping_id);
@ -335,8 +334,8 @@ namespace WTelegram // ---functions---
});
//destroy_session#e7512126 session_id:long = DestroySessionRes
public Task<DestroySessionRes> DestroySession(long session_id)
=> CallBareAsync<DestroySessionRes>(writer =>
public static Task<DestroySessionRes> DestroySession(this Client client, long session_id)
=> client.CallBareAsync<DestroySessionRes>(writer =>
{
writer.Write(0xE7512126);
writer.Write(session_id);

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,11 @@
// This file is (mainly) generated automatically using the Generator class
// This file is generated automatically using the Generator class
using System;
namespace TL
{
using BinaryWriter = System.IO.BinaryWriter;
using Client = WTelegram.Client;
namespace Layer8
{
///<summary>See <a href="https://core.telegram.org/type/DecryptedMessage"/></summary>

View file

@ -1,16 +1,16 @@
// This file is (mainly) generated automatically using the Generator class
// This file is generated automatically using the Generator class
using System;
using System.Collections.Generic;
namespace TL
{
static partial class Schema
static class Layer
{
public const int Layer = 133; // fetched 17/09/2021 01:46:27
public const uint VectorCtor = 0x1CB5C415;
public const uint NullCtor = 0x56730BCC;
public const uint RpcResult = 0xF35C6D01;
public const uint MsgContainer = 0x73F1F8DC;
public const int Version = 133; // fetched 17/09/2021 02:47:02
internal const uint VectorCtor = 0x1CB5C415;
internal const uint NullCtor = 0x56730BCC;
internal const uint RpcResultCtor = 0xF35C6D01;
internal const uint MsgContainerCtor = 0x73F1F8DC;
internal readonly static Dictionary<uint, Type> Table = new()
{

View file

@ -11,7 +11,7 @@ namespace TL
public interface ITLObject { }
public delegate string ITLFunction(BinaryWriter writer);
public static partial class Schema
public static class Serialization
{
internal static byte[] Serialize(this ITLObject msg)
{
@ -30,7 +30,7 @@ namespace TL
internal static void WriteTLObject(this BinaryWriter writer, ITLObject obj)
{
if (obj == null) { writer.Write(NullCtor); return; }
if (obj == null) { writer.Write(Layer.NullCtor); return; }
var type = obj.GetType();
var ctorNb = type.GetCustomAttribute<TLDefAttribute>().CtorNb;
writer.Write(ctorNb);
@ -52,8 +52,8 @@ namespace TL
internal static ITLObject ReadTLObject(this BinaryReader reader, uint ctorNb = 0)
{
if (ctorNb == 0) ctorNb = reader.ReadUInt32();
if (ctorNb == NullCtor) return null;
if (!Table.TryGetValue(ctorNb, out var type))
if (ctorNb == Layer.NullCtor) return null;
if (!Layer.Table.TryGetValue(ctorNb, out var type))
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
var obj = Activator.CreateInstance(type);
var fields = type.GetFields().GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
@ -144,7 +144,7 @@ namespace TL
internal static void WriteTLVector(this BinaryWriter writer, Array array)
{
writer.Write(VectorCtor);
writer.Write(Layer.VectorCtor);
if (array == null) { writer.Write(0); return; }
int count = array.Length;
writer.Write(count);
@ -155,7 +155,7 @@ namespace TL
internal static Array ReadTLVector(this BinaryReader reader, Type type)
{
var ctorNb = reader.ReadUInt32();
if (ctorNb != VectorCtor) throw new ApplicationException($"Cannot deserialize {type.Name} with ctor #{ctorNb:x}");
if (ctorNb != Layer.VectorCtor) throw new ApplicationException($"Cannot deserialize {type.Name} with ctor #{ctorNb:x}");
var elementType = type.GetElementType();
int count = reader.ReadInt32();
Array array = (Array)Activator.CreateInstance(type, count);
@ -215,9 +215,9 @@ namespace TL
internal static void WriteTLNull(this BinaryWriter writer, Type type)
{
if (!type.IsArray)
writer.Write(NullCtor);
writer.Write(Layer.NullCtor);
else if (type != typeof(byte[]))
writer.Write(VectorCtor);
writer.Write(Layer.VectorCtor);
writer.Write(0); // null arrays are serialized as empty
}