From 12ce0a33c149faf3b903f19761aa742b9a04c659 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Thu, 7 May 2020 14:57:28 +0200 Subject: [PATCH 1/4] Add linked chats to Chat objects --- pyrogram/client/types/user_and_chats/chat.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py index 5e1f18fa..03b7d76a 100644 --- a/pyrogram/client/types/user_and_chats/chat.py +++ b/pyrogram/client/types/user_and_chats/chat.py @@ -101,6 +101,9 @@ class Chat(Object): distance (``int``, *optional*): Distance in meters of this group chat from your location. Returned only in :meth:`~Client.get_nearby_chats`. + + linked_chat (:obj:`Chat`, *optional*): + The linked discussion group (in case of channels) or the linked channel (in case of supergroups). """ def __init__( @@ -127,7 +130,8 @@ class Chat(Object): members_count: int = None, restrictions: List[Restriction] = None, permissions: "pyrogram.ChatPermissions" = None, - distance: int = None + distance: int = None, + linked_chat: "pyrogram.Chat" = None ): super().__init__(client) @@ -152,6 +156,7 @@ class Chat(Object): self.restrictions = restrictions self.permissions = permissions self.distance = distance + self.linked_chat = linked_chat @staticmethod def _parse_user_chat(client, user: types.User) -> "Chat": @@ -241,10 +246,14 @@ class Chat(Object): else: full_chat = chat_full.full_chat chat = None + linked_chat = None - for i in chat_full.chats: - if full_chat.id == i.id: - chat = i + for c in chat_full.chats: + if full_chat.id == c.id: + chat = c + + if full_chat.linked_chat_id == c.id: + linked_chat = c if isinstance(full_chat, types.ChatFull): parsed_chat = Chat._parse_chat_chat(client, chat) @@ -259,6 +268,7 @@ class Chat(Object): # TODO: Add StickerSet type parsed_chat.can_set_sticker_set = full_chat.can_set_stickers parsed_chat.sticker_set_name = getattr(full_chat.stickerset, "short_name", None) + parsed_chat.linked_chat = Chat._parse_channel_chat(client, linked_chat) if full_chat.pinned_msg_id: parsed_chat.pinned_message = client.get_messages( From 0556efa26bbf3f64f59716f77640429870dada8a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Thu, 7 May 2020 15:05:31 +0200 Subject: [PATCH 2/4] Add support for joining linked chats with the .join() bound method --- pyrogram/client/methods/chats/join_chat.py | 15 ++++++++++----- pyrogram/client/types/user_and_chats/chat.py | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pyrogram/client/methods/chats/join_chat.py b/pyrogram/client/methods/chats/join_chat.py index c379bf03..66687115 100644 --- a/pyrogram/client/methods/chats/join_chat.py +++ b/pyrogram/client/methods/chats/join_chat.py @@ -16,6 +16,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from typing import Union + import pyrogram from pyrogram.api import functions, types from ...ext import BaseClient @@ -24,14 +26,14 @@ from ...ext import BaseClient class JoinChat(BaseClient): def join_chat( self, - chat_id: str + chat_id: Union[int, str] ): """Join a group chat or channel. Parameters: - chat_id (``str``): - Unique identifier for the target chat in form of a *t.me/joinchat/* link or username of the target - channel/supergroup (in the format @username). + chat_id (``int`` | ``str``): + Unique identifier for the target chat in form of a *t.me/joinchat/* link, a username of the target + channel/supergroup (in the format @username) or a chat id of a linked chat (channel or supergroup). Returns: :obj:`Chat`: On success, a chat object is returned. @@ -44,8 +46,11 @@ class JoinChat(BaseClient): # Join chat via invite link app.join_chat("https://t.me/joinchat/AAAAAE0QmSW3IUmm3UFR7A") + + # Join a linked chat + app.join_chat(app.get_chat("pyrogram").linked_chat.id) """ - match = self.INVITE_LINK_RE.match(chat_id) + match = self.INVITE_LINK_RE.match(str(chat_id)) if match: chat = self.send( diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py index 03b7d76a..db2b3ef6 100644 --- a/pyrogram/client/types/user_and_chats/chat.py +++ b/pyrogram/client/types/user_and_chats/chat.py @@ -675,7 +675,7 @@ class Chat(Object): chat.join() Note: - This only works for public groups and channels that have set a username. + This only works for public groups, channels that have set a username or linked chats. Returns: :obj:`Chat`: On success, a chat object is returned. @@ -684,7 +684,7 @@ class Chat(Object): RPCError: In case of a Telegram RPC error. """ - return self._client.join_chat(self.username) + return self._client.join_chat(self.username or self.id) def leave(self): """Bound method *leave* of :obj:`Chat`. From 27d5caf40e41fc3576518c4dc9469b5896fbe5fb Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 16 May 2020 00:35:05 +0200 Subject: [PATCH 3/4] Give Filters.regex superpowers Basically make it work on Message, CallbackQuery and InlineQuery updates --- pyrogram/client/filters/filters.py | 36 +++++++++++++------ .../bots_and_keyboards/callback_query.py | 9 +++-- .../client/types/inline_mode/inline_query.py | 10 ++++-- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 24637640..50543f6e 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -20,6 +20,7 @@ import re from typing import Callable from .filter import Filter +from ..types import Message, CallbackQuery, InlineQuery from ..types.bots_and_keyboards import InlineKeyboardMarkup, ReplyKeyboardMarkup CUSTOM_FILTER_NAME = "CustomFilter" @@ -288,26 +289,39 @@ class Filters: ) @staticmethod - def regex(pattern, flags: int = 0): - """Filter message texts or captions that match a given regular expression pattern. + def regex(pattern: str, flags: int = 0): + """Filter updates that match a given regular expression pattern. + + Can be applied to handlers that receive one of the following updates: + + - :obj:`Message`: The filter will match ``text`` or ``caption``. + - :obj:`CallbackQuery`: The filter will match ``data``. + - :obj:`InlineQuery`: The filter will match ``query``. + + When a pattern matches, all the `Match Objects `_ are + stored in the ``matches`` field of the update object itself. Parameters: pattern (``str``): - The RegEx pattern as string, it will be applied to the text or the caption of a message. When a pattern - matches, all the `Match Objects `_ are stored - in the *matches* field of the :obj:`Message` itself. + The regex pattern as string. flags (``int``, *optional*): - RegEx flags. + Regex flags. """ - def func(flt, message): - text = message.text or message.caption + def func(flt, update): + if isinstance(update, Message): + value = update.text or update.caption + elif isinstance(update, CallbackQuery): + value = update.data + elif isinstance(update, InlineQuery): + value = update.query + else: + raise ValueError("Regex filter doesn't work with {}".format(type(update))) - if text: - message.matches = list(flt.p.finditer(text)) or None + update.matches = list(flt.p.finditer(value)) or None - return bool(message.matches) + return bool(update.matches) return create(func, "RegexFilter", p=re.compile(pattern, flags)) diff --git a/pyrogram/client/types/bots_and_keyboards/callback_query.py b/pyrogram/client/types/bots_and_keyboards/callback_query.py index 34b8b52c..9820e560 100644 --- a/pyrogram/client/types/bots_and_keyboards/callback_query.py +++ b/pyrogram/client/types/bots_and_keyboards/callback_query.py @@ -18,7 +18,7 @@ from base64 import b64encode from struct import pack -from typing import Union +from typing import Union, List, Match import pyrogram from pyrogram.api import types @@ -59,6 +59,9 @@ class CallbackQuery(Object, Update): game_short_name (``str``, *optional*): Short name of a Game to be returned, serves as the unique identifier for the game. + matches (List of regex Matches, *optional*): + A list containing all `Match Objects `_ that match + the data of this callback query. Only applicable when using :obj:`Filters.regex `. """ def __init__( @@ -71,7 +74,8 @@ class CallbackQuery(Object, Update): message: "pyrogram.Message" = None, inline_message_id: str = None, data: Union[str, bytes] = None, - game_short_name: str = None + game_short_name: str = None, + matches: List[Match] = None ): super().__init__(client) @@ -82,6 +86,7 @@ class CallbackQuery(Object, Update): self.inline_message_id = inline_message_id self.data = data self.game_short_name = game_short_name + self.matches = matches @staticmethod def _parse(client, callback_query, users) -> "CallbackQuery": diff --git a/pyrogram/client/types/inline_mode/inline_query.py b/pyrogram/client/types/inline_mode/inline_query.py index 44fea75d..eadc539c 100644 --- a/pyrogram/client/types/inline_mode/inline_query.py +++ b/pyrogram/client/types/inline_mode/inline_query.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import List +from typing import List, Match import pyrogram from pyrogram.api import types @@ -47,6 +47,10 @@ class InlineQuery(Object, Update): location (:obj:`Location`. *optional*): Sender location, only for bots that request user location. + + matches (List of regex Matches, *optional*): + A list containing all `Match Objects `_ that match + the query of this inline query. Only applicable when using :obj:`Filters.regex `. """ def __init__( @@ -57,7 +61,8 @@ class InlineQuery(Object, Update): from_user: User, query: str, offset: str, - location: Location = None + location: Location = None, + matches: List[Match] = None ): super().__init__(client) @@ -66,6 +71,7 @@ class InlineQuery(Object, Update): self.query = query self.offset = offset self.location = location + self.matches = matches @staticmethod def _parse(client, inline_query: types.UpdateBotInlineQuery, users: dict) -> "InlineQuery": From efc92715cc81ad2e6eba2bab3ca59af8776fc746 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 16 May 2020 00:40:05 +0200 Subject: [PATCH 4/4] Remove Filters.callback_data (superseded by Filters.regex) @ColinTheShark say goodbye, thanks. --- pyrogram/client/filters/filters.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 50543f6e..83493965 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -389,15 +389,4 @@ class Filters: and message.from_user.is_self and not message.outgoing))) - @staticmethod - def callback_data(data: str or bytes): - """Filter callback queries for their data. - - Parameters: - data (``str`` | ``bytes``): - Pass the data you want to filter for. - """ - - return create(lambda flt, cb: cb.data == flt.data, "CallbackDataFilter", data=data) - dan = create(lambda _, m: bool(m.from_user and m.from_user.id == 23122162), "DanFilter")