mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Added logger system
This commit is contained in:
parent
39b0a79f0f
commit
85a3ea997f
29
Client.cs
29
Client.cs
|
|
@ -74,7 +74,7 @@ namespace WTelegram
|
|||
{
|
||||
var endpoint = _session.DataCenter == null ? IPEndPoint.Parse(_config("server_address"))
|
||||
: new IPEndPoint(IPAddress.Parse(_session.DataCenter.ip_address), _session.DataCenter.port);
|
||||
Console.WriteLine($"Connecting to {endpoint}...");
|
||||
Helpers.Log(2, $"Connecting to {endpoint}...");
|
||||
_tcpClient = new TcpClient(endpoint.AddressFamily);
|
||||
await _tcpClient.ConnectAsync(endpoint.Address, endpoint.Port);
|
||||
_networkStream = _tcpClient.GetStream();
|
||||
|
|
@ -102,7 +102,7 @@ namespace WTelegram
|
|||
|
||||
private async Task MigrateDCAsync(int dcId)
|
||||
{
|
||||
Console.WriteLine($"Migrate to DC {dcId}...");
|
||||
Helpers.Log(2, $"Migrate to DC {dcId}...");
|
||||
//TODO: Export/Import client authorization?
|
||||
var prevFamily = _tcpClient.Client.RemoteEndPoint.AddressFamily;
|
||||
_tcpClient.Close();
|
||||
|
|
@ -137,7 +137,7 @@ namespace WTelegram
|
|||
|
||||
if (_session.AuthKeyID == 0) // send unencrypted message
|
||||
{
|
||||
Console.WriteLine($"Sending {msg.GetType().Name}...");
|
||||
Helpers.Log(1, $"Sending {msg.GetType().Name}...");
|
||||
writer.Write(0L); // int64 auth_key_id = 0 (Unencrypted)
|
||||
writer.Write(msgId); // int64 message_id
|
||||
writer.Write(0); // int32 message_data_length (to be patched)
|
||||
|
|
@ -146,7 +146,7 @@ namespace WTelegram
|
|||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Sending {msg.GetType().Name}... (seqno {seqno})");
|
||||
Helpers.Log(1, $"Sending {msg.GetType().Name}... (seqno {seqno})");
|
||||
//TODO: Implement MTProto 2.0
|
||||
using var clearStream = new MemoryStream(1024); //TODO: choose a useful capacity
|
||||
using var clearWriter = new BinaryWriter(clearStream, Encoding.UTF8);
|
||||
|
|
@ -183,7 +183,7 @@ namespace WTelegram
|
|||
_lastSentMsg = msg;
|
||||
}
|
||||
|
||||
internal async Task<object> RecvInternalAsync()
|
||||
internal async Task<ITLObject> RecvInternalAsync()
|
||||
{
|
||||
var data = await RecvFrameAsync();
|
||||
if (data.Length == 4 && data[3] == 0xFF)
|
||||
|
|
@ -204,7 +204,7 @@ namespace WTelegram
|
|||
var ctorNb = reader.ReadUInt32();
|
||||
if (!Schema.Mappings.TryGetValue(ctorNb, out var realType))
|
||||
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
|
||||
Console.WriteLine($"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} unencrypted");
|
||||
Helpers.Log(1, $"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} unencrypted");
|
||||
return Schema.DeserializeObject(reader, realType);
|
||||
}
|
||||
else if (authKeyId != _session.AuthKeyID)
|
||||
|
|
@ -234,7 +234,7 @@ namespace WTelegram
|
|||
var ctorNb = reader.ReadUInt32();
|
||||
if (!Schema.Mappings.TryGetValue(ctorNb, out var realType))
|
||||
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
|
||||
Console.WriteLine($"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} {(seqno == -1 ? "clearText" : "isContent")}={(seqno & 1) != 0}");
|
||||
Helpers.Log(1, $"Receiving {realType.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} {(seqno == -1 ? "clearText" : "isContent")}={(seqno & 1) != 0}");
|
||||
if (realType == typeof(RpcResult))
|
||||
return DeserializeRpcResult(reader); // hack necessary because some RPC return bare types like bool or int[]
|
||||
else
|
||||
|
|
@ -282,14 +282,14 @@ namespace WTelegram
|
|||
}
|
||||
}
|
||||
|
||||
private object DeserializeRpcResult(BinaryReader reader)
|
||||
private RpcResult DeserializeRpcResult(BinaryReader reader)
|
||||
{
|
||||
long reqMsgId = reader.ReadInt64();
|
||||
var rpcResult = new RpcResult { req_msg_id = reqMsgId };
|
||||
if (reqMsgId == _session.LastSentMsgId)
|
||||
rpcResult.result = Schema.DeserializeValue(reader, _lastRpcResultType);
|
||||
else
|
||||
rpcResult.result = Schema.Deserialize<object>(reader);
|
||||
rpcResult.result = Schema.Deserialize<ITLObject>(reader);
|
||||
return rpcResult;
|
||||
}
|
||||
|
||||
|
|
@ -343,15 +343,14 @@ namespace WTelegram
|
|||
await SendAsync(msgsAck, false);
|
||||
}
|
||||
|
||||
private async Task HandleMessageAsync(object obj)
|
||||
private async Task HandleMessageAsync(ITLObject obj)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case MsgContainer container:
|
||||
foreach (var msg in container.messages)
|
||||
{
|
||||
Console.Write($" → {msg.body?.GetType().Name}");
|
||||
Console.WriteLine($"{new string(' ', Math.Max(0, 60 - Console.CursorLeft))} timestamp={_session.MsgIdToStamp(msg.msg_id)} isResponse={(msg.msg_id & 2) != 0} {(msg.seqno == -1 ? "clearText" : "isContent")}={(msg.seqno & 1) != 0}");
|
||||
Helpers.Log(1, $" → {msg.body?.GetType().Name,-48} timestamp={_session.MsgIdToStamp(msg.msg_id)} isResponse={(msg.msg_id & 2) != 0} {(msg.seqno == -1 ? "clearText" : "isContent")}={(msg.seqno & 1) != 0}");
|
||||
if ((msg.seqno & 1) != 0) lock (_msgsToAck) _msgsToAck.Add(msg.msg_id);
|
||||
if (msg.body != null) await HandleMessageAsync(msg.body);
|
||||
}
|
||||
|
|
@ -362,14 +361,14 @@ namespace WTelegram
|
|||
await SendAsync(_lastSentMsg);
|
||||
break;
|
||||
case BadMsgNotification badMsgNotification:
|
||||
Console.WriteLine($"BadMsgNotification {badMsgNotification.error_code} for msg {badMsgNotification.bad_msg_seqno}");
|
||||
Helpers.Log(3, $"BadMsgNotification {badMsgNotification.error_code} for msg {badMsgNotification.bad_msg_seqno}");
|
||||
break;
|
||||
case RpcResult rpcResult:
|
||||
if (_session.MsgIdToStamp(rpcResult.req_msg_id) >= _session.SessionStart)
|
||||
throw new ApplicationException($"Got RpcResult({rpcResult.result.GetType().Name}) for unknown msgId {rpcResult.req_msg_id}");
|
||||
break; // silently ignore results for msg_id from previous sessions
|
||||
default:
|
||||
//_updateHandler?.Invoke(obj);
|
||||
_updateHandler?.Invoke(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -386,7 +385,7 @@ namespace WTelegram
|
|||
api_hash = _apiHash,
|
||||
settings = settings ?? new()
|
||||
});
|
||||
Console.WriteLine($"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
|
||||
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
|
||||
var verification_code = _config("verification_code");
|
||||
var authorization = await CallAsync(new Auth_SignIn
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace WTelegram
|
|||
if (resPQ.nonce != reqPQ.nonce) throw new ApplicationException("Nonce mismatch");
|
||||
var fingerprint = resPQ.server_public_key_fingerprints.FirstOrDefault(PublicKeys.ContainsKey);
|
||||
if (fingerprint == 0) throw new ApplicationException("Couldn't match any server_public_key_fingerprints");
|
||||
Console.WriteLine($"Selected public key with fingerprint {fingerprint:X}");
|
||||
Helpers.Log(2, $"Selected public key with fingerprint {fingerprint:X}");
|
||||
//3)
|
||||
long retry_id = 0;
|
||||
ulong pq = Helpers.FromBigEndian(resPQ.pq);
|
||||
|
|
@ -69,7 +69,7 @@ namespace WTelegram
|
|||
var g_a = new BigInteger(serverDHinnerData.g_a, true, true);
|
||||
var dh_prime = new BigInteger(serverDHinnerData.dh_prime, true, true);
|
||||
ValidityChecks(dh_prime, serverDHinnerData.g);
|
||||
Console.WriteLine($"Server time: {serverDHinnerData.server_time} UTC");
|
||||
Helpers.Log(1, $"Server time: {serverDHinnerData.server_time} UTC");
|
||||
session.ServerTicksOffset = (serverDHinnerData.server_time - localTime).Ticks;
|
||||
|
||||
//6)
|
||||
|
|
@ -210,7 +210,7 @@ namespace WTelegram
|
|||
var bareData = Schema.Serialize(publicKey).AsSpan(4); // bare serialization
|
||||
var fingerprint = BitConverter.ToInt64(SHA1.HashData(bareData), 12); // 64 lower-order bits of SHA1
|
||||
PublicKeys[fingerprint] = publicKey;
|
||||
Console.WriteLine($"Loaded a public key with fingerprint {fingerprint:X}");
|
||||
Helpers.Log(1, $"Loaded a public key with fingerprint {fingerprint:X}");
|
||||
}
|
||||
|
||||
private static void LoadDefaultPublicKey() // fingerprint C3B42B026CE86B21
|
||||
|
|
|
|||
11
Helpers.cs
11
Helpers.cs
|
|
@ -10,6 +10,17 @@ namespace WTelegram
|
|||
public static V GetOrCreate<K, V>(this Dictionary<K, V> dictionary, K key) where V : new()
|
||||
=> dictionary.TryGetValue(key, out V value) ? value : dictionary[key] = new V();
|
||||
|
||||
public static Action<int, string> Log { get; set; } = DefaultLogger;
|
||||
|
||||
private static readonly ConsoleColor[] LogLevelToColor = new[] { ConsoleColor.DarkGray, ConsoleColor.DarkCyan, ConsoleColor.Cyan,
|
||||
ConsoleColor.Yellow, ConsoleColor.Red, ConsoleColor.Magenta, ConsoleColor.DarkBlue };
|
||||
private static void DefaultLogger(int level, string message)
|
||||
{
|
||||
Console.ForegroundColor = LogLevelToColor[level];
|
||||
Console.WriteLine(message);
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
public static void LittleEndian(byte[] buffer, int offset, int value)
|
||||
{
|
||||
buffer[offset + 0] = (byte)value;
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ namespace WTelegram
|
|||
var json = File.ReadAllText(pathname);
|
||||
var session = JsonSerializer.Deserialize<Session>(json, Helpers.JsonOptions);
|
||||
session._pathname = pathname;
|
||||
Console.WriteLine("Loaded previous session");
|
||||
Helpers.Log(2, "Loaded previous session");
|
||||
return session;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Exception while reading session file: {ex.Message}");
|
||||
Helpers.Log(4, $"Exception while reading session file: {ex.Message}");
|
||||
}
|
||||
}
|
||||
var sessionId = new byte[8];
|
||||
|
|
|
|||
19
TL.cs
19
TL.cs
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using WTelegram;
|
||||
|
||||
namespace TL
|
||||
{
|
||||
|
|
@ -35,7 +36,7 @@ namespace TL
|
|||
return memStream.ToArray();
|
||||
}
|
||||
|
||||
internal static T Deserialize<T>(byte[] bytes)
|
||||
internal static T Deserialize<T>(byte[] bytes) where T : ITLObject
|
||||
{
|
||||
using var memStream = new MemoryStream(bytes);
|
||||
using var reader = new BinaryReader(memStream);
|
||||
|
|
@ -50,7 +51,7 @@ namespace TL
|
|||
SerializeObject(writer, msg);
|
||||
}
|
||||
|
||||
internal static T Deserialize<T>(BinaryReader reader)
|
||||
internal static T Deserialize<T>(BinaryReader reader) where T : ITLObject
|
||||
{
|
||||
var ctorNb = reader.ReadUInt32();
|
||||
if (!Mappings.TryGetValue(ctorNb, out var realType))
|
||||
|
|
@ -72,7 +73,7 @@ namespace TL
|
|||
}
|
||||
}
|
||||
|
||||
internal static object DeserializeObject(BinaryReader reader, Type type)
|
||||
internal static ITLObject DeserializeObject(BinaryReader reader, Type type)
|
||||
{
|
||||
var obj = Activator.CreateInstance(type);
|
||||
var fields = obj.GetType().GetFields().GroupBy(f => f.DeclaringType).Reverse().SelectMany(g => g);
|
||||
|
|
@ -85,7 +86,7 @@ namespace TL
|
|||
field.SetValue(obj, value);
|
||||
if (field.Name.Equals("Flags", StringComparison.OrdinalIgnoreCase)) flags = (int)value;
|
||||
}
|
||||
return type == typeof(GzipPacked) ? UnzipPacket((GzipPacked)obj) : obj;
|
||||
return type == typeof(GzipPacked) ? UnzipPacket((GzipPacked)obj) : (ITLObject)obj;
|
||||
}
|
||||
|
||||
internal static void SerializeValue(BinaryWriter writer, object value)
|
||||
|
|
@ -161,7 +162,7 @@ namespace TL
|
|||
else if (type.IsValueType)
|
||||
return DeserializeObject(reader, type);
|
||||
else
|
||||
return Deserialize<object>(reader);
|
||||
return Deserialize<ITLObject>(reader);
|
||||
default:
|
||||
ShouldntBeHere();
|
||||
return null;
|
||||
|
|
@ -239,18 +240,18 @@ namespace TL
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
Helpers.Log(4, ex.ToString());
|
||||
}
|
||||
reader.BaseStream.Position = pos + array[i].bytes;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private static object UnzipPacket(GzipPacked obj)
|
||||
private static ITLObject UnzipPacket(GzipPacked obj)
|
||||
{
|
||||
using var reader = new BinaryReader(new GZipStream(new MemoryStream(obj.packed_data), CompressionMode.Decompress));
|
||||
var result = DeserializeValue(reader, typeof(object));
|
||||
Console.WriteLine($" → {result.GetType().Name}");
|
||||
var result = Deserialize<ITLObject>(reader);
|
||||
Helpers.Log(1, $" → {result.GetType().Name}");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@
|
|||
<RootNamespace>WTelegram</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove=".gitattributes" />
|
||||
<None Remove=".gitignore" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Crc32.NET" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
Loading…
Reference in a new issue