From 78d7e250f35be28faf3fe1b7318c92fb0078525e Mon Sep 17 00:00:00 2001 From: Wizou <11647984+wiz0u@users.noreply.github.com> Date: Sun, 27 Feb 2022 22:06:13 +0100 Subject: [PATCH] added Messages_GetAllDialogs. UserOrChat(null) returns null --- EXAMPLES.md | 25 ++++------ Examples/Program_CollectAccessHash.cs | 4 +- Examples/Program_ListenUpdates.cs | 14 ++---- FAQ.md | 4 +- src/Client.cs | 33 +++++++++++++- src/TL.Schema.cs | 66 +++++++++++++-------------- 6 files changed, 81 insertions(+), 65 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index ffeab06..3b5c93d 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -117,7 +117,7 @@ long chatId = long.Parse(Console.ReadLine()); await client.SendMessageAsync(chats.chats[chatId], "Hello, World"); ``` Notes: -- This list does not include discussions with other users. For this, you need to use [Messages_GetDialogs](#list-dialogs). +- This list does not include discussions with other users. For this, you need to use [Messages_GetAllDialogs](#list-dialogs). - The list returned by Messages_GetAllChats contains the `access_hash` for those chats. Read [FAQ #4](FAQ.MD#access-hash) about this. - If a small private chat group has been migrated to a supergroup, you may find both the old `Chat` and a `Channel` with different IDs in the `chats.chats` result, but the old `Chat` will be marked with flag [deactivated] and should not be used anymore. See [Terminology in ReadMe](README.md#terminology). @@ -168,23 +168,16 @@ await client.SendAlbumAsync(InputPeer.Self, inputMedias, "My first album"); ### List all dialogs (chats/groups/channels/user chat) the user is in ```csharp -var dialogs = await client.Messages_GetDialogs(); -while (dialogs.Dialogs.Length != 0) -{ - foreach (var dialog in dialogs.Dialogs) - switch (dialogs.UserOrChat(dialog)) - { - case User user when user.IsActive: Console.WriteLine("User " + user); break; - case ChatBase chat when chat.IsActive: Console.WriteLine(chat); break; - } - 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(); - dialogs = await client.Messages_GetDialogs(lastMsg?.Date ?? default, lastDialog.TopMessage, offsetPeer); -} +var dialogs = await client.Messages_GetAllDialogs(); +foreach (var dialog in dialogs.dialogs) + switch (dialogs.UserOrChat(dialog)) + { + case User user when user.IsActive: Console.WriteLine("User " + user); break; + case ChatBase chat when chat.IsActive: Console.WriteLine(chat); break; + } ``` -*Note: the lists returned by Messages_GetDialogs contains the `access_hash` for those chats and users.* +*Note: the lists returned by Messages_GetAllDialogs contains the `access_hash` for those chats and users.* See also the `Main` method in [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs). diff --git a/Examples/Program_CollectAccessHash.cs b/Examples/Program_CollectAccessHash.cs index 055e6b6..6276814 100644 --- a/Examples/Program_CollectAccessHash.cs +++ b/Examples/Program_CollectAccessHash.cs @@ -44,8 +44,8 @@ namespace WTelegramClientTest { // Zero means the access hash for Durov's Channel was not collected yet. // So we need to obtain it through Client API calls whose results contains the access_hash field, such as: - // - Messages_GetAllChats (see Program_GetAllChats.cs for an example on how to use it) - // - Messages_GetDialogs (see Program_ListenUpdates.cs for an example on how to use it) + // - Messages_GetAllChats (see Program_GetAllChats.cs for an example on how to use it) + // - Messages_GetAllDialogs (see Program_ListenUpdates.cs for an example on how to use it) // - Contacts_ResolveUsername (see below for an example on how to use it) // and many more API methods... // The access_hash fields can be found inside instance of User, Channel, Photo, Document, etc.. diff --git a/Examples/Program_ListenUpdates.cs b/Examples/Program_ListenUpdates.cs index c5bf8a7..a0280b6 100644 --- a/Examples/Program_ListenUpdates.cs +++ b/Examples/Program_ListenUpdates.cs @@ -25,16 +25,8 @@ namespace WTelegramClientTest // Note that on login Telegram may sends a bunch of updates/messages that happened in the past and were not acknowledged Console.WriteLine($"We are logged-in as {My.username ?? My.first_name + " " + My.last_name} (id {My.id})"); // We collect all infos about the users/chats so that updates can be printed with their names - var dialogsBase = await Client.Messages_GetDialogs(); // dialogs = groups/channels/users - if (dialogsBase is Messages_Dialogs dialogs) - while (dialogs.dialogs.Length != 0) - { - 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(); - dialogs = (Messages_Dialogs)await Client.Messages_GetDialogs(lastMsg?.Date ?? default, lastDialog.TopMessage, offsetPeer); - } + var dialogs = await Client.Messages_GetAllDialogs(); // dialogs = groups/channels/users + dialogs.CollectUsersChats(_users, _chats); Console.ReadKey(); } } @@ -64,7 +56,7 @@ namespace WTelegramClientTest case UpdateUserStatus uus: Console.WriteLine($"{User(uus.user_id)} is now {uus.status.GetType().Name[10..]}"); break; case UpdateUserName uun: Console.WriteLine($"{User(uun.user_id)} has changed profile name: @{uun.username} {uun.first_name} {uun.last_name}"); break; case UpdateUserPhoto uup: Console.WriteLine($"{User(uup.user_id)} has changed profile photo"); break; - default: Console.WriteLine(update.GetType().Name); break; + default: Console.WriteLine(update.GetType().Name); break; // there are much more update types than the above cases } } diff --git a/FAQ.md b/FAQ.md index 89c084b..e357937 100644 --- a/FAQ.md +++ b/FAQ.md @@ -55,7 +55,7 @@ However most common chat groups are not `Chat` but a `Channel` supergroup (witho Some TL methods only applies to private `Chat`, some only applies to `Channel` and some to both. The `access_hash` must usually be provided within the `Input...` structure you pass in argument to an API method (`InputPeer`, `InputChannel`, `InputUser`, etc...). -You obtain the `access_hash` through **description structures** like `Channel`, `User`, `Photo`, `Document` that you receive through updates or when you query them through API methods like `Messages_GetAllChats`, `Messages_GetDialogs`, `Contacts_ResolveUsername`, etc... +You obtain the `access_hash` through **description structures** like `Channel`, `User`, `Photo`, `Document` that you receive through updates or when you query them through API methods like `Messages_GetAllChats`, `Messages_GetAllDialogs`, `Contacts_ResolveUsername`, etc... *(if you have a `Peer` object, you can convert it to a `User`/`Channel`/`Chat` via the `UserOrChat` helper from the root class that contained the peer)* Once you obtained the description structure, there are 3 methods for building your `Input...` structure: @@ -157,7 +157,7 @@ API method [Messages_GetAllChats](https://corefork.telegram.org/method/messages. Telegram Client API don't use these kind of IDs for chats. Remove the -100 prefix and try again with the rest (1234567890). - You're trying to use a user ID instead of a chat ID. Private messages with a user are not called "chats". See [Terminology in ReadMe](README.md#terminology). -To obtain the list of users (as well as chats and channels) the logged-in user is currenly engaged in a discussion with, you should [use the API method Messages_GetDialogs](EXAMPLES.md#list-dialogs) +To obtain the list of users (as well as chats and channels) the logged-in user is currenly engaged in a discussion with, you should [use the API method Messages_GetAllDialogs](EXAMPLES.md#list-dialogs) - the `chats.chats` dictionary is empty. This is the case if you are logged-in as a brand new user account (that hasn't join any chat groups/channels) or if you are connected to a Test DC (a Telegram datacenter server for tests) instead of Production DC diff --git a/src/Client.cs b/src/Client.cs index 4fba0b5..2749097 100644 --- a/src/Client.cs +++ b/src/Client.cs @@ -1532,7 +1532,7 @@ namespace WTelegram _parallelTransfers.Release(); } if (fileBase is not Upload_File fileData) - throw new ApplicationException("Upload_GetFile returned unsupported " + fileBase.GetType().Name); + throw new ApplicationException("Upload_GetFile returned unsupported " + fileBase?.GetType().Name); if (fileData.bytes.Length != FilePartSize) abort = true; if (fileData.bytes.Length != 0) { @@ -1623,6 +1623,37 @@ namespace WTelegram return true; } + /// Returns the current user dialog list. Possible codes: 400 (details) + /// Peer folder ID, for more info click here + /// See + public async Task Messages_GetAllDialogs(int? folder_id = null) + { + var dialogs = await this.Messages_GetDialogs(folder_id: folder_id); + switch (dialogs) + { + case Messages_DialogsSlice mds: + var dialogList = new List(); + var messageList = new List(); + while (dialogs.Dialogs.Length != 0) + { + dialogList.AddRange(dialogs.Dialogs); + messageList.AddRange(dialogs.Messages); + 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(); + dialogs = await this.Messages_GetDialogs(lastMsg?.Date ?? default, lastDialog.TopMessage, offsetPeer, folder_id: folder_id); + if (dialogs is not Messages_Dialogs md) break; + foreach (var (key, value) in md.chats) mds.chats[key] = value; + foreach (var (key, value) in md.users) mds.users[key] = value; + } + mds.dialogs = dialogList.ToArray(); + mds.messages = messageList.ToArray(); + return mds; + case Messages_Dialogs md: return md; + default: throw new ApplicationException("Messages_GetDialogs returned unexpected " + dialogs?.GetType().Name); + } + } + /// Helper method that tries to fetch all participants from a Channel (beyond Telegram server-side limitations) /// The channel to query /// Also fetch the kicked/banned members? diff --git a/src/TL.Schema.cs b/src/TL.Schema.cs index d551346..e9c3b96 100644 --- a/src/TL.Schema.cs +++ b/src/TL.Schema.cs @@ -2723,7 +2723,7 @@ namespace TL /// List of users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Incomplete list of blocked users. See [TLDef(0xE1664194)] @@ -2761,7 +2761,7 @@ namespace TL /// List of last messages from each chat public override MessageBase[] Messages => messages; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Incomplete list of dialogs with messages and auxiliary data. See [TLDef(0x71E094F3)] @@ -2805,7 +2805,7 @@ namespace TL /// List of messages public override MessageBase[] Messages => messages; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Incomplete list of messages and auxiliary data. See [TLDef(0x3A54685E)] @@ -2860,7 +2860,7 @@ namespace TL /// Found messages public override MessageBase[] Messages => messages; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// No new messages matching the query were found See [TLDef(0x74535F21)] @@ -2900,7 +2900,7 @@ namespace TL /// List of users mentioned above public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Affected part of communication history with the user or in a chat. See @@ -4168,7 +4168,7 @@ namespace TL /// List of updates public override Update[] OtherUpdates => other_updates; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Incomplete list of occurred events. See [TLDef(0xA8FB1981)] @@ -4194,7 +4194,7 @@ namespace TL /// List of updates public override Update[] OtherUpdates => other_updates; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// The difference is too long, and the specified state must be used to refetch updates. See [TLDef(0x4AFE8F6D)] @@ -4374,7 +4374,7 @@ namespace TL /// Current date public override DateTime Date => date; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Full constructor of updates See [TLDef(0x74AE4240)] @@ -4394,7 +4394,7 @@ namespace TL /// Current date public override DateTime Date => date; /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Shortened constructor containing info on one outgoing message to a contact (the destination chat has to be extracted from the method call that returned this object). See [TLDef(0x9015E101)] @@ -5178,7 +5178,7 @@ namespace TL /// List of users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Privacy key See @@ -5320,7 +5320,7 @@ namespace TL /// Users to which the rules apply public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Time to live in days of the current account See @@ -6334,7 +6334,7 @@ namespace TL /// Users public Dictionary users; /// returns a or for the result - public IPeerInfo UserOrChat => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat => peer?.UserOrChat(users, chats); } /// Indicates a range of chat messages See @@ -6399,7 +6399,7 @@ namespace TL has_timeout = 0x2, } /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// The new updates See [TLDef(0x2064674E)] @@ -6428,7 +6428,7 @@ namespace TL has_timeout = 0x2, } /// returns a or for the given Peer - public override IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public override IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Filter for getting only certain types of channel messages See @@ -6627,7 +6627,7 @@ namespace TL /// Users mentioned in participant info public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Represents a channel participant See @@ -6641,7 +6641,7 @@ namespace TL /// Users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Info about the latest telegram Terms Of Service See @@ -7457,7 +7457,7 @@ namespace TL /// Current update state of dialog public Updates_State state; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Top peer See @@ -7517,7 +7517,7 @@ namespace TL /// Users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Top peers disabled See [TLDef(0xB52C939D)] @@ -9434,7 +9434,7 @@ namespace TL /// Users mentioned in events public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Filter only certain admin log events See @@ -9555,7 +9555,7 @@ namespace TL /// Users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// A single media in an album or grouped media sent with messages.sendMultiMedia. See @@ -11146,7 +11146,7 @@ namespace TL /// Users mentioned in the chat list public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Basic theme settings See @@ -11547,7 +11547,7 @@ namespace TL has_psa_message = 0x4, } /// returns a or for the result - public IPeerInfo UserOrChat => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat => peer?.UserOrChat(users, chats); } /// Animated profile picture in MPEG4 format See @@ -11758,7 +11758,7 @@ namespace TL /// Users mentioned in constructor public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Information about a message thread See @@ -11792,7 +11792,7 @@ namespace TL has_read_outbox_max_id = 0x4, } /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Message replies and thread information See @@ -12037,7 +12037,7 @@ namespace TL /// Users mentioned in the participants vector public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Info about the participants of a group call or livestream See @@ -12057,7 +12057,7 @@ namespace TL /// Version info public int version; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Type of the chat from which the inline query was sent. See @@ -12244,7 +12244,7 @@ namespace TL /// Users mentioned in the peers vector public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// An invite to a group call or livestream See @@ -12396,7 +12396,7 @@ namespace TL /// Users mentioned in the sponsored messages public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// See @@ -12435,7 +12435,7 @@ namespace TL has_offset_id_offset = 0x2, } /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Information about a message in a specific position Derived classes: See @@ -12468,7 +12468,7 @@ namespace TL /// Mentioned users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Full user information See @@ -12482,7 +12482,7 @@ namespace TL /// Mentioned users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Peer settings See @@ -12496,7 +12496,7 @@ namespace TL /// Mentioned users public Dictionary users; /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Authentication token to be used on subsequent authorizations See @@ -12578,7 +12578,7 @@ namespace TL has_next_offset = 0x1, } /// returns a or for the given Peer - public IPeerInfo UserOrChat(Peer peer) => peer.UserOrChat(users, chats); + public IPeerInfo UserOrChat(Peer peer) => peer?.UserOrChat(users, chats); } /// Animations associated with a message reaction See