diff --git a/src/Client.Helpers.cs b/src/Client.Helpers.cs index ce1580d..430bbde 100644 --- a/src/Client.Helpers.cs +++ b/src/Client.Helpers.cs @@ -15,49 +15,6 @@ namespace WTelegram { partial class Client { - #region Collect Access Hash system - #pragma warning disable CS0618 // Type or member is obsolete - /// Enable the collection of id/access_hash pairs (deprecated) - [Obsolete("This system will be removed in a future version. You should use CollectUsersChats helper on API results or updates instead. See https://wiz0u.github.io/WTelegramClient/EXAMPLES#collect-users-chats")] - public bool CollectAccessHash { get; set; } - public IEnumerable> AllAccessHashesFor() where T : IObject => _accessHashes.GetValueOrDefault(typeof(T)); - private readonly Dictionary> _accessHashes = new(); - private static readonly FieldInfo userFlagsField = typeof(User).GetField("flags"); - private static readonly FieldInfo channelFlagsField = typeof(Channel).GetField("flags"); - - /// Retrieve the access_hash associated with this id (for a TL class) if it was collected - /// This requires to be set to first. - /// See Examples/Program_CollectAccessHash.cs for how to use this - /// a TL object class. For example User, Channel or Photo - public long GetAccessHashFor(long id) where T : IObject - { - if (!CollectAccessHash) Helpers.Log(4, "GetAccessHashFor doesn't do what you think. See https://github.com/wiz0u/WTelegramClient/blob/master/FAQ.md#access-hash"); - lock (_accessHashes) - return _accessHashes.GetOrCreate(typeof(T)).TryGetValue(id, out var access_hash) ? access_hash : 0; - } - public void SetAccessHashFor(long id, long access_hash) where T : IObject - { - lock (_accessHashes) - _accessHashes.GetOrCreate(typeof(T))[id] = access_hash; - } - internal void CollectField(FieldInfo fieldInfo, object obj, object access_hash) - { - if (fieldInfo.Name != "access_hash") return; - if (access_hash is not long accessHash) return; - var type = fieldInfo.ReflectedType; - if ((type == typeof(User) && ((User.Flags)userFlagsField.GetValue(obj)).HasFlag(User.Flags.min)) || - (type == typeof(Channel) && ((Channel.Flags)channelFlagsField.GetValue(obj)).HasFlag(Channel.Flags.min))) - return; // access_hash from Min constructors are mostly useless. see https://core.telegram.org/api/min - if (type.GetField("id") is not FieldInfo idField) return; - if (idField.GetValue(obj) is not long id) - if (idField.GetValue(obj) is not int idInt) return; - else id = idInt; - lock (_accessHashes) - _accessHashes.GetOrCreate(type)[id] = accessHash; - } - #pragma warning restore CS0618 // Type or member is obsolete - #endregion - #region Client TL Helpers /// Used to indicate progression of file download/upload /// transmitted bytes diff --git a/src/Client.cs b/src/Client.cs index a9db6c5..2b24c02 100644 --- a/src/Client.cs +++ b/src/Client.cs @@ -384,7 +384,7 @@ namespace WTelegram throw new ApplicationException($"Received a packet encrypted with unexpected key {authKeyId:X}"); if (authKeyId == 0) // Unencrypted message { - using var reader = new TL.BinaryReader(new MemoryStream(data, 8, dataLen - 8), this); + using var reader = new BinaryReader(new MemoryStream(data, 8, dataLen - 8)); long msgId = _lastRecvMsgId = reader.ReadInt64(); if ((msgId & 1) == 0) throw new ApplicationException($"Invalid server msgId {msgId}"); int length = reader.ReadInt32(); @@ -407,7 +407,7 @@ namespace WTelegram if (!data.AsSpan(8, 16).SequenceEqual(_sha256Recv.Hash.AsSpan(8, 16))) throw new ApplicationException("Mismatch between MsgKey & decrypted SHA256"); _sha256Recv.Initialize(); - using var reader = new TL.BinaryReader(new MemoryStream(decrypted_data), this); + using var reader = new BinaryReader(new MemoryStream(decrypted_data)); var serverSalt = reader.ReadInt64(); // int64 salt var sessionId = reader.ReadInt64(); // int64 session_id var msgId = reader.ReadInt64(); // int64 message_id @@ -470,7 +470,7 @@ namespace WTelegram }; } - internal MsgContainer ReadMsgContainer(TL.BinaryReader reader) + internal MsgContainer ReadMsgContainer(BinaryReader reader) { int count = reader.ReadInt32(); var array = new _Message[count]; @@ -502,7 +502,7 @@ namespace WTelegram return new MsgContainer { messages = array }; } - private RpcResult ReadRpcResult(TL.BinaryReader reader) + private RpcResult ReadRpcResult(BinaryReader reader) { long msgId = reader.ReadInt64(); var rpc = PullPendingRequest(msgId); @@ -519,7 +519,7 @@ namespace WTelegram if (peek == Layer.RpcErrorCtor) result = reader.ReadTLObject(Layer.RpcErrorCtor); else if (peek == Layer.GZipedCtor) - using (var gzipReader = new TL.BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress), reader.Client)) + using (var gzipReader = new BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress))) result = gzipReader.ReadTLValue(rpc.type); else { diff --git a/src/Encryption.cs b/src/Encryption.cs index 03b72c0..01f8cc9 100644 --- a/src/Encryption.cs +++ b/src/Encryption.cs @@ -97,7 +97,7 @@ namespace WTelegram var (tmp_aes_key, tmp_aes_iv) = ConstructTmpAESKeyIV(resPQ.server_nonce, pqInnerData.new_nonce); var answer = AES_IGE_EncryptDecrypt(serverDHparamsOk.encrypted_answer, tmp_aes_key, tmp_aes_iv, false); - using var answerReader = new TL.BinaryReader(new MemoryStream(answer), client); + using var answerReader = new BinaryReader(new MemoryStream(answer)); var answerHash = answerReader.ReadBytes(20); var answerObj = answerReader.ReadTLObject(); if (answerObj is not ServerDHInnerData serverDHinnerData) throw new ApplicationException("not server_DH_inner_data"); diff --git a/src/SecretChats.cs b/src/SecretChats.cs index b857422..53bdec0 100644 --- a/src/SecretChats.cs +++ b/src/SecretChats.cs @@ -94,7 +94,7 @@ namespace WTelegram } public void Load(Stream input) { - using var reader = new TL.BinaryReader(input, null, true); + using var reader = new BinaryReader(input, Encoding.UTF8, true); if (reader.ReadInt32() != 0) throw new ApplicationException("Unrecognized Secrets format"); dh = (Messages_DhConfig)reader.ReadTLObject(); if (dh?.p != null) dh_prime = BigEndianInteger(dh.p); @@ -359,7 +359,7 @@ namespace WTelegram } if (!success) throw new ApplicationException("Could not decrypt message"); if (length % 4 != 0) throw new ApplicationException($"Invalid message_data_length: {length}"); - using var reader = new TL.BinaryReader(new MemoryStream(decrypted_data, 4, length), null); + using var reader = new BinaryReader(new MemoryStream(decrypted_data, 4, length)); return reader.ReadTLObject(); } diff --git a/src/TL.Extensions.cs b/src/TL.Extensions.cs index 9139778..c9205f8 100644 --- a/src/TL.Extensions.cs +++ b/src/TL.Extensions.cs @@ -37,21 +37,21 @@ namespace TL public static void CollectUsersChats(this IPeerResolver structure, Dictionary users, Dictionary chats) => structure.UserOrChat(new CollectorPeer { _users = users, _chats = chats }); - public static Task Messages_GetChats(this WTelegram.Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats"); - public static Task Channels_GetChannels(this WTelegram.Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats"); - public static Task Users_GetUsers(this WTelegram.Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllDialogs"); - public static Task Messages_GetMessages(this WTelegram.Client _) => throw new ApplicationException("If you want to get the messages from a chat, use Messages_GetHistory"); + public static Task Messages_GetChats(this Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats"); + public static Task Channels_GetChannels(this Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats"); + public static Task Users_GetUsers(this Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllDialogs"); + public static Task Messages_GetMessages(this Client _) => throw new ApplicationException("If you want to get the messages from a chat, use Messages_GetHistory"); } public static class Markdown { /// Converts a Markdown text into the (plain text + entities) format used by Telegram messages - /// Client, used for getting access_hash for tg://user?id= URLs + /// not used anymore, you can pass null /// [in] The Markdown text
[out] The same (plain) text, stripped of all Markdown notation /// Generate premium entities if any /// Dictionary used for tg://user?id= notation - /// The array of formatting entities that you can pass (along with the plain text) to SendMessageAsync or SendMediaAsync - public static MessageEntity[] MarkdownToEntities(this WTelegram.Client client, ref string text, bool premium = false, Dictionary users = null) + /// The array of formatting entities that you can pass (along with the plain text) to SendMessageAsync or SendMediaAsync + public static MessageEntity[] MarkdownToEntities(this Client _, ref string text, bool premium = false, Dictionary users = null) { var entities = new List(); var sb = new StringBuilder(text); @@ -121,7 +121,7 @@ namespace TL else if (c == ')') break; } textUrl.url = sb.ToString(offset + 2, offset2 - offset - 3); - if (textUrl.url.StartsWith("tg://user?id=") && long.TryParse(textUrl.url[13..], out var id) && (users?.GetValueOrDefault(id)?.access_hash ?? client.GetAccessHashFor(id)) is long hash) + if (textUrl.url.StartsWith("tg://user?id=") && long.TryParse(textUrl.url[13..], out var id) && users?.GetValueOrDefault(id)?.access_hash is long hash) entities[lastIndex] = new InputMessageEntityMentionName { offset = textUrl.offset, length = textUrl.length, user_id = new InputUser(id, hash) }; else if ((textUrl.url.StartsWith("tg://emoji?id=") || textUrl.url.StartsWith("emoji?id=")) && long.TryParse(textUrl.url[(textUrl.url.IndexOf('=') + 1)..], out id)) if (premium) entities[lastIndex] = new MessageEntityCustomEmoji { offset = textUrl.offset, length = textUrl.length, document_id = id }; @@ -154,7 +154,7 @@ namespace TL /// The array of formatting entities, typically obtained from /// Convert premium entities (might lead to non-standard markdown) /// The message text with MarkdownV2 formattings - public static string EntitiesToMarkdown(this WTelegram.Client client, string message, MessageEntity[] entities, bool premium = false) + public static string EntitiesToMarkdown(this Client client, string message, MessageEntity[] entities, bool premium = false) { if (entities == null || entities.Length == 0) return Escape(message); var closings = new List<(int offset, string md)>(); @@ -246,12 +246,12 @@ namespace TL public static class HtmlText { /// Converts an HTML-formatted text into the (plain text + entities) format used by Telegram messages - /// Client, used for getting access_hash for tg://user?id= URLs + /// not used anymore, you can pass null /// [in] The HTML-formatted text
[out] The same (plain) text, stripped of all HTML tags /// Generate premium entities if any /// Dictionary used for tg://user?id= notation - /// The array of formatting entities that you can pass (along with the plain text) to SendMessageAsync or SendMediaAsync - public static MessageEntity[] HtmlToEntities(this WTelegram.Client client, ref string text, bool premium = false, Dictionary users = null) + /// The array of formatting entities that you can pass (along with the plain text) to SendMessageAsync or SendMediaAsync + public static MessageEntity[] HtmlToEntities(this Client _, ref string text, bool premium = false, Dictionary users = null) { var entities = new List(); var sb = new StringBuilder(text); @@ -306,7 +306,7 @@ namespace TL else if (tag.StartsWith("a href=\"") && tag.EndsWith("\"")) { tag = tag[8..^1]; - if (tag.StartsWith("tg://user?id=") && long.TryParse(tag[13..], out var user_id) && (users?.GetValueOrDefault(user_id)?.access_hash ?? client.GetAccessHashFor(user_id)) is long hash) + if (tag.StartsWith("tg://user?id=") && long.TryParse(tag[13..], out var user_id) && users?.GetValueOrDefault(user_id)?.access_hash is long hash) entities.Add(new InputMessageEntityMentionName { offset = offset, length = -1, user_id = new InputUser(user_id, hash) }); else entities.Add(new MessageEntityTextUrl { offset = offset, length = -1, url = tag }); @@ -342,7 +342,7 @@ namespace TL /// The array of formatting entities, typically obtained from /// Convert premium entities /// The message text with HTML formatting tags - public static string EntitiesToHtml(this WTelegram.Client client, string message, MessageEntity[] entities, bool premium = false) + public static string EntitiesToHtml(this Client client, string message, MessageEntity[] entities, bool premium = false) { if (entities == null || entities.Length == 0) return Escape(message); var closings = new List<(int offset, string tag)>(); diff --git a/src/TL.cs b/src/TL.cs index b5544b4..4ec4923 100644 --- a/src/TL.cs +++ b/src/TL.cs @@ -42,12 +42,6 @@ namespace TL public Exception Exception; } - internal class BinaryReader : System.IO.BinaryReader - { - public readonly WTelegram.Client Client; - public BinaryReader(Stream stream, WTelegram.Client client, bool leaveOpen = false) : base(stream, Encoding.UTF8, leaveOpen) => Client = client; - } - internal static class Serialization { internal static void WriteTLObject(this BinaryWriter writer, T obj) where T : IObject @@ -76,7 +70,7 @@ namespace TL { if (ctorNb == 0) ctorNb = reader.ReadUInt32(); if (ctorNb == Layer.GZipedCtor) - using (var gzipReader = new BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress), reader.Client)) + using (var gzipReader = new BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress))) return ReadTLObject(gzipReader); if (!Layer.Table.TryGetValue(ctorNb, out var type)) throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}"); @@ -95,9 +89,6 @@ namespace TL if (field.FieldType.IsEnum) if (field.Name == "flags") flags = (uint)value; else if (field.Name == "flags2") flags |= (ulong)(uint)value << 32; -#pragma warning disable CS0618 // Type or member is obsolete - if (reader.Client?.CollectAccessHash == true) reader.Client.CollectField(field, obj, value); -#pragma warning restore CS0618 // Type or member is obsolete } return (IObject)obj; }