From 4e07c03a0b1cc8b964c9d698c573c1a878287db7 Mon Sep 17 00:00:00 2001 From: Wizou <11647984+wiz0u@users.noreply.github.com> Date: Mon, 14 Feb 2022 02:02:13 +0100 Subject: [PATCH] CollectUsersChats helper for your dictionaries (min-aware). CollectAccessHash won't collect 'min' access_hash. --- Examples/Program_ListenUpdates.cs | 6 ++---- FAQ.md | 2 ++ src/Client.cs | 5 +++++ src/TL.Helpers.cs | 32 +++++++++++++++++++++++++++++++ src/TL.cs | 2 +- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Examples/Program_ListenUpdates.cs b/Examples/Program_ListenUpdates.cs index 1a375c6..c5bf8a7 100644 --- a/Examples/Program_ListenUpdates.cs +++ b/Examples/Program_ListenUpdates.cs @@ -29,8 +29,7 @@ namespace WTelegramClientTest if (dialogsBase is Messages_Dialogs dialogs) while (dialogs.dialogs.Length != 0) { - foreach (var (id, user) in dialogs.users) _users[id] = user; - foreach (var (id, chat) in dialogs.chats) _chats[id] = chat; + dialogs.CollectUsersChats(_users, _chats); var lastDialog = dialogs.dialogs[^1]; var lastMsg = dialogs.messages.LastOrDefault(m => m.Peer.ID == lastDialog.Peer.ID && m.ID == lastDialog.TopMessage); var offsetPeer = dialogs.UserOrChat(lastDialog).ToInputPeer(); @@ -50,8 +49,7 @@ namespace WTelegramClientTest private static void Client_Update(IObject arg) { if (arg is not UpdatesBase updates) return; - foreach (var (id, user) in updates.Users) _users[id] = user; - foreach (var (id, chat) in updates.Chats) _chats[id] = chat; + updates.CollectUsersChats(_users, _chats); foreach (var update in updates.UpdateList) switch (update) { diff --git a/FAQ.md b/FAQ.md index 0e37109..8e4c775 100644 --- a/FAQ.md +++ b/FAQ.md @@ -61,6 +61,8 @@ So you can just pass that structure you already have, in place of the `Input...` * If you have enabled the [CollectAccessHash system](EXAMPLES.md#collect-access-hash) at the start of your session, it will have collected the `access_hash`. You can then retrieve it with `client.GetAccessHashFor(id)` +⚠️ *`access_hash` obtained from a User or Channel with flag `min` may not be used for most requests. See [Min constructors](https://core.telegram.org/api/min).* + #### 5. I need to test a feature that has been developed but not yet released in WTelegramClient nuget diff --git a/src/Client.cs b/src/Client.cs index e366e3e..7a7476a 100644 --- a/src/Client.cs +++ b/src/Client.cs @@ -1175,11 +1175,16 @@ namespace WTelegram lock (_accessHashes) _accessHashes.GetOrCreate(typeof(T))[id] = access_hash; } + static readonly FieldInfo userFlagsField = typeof(User).GetField("flags"); + static readonly FieldInfo channelFlagsField = typeof(Channel).GetField("flags"); 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; diff --git a/src/TL.Helpers.cs b/src/TL.Helpers.cs index 92ca799..7c8f464 100644 --- a/src/TL.Helpers.cs +++ b/src/TL.Helpers.cs @@ -518,6 +518,38 @@ namespace TL } } + public static class Helpers + { + private class CollectorPeer : Peer + { + public override long ID => 0; + internal Dictionary _users; + internal Dictionary _chats; + internal override IPeerInfo UserOrChat(Dictionary users, Dictionary chats) + { + lock (_users) + foreach (var user in users.Values) + if (user != null) + if (!user.flags.HasFlag(User.Flags.min) || !_users.TryGetValue(user.id, out var prevUser) || prevUser.flags.HasFlag(User.Flags.min)) + _users[user.id] = user; + lock (_chats) + foreach (var kvp in chats) + if (kvp.Value is not Channel channel) + _chats[kvp.Key] = kvp.Value; + else if (!channel.flags.HasFlag(Channel.Flags.min) || !_chats.TryGetValue(channel.id, out var prevChat) || prevChat is not Channel prevChannel || prevChannel.flags.HasFlag(Channel.Flags.min)) + _chats[kvp.Key] = channel; + return null; + } + } + + /// Accumulate users/chats found in this structure in your dictionaries, ignoring Min constructors when the full object is already stored + /// The structure having a users + /// + /// + public static void CollectUsersChats(this IPeerResolver structure, Dictionary users, Dictionary chats) + => structure.UserOrChat(new CollectorPeer { _users = users, _chats = chats }); + } + public static class Markdown { /// Converts a Markdown text into the (Entities + plain text) format used by Telegram messages diff --git a/src/TL.cs b/src/TL.cs index 8673811..1653543 100644 --- a/src/TL.cs +++ b/src/TL.cs @@ -13,7 +13,7 @@ namespace TL public interface IMethod : IObject { } public interface IPeerResolver { IPeerInfo UserOrChat(Peer peer); } - public static class Serialization + internal static class Serialization { internal static void WriteTLObject(this BinaryWriter writer, T obj) where T : IObject {