From 5d0fd6452fe8a6aea72eb0142c0d7b0d07895e8b Mon Sep 17 00:00:00 2001 From: Wizou <11647984+wiz0u@users.noreply.github.com> Date: Fri, 17 Feb 2023 19:31:01 +0100 Subject: [PATCH] Added helpers AnalyzeInviteLink & GetMessageByLink --- src/Client.Helpers.cs | 98 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/Client.Helpers.cs b/src/Client.Helpers.cs index 430bbde..961934e 100644 --- a/src/Client.Helpers.cs +++ b/src/Client.Helpers.cs @@ -675,6 +675,104 @@ namespace WTelegram /// If a positive value is passed, only messages with identifiers less or equal than the given one will be marked read public async Task ReadHistory(InputPeer peer, int max_id = default) => peer is InputPeerChannel channel ? await this.Channels_ReadHistory(channel, max_id) : (await this.Messages_ReadHistory(peer, max_id)) != null; + + private static readonly char[] QueryOrFragment = new[] { '?', '#' }; + + /// Return information about a chat/channel based on Invite Link + /// Channel or Invite Link, like https://t.me/+InviteHash, https://t.me/joinchat/InviteHash or https://t.me/channelname + /// to also join the chat/channel + /// a Chat or Channel, possibly partial Channel information only (with flag ) + public async Task AnalyzeInviteLink(string url, bool join = false) + { + int start = url.IndexOf("//"); + start = url.IndexOf('/', start + 2) + 1; + int end = url.IndexOfAny(QueryOrFragment, start); + if (end == -1) end = url.Length; + if (start == 0 || end == start) throw new ArgumentException("Invalid URI"); + string hash; + if (url[start] == '+') + hash = url[(start + 1)..end]; + else if (string.Compare(url, start, "joinchat/", 0, 9, StringComparison.OrdinalIgnoreCase) == 0) + hash = url[(start + 9)..end]; + else + { + var resolved = await this.Contacts_ResolveUsername(url[start..end]); + var chat = resolved.Chat; + if (join && chat != null) + { + var res = await this.Channels_JoinChannel((Channel)chat); + chat = res.Chats[chat.ID]; + } + return chat; + } + var chatInvite = await this.Messages_CheckChatInvite(hash); + if (join) + try + { + var res = await this.Messages_ImportChatInvite(hash); + if (res.Chats.Values.FirstOrDefault() is ChatBase chat) return chat; + } + catch (RpcException ex) when (ex.Code == 400 && ex.Message == "INVITE_REQUEST_SENT") { } + switch (chatInvite) + { + case ChatInviteAlready cia: return cia.chat; + case ChatInvitePeek cip: return cip.chat; + case ChatInvite ci: + ChatPhoto chatPhoto = null; + if (ci.photo is Photo photo) + { + var stripped_thumb = photo.sizes.OfType().FirstOrDefault()?.bytes; + chatPhoto = new ChatPhoto + { + dc_id = photo.dc_id, + photo_id = photo.id, + stripped_thumb = stripped_thumb, + flags = (stripped_thumb != null ? ChatPhoto.Flags.has_stripped_thumb : 0) | + (photo.flags.HasFlag(Photo.Flags.has_video_sizes) ? ChatPhoto.Flags.has_video : 0), + }; + } + var rrAbout = ci.about == null ? null : new RestrictionReason[] { new() { text = ci.about } }; + return !ci.flags.HasFlag(ChatInvite.Flags.channel) + ? new Chat { title = ci.title, photo = chatPhoto, participants_count = ci.participants_count } + : new Channel { title = ci.title, photo = chatPhoto, participants_count = ci.participants_count, + restriction_reason = rrAbout, + flags = (ci.flags.HasFlag(ChatInvite.Flags.broadcast) ? Channel.Flags.broadcast | Channel.Flags.min : Channel.Flags.min) | + (ci.flags.HasFlag(ChatInvite.Flags.public_) ? Channel.Flags.has_username : 0) | + (ci.flags.HasFlag(ChatInvite.Flags.megagroup) ? Channel.Flags.megagroup : 0) | + (ci.flags.HasFlag(ChatInvite.Flags.request_needed) ? Channel.Flags.join_request : 0) }; + } + return null; + } + + /// Return chat and message details based on a message URL + /// Message Link, like https://t.me/c/1234567890/1234 or https://t.me/channelname/1234 + /// Structure containing the message, chat and user details + /// If link is for private group (t.me/c/..), user must have joined the group + public async Task GetMessageByLink(string url) + { + int start = url.IndexOf("//"); + start = url.IndexOf('/', start + 2) + 1; + int slash = url.IndexOf('/', start + 2); + if (start == 0 || slash == -1) throw new ArgumentException("Invalid URI"); + int end = url.IndexOfAny(QueryOrFragment, slash + 1); + if (end == -1) end = url.Length; + ChatBase chat; + if (url[start] is 'c' or 'C' && url[start + 1] == '/') + { + long chatId = long.Parse(url[(start + 2)..slash]); + var chats = await this.Channels_GetChannels(new InputChannel(chatId, 0)); + if (!chats.chats.TryGetValue(chatId, out chat)) + throw new ApplicationException($"Channel {chatId} not found"); + } + else + { + var resolved = await this.Contacts_ResolveUsername(url[start..slash]); + chat = resolved.Chat; + if (chat is null) throw new ApplicationException($"@{url[start..slash]} is not a Chat/Channel"); + } + int msgId = int.Parse(url[(slash + 1)..end]); + return await this.Channels_GetMessages((Channel)chat, msgId) as Messages_ChannelMessages; + } #endregion } }