From bf207c872d20ed6b28f1013f43e8eec2c4398f57 Mon Sep 17 00:00:00 2001 From: Aliwoto Date: Thu, 6 Jun 2024 17:03:25 +0330 Subject: [PATCH] Add new files. Signed-off-by: Aliwoto --- pyrogram/enums/client_platform.py | 49 ++++++ .../handlers/pre_checkout_query_handler.py | 49 ++++++ .../methods/bots/answer_pre_checkout_query.py | 64 ++++++++ pyrogram/methods/business/__init__.py | 25 +++ .../business/get_business_connection.py | 54 +++++++ .../methods/chats/get_personal_channels.py | 48 ++++++ .../decorators/on_pre_checkout_query.py | 61 +++++++ pyrogram/methods/messages/business_session.py | 75 +++++++++ .../methods/messages/get_available_effects.py | 59 +++++++ pyrogram/methods/messages/search_posts.py | 96 +++++++++++ .../methods/messages/search_posts_count.py | 54 +++++++ pyrogram/methods/messages/view_messages.py | 61 +++++++ pyrogram/methods/payments/__init__.py | 24 +++ pyrogram/methods/payments/check_giftcode.py | 67 ++++++++ pyrogram/methods/phone/__init__.py | 25 +++ pyrogram/methods/phone/get_call_members.py | 103 ++++++++++++ pyrogram/methods/stories/view_stories.py | 61 +++++++ pyrogram/methods/users/update_birthday.py | 67 ++++++++ .../methods/users/update_personal_channel.py | 65 ++++++++ .../types/bots_and_keyboards/payment_info.py | 52 ++++++ .../bots_and_keyboards/pre_checkout_query.py | 139 ++++++++++++++++ .../bots_and_keyboards/shipping_address.py | 61 +++++++ .../bots_and_keyboards/successful_payment.py | 111 +++++++++++++ .../messages_and_media/available_effect.py | 88 +++++++++++ .../messages_and_media/business_message.py | 111 +++++++++++++ .../messages_and_media/checked_gift_code.py | 92 +++++++++++ pyrogram/types/messages_and_media/invoice.py | 85 ++++++++++ pyrogram/types/user_and_chats/birthday.py | 62 ++++++++ .../user_and_chats/business_connection.py | 82 ++++++++++ .../types/user_and_chats/business_intro.py | 74 +++++++++ .../types/user_and_chats/group_call_member.py | 149 ++++++++++++++++++ 31 files changed, 2213 insertions(+) create mode 100644 pyrogram/enums/client_platform.py create mode 100644 pyrogram/handlers/pre_checkout_query_handler.py create mode 100644 pyrogram/methods/bots/answer_pre_checkout_query.py create mode 100644 pyrogram/methods/business/__init__.py create mode 100644 pyrogram/methods/business/get_business_connection.py create mode 100644 pyrogram/methods/chats/get_personal_channels.py create mode 100644 pyrogram/methods/decorators/on_pre_checkout_query.py create mode 100644 pyrogram/methods/messages/business_session.py create mode 100644 pyrogram/methods/messages/get_available_effects.py create mode 100644 pyrogram/methods/messages/search_posts.py create mode 100644 pyrogram/methods/messages/search_posts_count.py create mode 100644 pyrogram/methods/messages/view_messages.py create mode 100644 pyrogram/methods/payments/__init__.py create mode 100644 pyrogram/methods/payments/check_giftcode.py create mode 100644 pyrogram/methods/phone/__init__.py create mode 100644 pyrogram/methods/phone/get_call_members.py create mode 100644 pyrogram/methods/stories/view_stories.py create mode 100644 pyrogram/methods/users/update_birthday.py create mode 100644 pyrogram/methods/users/update_personal_channel.py create mode 100644 pyrogram/types/bots_and_keyboards/payment_info.py create mode 100644 pyrogram/types/bots_and_keyboards/pre_checkout_query.py create mode 100644 pyrogram/types/bots_and_keyboards/shipping_address.py create mode 100644 pyrogram/types/bots_and_keyboards/successful_payment.py create mode 100644 pyrogram/types/messages_and_media/available_effect.py create mode 100644 pyrogram/types/messages_and_media/business_message.py create mode 100644 pyrogram/types/messages_and_media/checked_gift_code.py create mode 100644 pyrogram/types/messages_and_media/invoice.py create mode 100644 pyrogram/types/user_and_chats/birthday.py create mode 100644 pyrogram/types/user_and_chats/business_connection.py create mode 100644 pyrogram/types/user_and_chats/business_intro.py create mode 100644 pyrogram/types/user_and_chats/group_call_member.py diff --git a/pyrogram/enums/client_platform.py b/pyrogram/enums/client_platform.py new file mode 100644 index 00000000..3d392e0e --- /dev/null +++ b/pyrogram/enums/client_platform.py @@ -0,0 +1,49 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from enum import auto + +from .auto_name import AutoName + + +class ClientPlatform(AutoName): + """Valid platforms for a :obj:`~pyrogram.Client`.""" + + ANDROID = auto() + "Android" + + IOS = auto() + "iOS" + + WP = auto() + "Windows Phone" + + BB = auto() + "Blackberry" + + DESKTOP = auto() + "Desktop" + + WEB = auto() + "Web" + + UBP = auto() + "Ubuntu Phone" + + OTHER = auto() + "Other" diff --git a/pyrogram/handlers/pre_checkout_query_handler.py b/pyrogram/handlers/pre_checkout_query_handler.py new file mode 100644 index 00000000..ba8c6505 --- /dev/null +++ b/pyrogram/handlers/pre_checkout_query_handler.py @@ -0,0 +1,49 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Callable + +from .handler import Handler + + +class PreCheckoutQueryHandler(Handler): + """The PreCheckoutQueryHandler handler class. Used to handle pre-checkout queries coming from buy buttons. + It is intended to be used with :meth:`~pyrogram.Client.add_handler` + + For a nicer way to register this handler, have a look at the + :meth:`~pyrogram.Client.on_pre_checkout_query` decorator. + + Parameters: + callback (``Callable``): + Pass a function that will be called when a new PreCheckoutQuery arrives. It takes *(client, pre_checkout_query)* + as positional arguments (look at the section below for a detailed description). + + filters (:obj:`Filters`): + Pass one or more filters to allow only a subset of callback queries to be passed + in your callback function. + + Other parameters: + client (:obj:`~pyrogram.Client`): + The Client itself, useful when you want to call other API methods inside the message handler. + + pre_checkout_query (:obj:`~pyrogram.types.PreCheckoutQuery`): + The received callback query. + """ + + def __init__(self, callback: Callable, filters=None): + super().__init__(callback, filters) diff --git a/pyrogram/methods/bots/answer_pre_checkout_query.py b/pyrogram/methods/bots/answer_pre_checkout_query.py new file mode 100644 index 00000000..e9cc452c --- /dev/null +++ b/pyrogram/methods/bots/answer_pre_checkout_query.py @@ -0,0 +1,64 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from pyrogram import raw + + +class AnswerPreCheckoutQuery: + async def answer_pre_checkout_query( + self: "pyrogram.Client", + pre_checkout_query_id: str, + success: bool = None, + error: str = None + ): + """Send answers to pre-checkout queries. + + .. include:: /_includes/usable-by/bots.rst + + Parameters: + pre_checkout_query_id (``str``): + Unique identifier for the query to be answered. + + success (``bool``, *optional*): + Set this flag if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. + Otherwise do not set it, and set the error field, instead. + + error (``str``, *optional*): + Error message in human readable form that explains the reason for failure to proceed with the checkout. + Required if ``success`` isn't set. + + Returns: + ``bool``: True, on success. + + Example: + .. code-block:: python + + # Proceed with the order + await app.answer_pre_checkout_query(query_id, success=True) + + # Answer with error message + await app.answer_pre_checkout_query(query_id, error=error) + """ + return await self.invoke( + raw.functions.messages.SetBotPrecheckoutResults( + query_id=int(pre_checkout_query_id), + success=success or None, + error=error or None + ) + ) diff --git a/pyrogram/methods/business/__init__.py b/pyrogram/methods/business/__init__.py new file mode 100644 index 00000000..4f31035d --- /dev/null +++ b/pyrogram/methods/business/__init__.py @@ -0,0 +1,25 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from .get_business_connection import GetBusinessConnection + + +class Business( + GetBusinessConnection +): + pass diff --git a/pyrogram/methods/business/get_business_connection.py b/pyrogram/methods/business/get_business_connection.py new file mode 100644 index 00000000..62b6e82e --- /dev/null +++ b/pyrogram/methods/business/get_business_connection.py @@ -0,0 +1,54 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from pyrogram import raw, types + + +class GetBusinessConnection: + async def get_business_connection( + self: "pyrogram.Client", + connection_id: str + ): + """Get a business connection information. + + .. include:: /_includes/usable-by/users-bots.rst + + Parameters: + connection_id (``str``): + Unique identifier of the business connection. + + Returns: + :obj:`~pyrogram.types.BusinessConnection`: On success the business connection is returned. + + Example: + .. code-block:: python + + # Get a business connection information + app.get_business_connection(connection_id) + """ + r = await self.invoke( + raw.functions.account.GetBotBusinessConnection( + connection_id=connection_id + ) + ) + + users = {i.id: i for i in r.users} + chats = {i.id: i for i in r.chats} + + return types.BusinessConnection._parse(self, r.updates[0].connection, users) diff --git a/pyrogram/methods/chats/get_personal_channels.py b/pyrogram/methods/chats/get_personal_channels.py new file mode 100644 index 00000000..1a5038cc --- /dev/null +++ b/pyrogram/methods/chats/get_personal_channels.py @@ -0,0 +1,48 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import List, Optional + +import pyrogram +from pyrogram import raw, types + + +class GetPersonalChannels: + async def get_personal_channels( + self: "pyrogram.Client" + ) -> Optional[List["types.Chat"]]: + """Get all your public channels. + + .. include:: /_includes/usable-by/users.rst + + Returns: + List of :obj:`~pyrogram.types.Chat`: On success, a list of personal channels is returned. + + Example: + .. code-block:: python + + # Get all your personal channels + await app.get_personal_channels() + """ + r = await self.invoke( + raw.functions.channels.GetAdminedPublicChannels( + for_personal=True + ) + ) + + return types.List(types.Chat._parse_chat(self, i) for i in r.chats) or None diff --git a/pyrogram/methods/decorators/on_pre_checkout_query.py b/pyrogram/methods/decorators/on_pre_checkout_query.py new file mode 100644 index 00000000..9e076fda --- /dev/null +++ b/pyrogram/methods/decorators/on_pre_checkout_query.py @@ -0,0 +1,61 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Callable, Optional, Union + +import pyrogram +from pyrogram.filters import Filter + + +class OnPreCheckoutQuery: + def on_pre_checkout_query( + self: Union["OnPreCheckoutQuery", Filter, None] = None, + filters: Optional[Filter] = None, + group: int = 0, + ) -> Callable: + """Decorator for handling pre-checkout queries. + + This does the same thing as :meth:`~pyrogram.Client.add_handler` using the + :obj:`~pyrogram.handlers.PreCheckoutQueryHandler`. + + Parameters: + filters (:obj:`~pyrogram.filters`, *optional*): + Pass one or more filters to allow only a subset of callback queries to be passed + in your function. + + group (``int``, *optional*): + The group identifier, defaults to 0. + """ + + def decorator(func: Callable) -> Callable: + if isinstance(self, pyrogram.Client): + self.add_handler(pyrogram.handlers.PreCheckoutQueryHandler(func, filters), group) + elif isinstance(self, Filter) or self is None: + if not hasattr(func, "handlers"): + func.handlers = [] + + func.handlers.append( + ( + pyrogram.handlers.PreCheckoutQueryHandler(func, self), + group if filters is None else filters + ) + ) + + return func + + return decorator diff --git a/pyrogram/methods/messages/business_session.py b/pyrogram/methods/messages/business_session.py new file mode 100644 index 00000000..a207f428 --- /dev/null +++ b/pyrogram/methods/messages/business_session.py @@ -0,0 +1,75 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from pyrogram import raw +from pyrogram.errors import AuthBytesInvalid +from pyrogram.session import Session +from pyrogram.session.auth import Auth + + +async def get_session(client: "pyrogram.Client", business_connection_id: str) -> Session: + dc_id = client.business_connections.get(business_connection_id) + + if dc_id is None: + connection = await client.session.invoke( + raw.functions.account.GetBotBusinessConnection( + connection_id=business_connection_id + ) + ) + + dc_id = client.business_connections[business_connection_id] = connection.updates[0].connection.dc_id + + if dc_id == await client.storage.dc_id(): + return client.session + + async with client.sessions_lock: + if client.sessions.get(dc_id): + return client.sessions[dc_id] + + session = client.sessions[dc_id] = Session( + client, dc_id, + await Auth(client, dc_id, await client.storage.test_mode()).create(), + await client.storage.test_mode() + ) + + await session.start() + + for _ in range(3): + exported_auth = await client.invoke( + raw.functions.auth.ExportAuthorization( + dc_id=dc_id + ) + ) + + try: + await session.invoke( + raw.functions.auth.ImportAuthorization( + id=exported_auth.id, + bytes=exported_auth.bytes + ) + ) + except AuthBytesInvalid: + continue + else: + break + else: + await session.stop() + raise AuthBytesInvalid + + return session diff --git a/pyrogram/methods/messages/get_available_effects.py b/pyrogram/methods/messages/get_available_effects.py new file mode 100644 index 00000000..fc853781 --- /dev/null +++ b/pyrogram/methods/messages/get_available_effects.py @@ -0,0 +1,59 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import logging +from typing import List + +import pyrogram +from pyrogram import raw +from pyrogram import types + +log = logging.getLogger(__name__) + + +class GetAvailableEffects: + async def get_available_effects( + self: "pyrogram.Client" + ) -> List["types.AvailableEffect"]: + """Get all available effects. + + .. include:: /_includes/usable-by/users.rst + + Returns: + List of :obj:`~pyrogram.types.AvailableEffect`: A list of available effects is returned. + + Example: + .. code-block:: python + + # Get all available effects + await app.get_available_effects() + """ + r = await self.invoke( + raw.functions.messages.GetAvailableEffects( + hash=0 + ) + ) + + documents = {d.id: d for d in r.documents} + + return types.List( + [ + await types.AvailableEffect._parse(self, effect, documents.get(effect.effect_sticker_id, None)) + for effect in r.effects + ] + ) diff --git a/pyrogram/methods/messages/search_posts.py b/pyrogram/methods/messages/search_posts.py new file mode 100644 index 00000000..83dc2a51 --- /dev/null +++ b/pyrogram/methods/messages/search_posts.py @@ -0,0 +1,96 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import AsyncGenerator + +import pyrogram +from pyrogram import raw +from pyrogram import types +from pyrogram import utils + + +class SearchPosts: + async def search_posts( + self: "pyrogram.Client", + hashtag: str, + limit: int = 0, + ) -> AsyncGenerator["types.Message", None]: + """Search posts globally by hashtag. + + If you want to get the posts count only, see :meth:`~pyrogram.Client.search_posts_count`. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + hashtag (``str``): + Text query string. + + limit (``int``, *optional*): + Limits the number of posts to be retrieved. + By default, no limit is applied and all posts are returned. + + Returns: + ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects. + + Example: + .. code-block:: python + + # Search for "#pyrogram". Get the first 50 results + async for message in app.search_posts("#pyrogram", limit=50): + print(message.text) + """ + current = 0 + total = abs(limit) or (1 << 31) + limit = min(100, total) + + offset_date = 0 + offset_peer = raw.types.InputPeerEmpty() + offset_id = 0 + + while True: + messages = await utils.parse_messages( + self, + await self.invoke( + raw.functions.channels.SearchPosts( + hashtag=hashtag, + offset_rate=offset_date, + offset_peer=offset_peer, + offset_id=offset_id, + limit=limit + ), + sleep_threshold=60 + ), + replies=0 + ) + + if not messages: + return + + last = messages[-1] + + offset_date = utils.datetime_to_timestamp(last.date) + offset_peer = await self.resolve_peer(last.chat.id) + offset_id = last.id + + for message in messages: + yield message + + current += 1 + + if current >= total: + return diff --git a/pyrogram/methods/messages/search_posts_count.py b/pyrogram/methods/messages/search_posts_count.py new file mode 100644 index 00000000..5dc47839 --- /dev/null +++ b/pyrogram/methods/messages/search_posts_count.py @@ -0,0 +1,54 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from pyrogram import raw + + +class SearchPostsCount: + async def search_posts_count( + self: "pyrogram.Client", + hashtag: str, + ) -> int: + """Get the count of posts with hashtag resulting from a search. + + If you want to get the actual posts, see :meth:`~pyrogram.Client.search_posts`. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + hashtag (``str``): + Text query string. + + Returns: + ``int``: On success, the posts count is returned. + """ + r = await self.invoke( + raw.functions.channels.SearchPosts( + hashtag=hashtag, + offset_rate=0, + offset_peer=raw.types.InputPeerEmpty(), + offset_id=0, + limit=1 + ) + ) + + if hasattr(r, "count"): + return r.count + else: + return len(r.messages) diff --git a/pyrogram/methods/messages/view_messages.py b/pyrogram/methods/messages/view_messages.py new file mode 100644 index 00000000..09136f22 --- /dev/null +++ b/pyrogram/methods/messages/view_messages.py @@ -0,0 +1,61 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union, List + +import pyrogram +from pyrogram import raw + + +class ViewMessages: + async def view_messages( + self: "pyrogram.Client", + chat_id: Union[int, str], + message_id: Union[int, List[int]], + ) -> bool: + """Increment message views counter. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + + message_id (``int`` | List of ``int``): + Identifier or list of message identifiers of the target message. + + Returns: + ``bool``: On success, True is returned. + + Example: + .. code-block:: python + + # Increment message views + await app.view_messages(chat_id, 1) + """ + ids = [message_id] if not isinstance(message_id, list) else message_id + + r = await self.invoke( + raw.functions.messages.GetMessagesViews( + peer=await self.resolve_peer(chat_id), + id=ids, + increment=True + ) + ) + + return bool(r) diff --git a/pyrogram/methods/payments/__init__.py b/pyrogram/methods/payments/__init__.py new file mode 100644 index 00000000..d45ec785 --- /dev/null +++ b/pyrogram/methods/payments/__init__.py @@ -0,0 +1,24 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from .check_giftcode import CheckGiftCode + +class Payments( + CheckGiftCode +): + pass diff --git a/pyrogram/methods/payments/check_giftcode.py b/pyrogram/methods/payments/check_giftcode.py new file mode 100644 index 00000000..61359591 --- /dev/null +++ b/pyrogram/methods/payments/check_giftcode.py @@ -0,0 +1,67 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . +import re + +import pyrogram +from pyrogram import raw, types + + +class CheckGiftCode: + async def check_gift_code( + self: "pyrogram.Client", + link: str, + ) -> "types.CheckedGiftCode": + """Get information about a gift code. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + link (``str``): + The gift code link. + + Returns: + :obj:`~pyrogram.types.CheckedGiftCode`: On success, a checked gift code is returned. + + Raises: + ValueError: In case the folder invite link is invalid. + + Example: + .. code-block:: python + + # get information about a gift code + app.check_gift_code("t.me/giftcode/abc1234567def") + """ + match = re.match(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:giftcode/|\+))([\w-]+)$", link) + + if match: + slug = match.group(1) + elif isinstance(link, str): + slug = link + else: + raise ValueError("Invalid gift code link") + + r = await self.invoke( + raw.functions.payments.CheckGiftCode( + slug=slug + ) + ) + + users = {i.id: i for i in r.users} + chats = {i.id: i for i in r.chats} + + return types.CheckedGiftCode._parse(self, r, users, chats) diff --git a/pyrogram/methods/phone/__init__.py b/pyrogram/methods/phone/__init__.py new file mode 100644 index 00000000..d2cff63d --- /dev/null +++ b/pyrogram/methods/phone/__init__.py @@ -0,0 +1,25 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from .get_call_members import GetCallMembers + + +class Phone( + GetCallMembers +): + pass diff --git a/pyrogram/methods/phone/get_call_members.py b/pyrogram/methods/phone/get_call_members.py new file mode 100644 index 00000000..8fabc1d9 --- /dev/null +++ b/pyrogram/methods/phone/get_call_members.py @@ -0,0 +1,103 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union, AsyncGenerator + +import pyrogram +from pyrogram import types, raw + + +class GetCallMembers: + async def get_call_members( + self: "pyrogram.Client", + chat_id: Union[int, str], + limit: int = 0 + ) -> AsyncGenerator["types.GroupCallMember", None]: + """Get the members list of a chat call. + + A chat can be either a basic group or a supergroup. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + + limit (``int``, *optional*): + Limits the number of members to be retrieved. + + Returns: + ``Generator``: On success, a generator yielding :obj:`~pyrogram.types.GroupCallMember` objects is returned. + + Example: + .. code-block:: python + + # Get members + async for member in app.get_call_members(chat_id): + print(member) + """ + peer = await self.resolve_peer(chat_id) + + if isinstance(peer, raw.types.InputPeerChannel): + r = await self.invoke(raw.functions.channels.GetFullChannel(channel=peer)) + elif isinstance(peer, raw.types.InputPeerChat): + r = await self.invoke(raw.functions.messages.GetFullChat(chat_id=peer.chat_id)) + else: + raise ValueError("Target chat should be group, supergroup or channel.") + + full_chat = r.full_chat + + if not getattr(full_chat, "call", None): + raise ValueError("There is no active call in this chat.") + + current = 0 + offset = "" + total = abs(limit) or (1 << 31) - 1 + limit = min(20, total) + + while True: + r = await self.invoke( + raw.functions.phone.GetGroupParticipants( + call=full_chat.call, + ids=[], + sources=[], + offset=offset, + limit=limit + ), + sleep_threshold=60 + ) + + users = {u.id: u for u in r.users} + chats = {c.id: c for c in r.chats} + members = [ + types.GroupCallMember._parse(self, member, users, chats) + for member in r.participants + ] + + if not members: + return + + offset = r.next_offset + + for member in members: + yield member + + current += 1 + + if current >= total: + return diff --git a/pyrogram/methods/stories/view_stories.py b/pyrogram/methods/stories/view_stories.py new file mode 100644 index 00000000..9f5bf597 --- /dev/null +++ b/pyrogram/methods/stories/view_stories.py @@ -0,0 +1,61 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union, List + +import pyrogram +from pyrogram import raw + + +class ViewStories: + async def view_stories( + self: "pyrogram.Client", + chat_id: Union[int, str], + story_id: Union[int, List[int]], + ) -> bool: + """Increment story views. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For a contact that exists in your Telegram address book you can use his phone number (str). + + story_id (``int`` | List of ``int``): + Identifier or list of story identifiers of the target story. + + Returns: + ``bool``: On success, True is returned. + + Example: + .. code-block:: python + + # Increment story views + await app.view_stories(chat_id, 1) + """ + ids = [story_id] if not isinstance(story_id, list) else story_id + + r = await self.invoke( + raw.functions.stories.IncrementStoryViews( + peer=await self.resolve_peer(chat_id), + id=ids + ) + ) + + return r diff --git a/pyrogram/methods/users/update_birthday.py b/pyrogram/methods/users/update_birthday.py new file mode 100644 index 00000000..133bbb84 --- /dev/null +++ b/pyrogram/methods/users/update_birthday.py @@ -0,0 +1,67 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from pyrogram import raw + + +class UpdateBirthday: + async def update_birthday( + self: "pyrogram.Client", + day: int = None, + month: int = None, + year: int = None + ) -> bool: + """Update birthday in your profile. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + day (``int``, *optional*): + Birthday day. + + month (``int``, *optional*): + Birthday month. + + year (``int``, *optional*): + Birthday year. + + Returns: + ``bool``: True on success. + + Example: + .. code-block:: python + + # Update your birthday + await app.update_birthday(day=1, month=1, year=2000) + + # Remove birthday from profile + await app.update_birthday() + """ + birthday = None + + if all((day, month)): + birthday = raw.types.Birthday(day=day, month=month, year=year) + + return bool( + await self.invoke( + raw.functions.account.UpdateBirthday( + birthday=birthday + ) + ) + ) diff --git a/pyrogram/methods/users/update_personal_channel.py b/pyrogram/methods/users/update_personal_channel.py new file mode 100644 index 00000000..2b26c383 --- /dev/null +++ b/pyrogram/methods/users/update_personal_channel.py @@ -0,0 +1,65 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# 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 import raw + + +class UpdatePersonalChannel: + async def update_personal_channel( + self: "pyrogram.Client", + chat_id: Union[int, str] = None + ) -> bool: + """Update your personal channel. + + .. include:: /_includes/usable-by/users.rst + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target user. + Use :meth:`~pyrogram.Client.get_personal_channels` to get available channels. + + Returns: + ``bool``: True on success. + + Example: + .. code-block:: python + + # Update your personal channel + await app.update_personal_channel(chat_id) + + # Remove personal channel from your profile + await app.update_personal_channel() + """ + if chat_id is None: + peer = raw.types.InputChannelEmpty() + else: + peer = await self.resolve_peer(chat_id) + + if not isinstance(peer, raw.types.InputChannel): + return False + + return bool( + await self.invoke( + raw.functions.account.UpdatePersonalChannel( + channel=peer + ) + ) + ) diff --git a/pyrogram/types/bots_and_keyboards/payment_info.py b/pyrogram/types/bots_and_keyboards/payment_info.py new file mode 100644 index 00000000..16767c7a --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/payment_info.py @@ -0,0 +1,52 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from ..object import Object +from pyrogram import types + + +class PaymentInfo(Object): + """Contains information about a payment. + + Parameters: + name (``str``, *optional*): + User's name. + + phone_number (``str``, *optional*): + User's phone number. + + email (``str``, *optional*): + User's email. + + shipping_address (:obj:`~pyrogram.types.ShippingAddress`, *optional*): + User's shipping address. + """ + + def __init__( + self, *, + name: str = None, + phone_number: str = None, + email: str = None, + shipping_address: "types.ShippingAddress" = None + ): + super().__init__() + + self.name = name + self.phone_number = phone_number + self.email = email + self.shipping_address = shipping_address diff --git a/pyrogram/types/bots_and_keyboards/pre_checkout_query.py b/pyrogram/types/bots_and_keyboards/pre_checkout_query.py new file mode 100644 index 00000000..f8fde554 --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/pre_checkout_query.py @@ -0,0 +1,139 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union, List, Match, Optional + +import pyrogram +from pyrogram import raw, enums +from pyrogram import types +from ..object import Object +from ..update import Update +from ... import utils + + +class PreCheckoutQuery(Object, Update): + """An incoming pre-checkout query from a buy button in an inline keyboard. + + Parameters: + id (``str``): + Unique identifier for this query. + + from_user (:obj:`~pyrogram.types.User`): + User who sent the query. + + currency (``str``): + Three-letter ISO 4217 currency code. + + total_amount (``int``): + Total price in the smallest units of the currency. + + payload (``str``): + Bot specified invoice payload. + + shipping_option_id (``str``, *optional*): + Identifier of the shipping option chosen by the user. + + payment_info (:obj:`~pyrogram.types.PaymentInfo`, *optional*): + Payment information provided by the user. + """ + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + id: str, + from_user: "types.User", + currency: str, + total_amount: int, + payload: str, + shipping_option_id: str = None, + payment_info: "types.PaymentInfo" = None + ): + super().__init__(client) + + self.id = id + self.from_user = from_user + self.currency = currency + self.total_amount = total_amount + self.payload = payload + self.shipping_option_id = shipping_option_id + self.payment_info = payment_info + + @staticmethod + async def _parse(client: "pyrogram.Client", pre_checkout_query, users) -> "PreCheckoutQuery": + # Try to decode pre-checkout query payload into string. If that fails, fallback to bytes instead of decoding by + # ignoring/replacing errors, this way, button clicks will still work. + try: + payload = pre_checkout_query.payload.decode() + except (UnicodeDecodeError, AttributeError): + payload = pre_checkout_query.payload + + return PreCheckoutQuery( + id=str(pre_checkout_query.query_id), + from_user=types.User._parse(client, users[pre_checkout_query.user_id]), + currency=pre_checkout_query.currency, + total_amount=pre_checkout_query.total_amount, + payload=payload, + shipping_option_id=pre_checkout_query.shipping_option_id, + payment_info=types.PaymentInfo( + name=pre_checkout_query.info.name, + phone_number=pre_checkout_query.info.phone, + email=pre_checkout_query.info.email, + shipping_address=types.ShippingAddress( + street_line1=pre_checkout_query.info.shipping_address.street_line1, + street_line2=pre_checkout_query.info.shipping_address.street_line2, + city=pre_checkout_query.info.shipping_address.city, + state=pre_checkout_query.info.shipping_address.state, + post_code=pre_checkout_query.info.shipping_address.post_code, + country_code=pre_checkout_query.info.shipping_address.country_iso2 + ) + ) if pre_checkout_query.info else None, + client=client + ) + + async def answer(self, success: bool = None, error: str = None): + """Bound method *answer* of :obj:`~pyrogram.types.PreCheckoutQuery`. + + Use this method as a shortcut for: + + .. code-block:: python + + await client.answer_pre_checkout_query( + pre_checkout_query.id, + success=True + ) + + Example: + .. code-block:: python + + await pre_checkout_query.answer(success=True) + + Parameters: + success (``bool`` *optional*): + If true, an alert will be shown by the client instead of a notification at the top of the chat screen. + Defaults to False. + + error (``bool`` *optional*): + If true, an alert will be shown by the client instead of a notification at the top of the chat screen. + Defaults to False. + """ + return await self._client.answer_pre_checkout_query( + pre_checkout_query_id=self.id, + success=success, + error=error + ) diff --git a/pyrogram/types/bots_and_keyboards/shipping_address.py b/pyrogram/types/bots_and_keyboards/shipping_address.py new file mode 100644 index 00000000..8e373f31 --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/shipping_address.py @@ -0,0 +1,61 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from ..object import Object + + +class ShippingAddress(Object): + """Contains information about a shipping address. + + Parameters: + street_line1 (``str``): + First line for the address. + + street_line1 (``str``): + Second line for the address. + + city (``str``): + City for the address. + + state (``str``): + State for the address, if applicable. + + post_code (``str``): + Post code for the address. + + country_code (``str``): + Two-letter ISO 3166-1 alpha-2 country code. + """ + + def __init__( + self, *, + street_line1: str, + street_line2: str, + city: str, + state: str, + post_code: str, + country_code: str + ): + super().__init__() + + self.street_line1 = street_line1 + self.street_line2 = street_line2 + self.city = city + self.state = state + self.post_code = post_code + self.country_code = country_code diff --git a/pyrogram/types/bots_and_keyboards/successful_payment.py b/pyrogram/types/bots_and_keyboards/successful_payment.py new file mode 100644 index 00000000..d362f2f7 --- /dev/null +++ b/pyrogram/types/bots_and_keyboards/successful_payment.py @@ -0,0 +1,111 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from pyrogram import raw +from pyrogram import types +from ..object import Object + + +class SuccessfulPayment(Object): + """Contains information about a successful payment. + + Parameters: + currency (``str``): + Three-letter ISO 4217 currency code. + + total_amount (``int``): + Total price in the smallest units of the currency. + + payload (``str``, *optional*): + Bot specified invoice payload. Only available to the bot that received the payment. + + telegram_payment_charge_id (``str``, *optional*): + Telegram payment identifier. Only available to the bot that received the payment. + + provider_payment_charge_id (``str``, *optional*): + Provider payment identifier. Only available to the bot that received the payment. + + shipping_option_id (``str``, *optional*): + Identifier of the shipping option chosen by the user. Only available to the bot that received the payment. + + payment_info (:obj:`~pyrogram.types.PaymentInfo`, *optional*): + Payment information provided by the user. Only available to the bot that received the payment. + """ + + def __init__( + self, *, + currency: str, + total_amount: str, + payload: str, + telegram_payment_charge_id: str, + provider_payment_charge_id: str, + shipping_option_id: str = None, + payment_info: "types.PaymentInfo" = None + ): + super().__init__() + + self.currency = currency + self.total_amount = total_amount + self.payload = payload + self.telegram_payment_charge_id = telegram_payment_charge_id + self.provider_payment_charge_id = provider_payment_charge_id + self.shipping_option_id = shipping_option_id + self.payment_info = payment_info + + @staticmethod + def _parse(client: "pyrogram.Client", successful_payment) -> "SuccessfulPayment": + payload = None + telegram_payment_charge_id = None + provider_payment_charge_id = None + shipping_option_id = None + payment_info = None + + if isinstance(successful_payment, raw.types.MessageActionPaymentSentMe): + # Try to decode invoice payload into string. If that fails, fallback to bytes instead of decoding by + # ignoring/replacing errors, this way, button clicks will still work. + try: + payload = successful_payment.payload.decode() + except (UnicodeDecodeError, AttributeError): + payload = successful_payment.payload + + telegram_payment_charge_id = successful_payment.charge.id + provider_payment_charge_id = successful_payment.charge.provider_charge_id + shipping_option_id = successful_payment.shipping_option_id + payment_info = types.PaymentInfo( + name=successful_payment.info.name, + phone_number=successful_payment.info.phone, + email=successful_payment.info.email, + shipping_address=types.ShippingAddress( + street_line1=successful_payment.info.shipping_address.street_line1, + street_line2=successful_payment.info.shipping_address.street_line2, + city=successful_payment.info.shipping_address.city, + state=successful_payment.info.shipping_address.state, + post_code=successful_payment.info.shipping_address.post_code, + country_code=successful_payment.info.shipping_address.country_iso2 + ) + ) if successful_payment.info else None + + return SuccessfulPayment( + currency=successful_payment.currency, + total_amount=successful_payment.total_amount, + payload=payload, + telegram_payment_charge_id=telegram_payment_charge_id, + provider_payment_charge_id=shipping_option_id, + shipping_option_id=shipping_option_id, + payment_info=payment_info + ) diff --git a/pyrogram/types/messages_and_media/available_effect.py b/pyrogram/types/messages_and_media/available_effect.py new file mode 100644 index 00000000..c15614dd --- /dev/null +++ b/pyrogram/types/messages_and_media/available_effect.py @@ -0,0 +1,88 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Optional + +from pyrogram import raw, types +from ..object import Object + + +class AvailableEffect(Object): + """Contains information about available effect. + + Parameters: + id (``int``): + Unique effect identifier. + + emoji (``str``): + Emoji that represents the effect. + + effect_sticker_id (``int``): + sticker identifier that represents the effect. + + sticker (:obj:`~pyrogram.types.Sticker`, *optional*): + Sticker that represents the effect. + + is_premium (``bool``, *optional*): + Whether the effect is available only for premium users. + + static_icon_id (``int``, *optional*): + Static icon identifier that represents the effect. + + effect_animation_id (``int``, *optional*): + Animation identifier that represents the effect. + """ + + def __init__( + self, + *, + id: int, + emoji: str, + effect_sticker_id: int, + sticker: Optional["types.Sticker"] = None, + is_premium: Optional[bool] = None, + static_icon_id: Optional[int] = None, + effect_animation_id: Optional[int] = None + ): + super().__init__() + + self.id = id + self.emoji = emoji + self.effect_sticker_id = effect_sticker_id + self.sticker = sticker + self.is_premium = is_premium + self.static_icon_id = static_icon_id + self.effect_animation_id = effect_animation_id + + @staticmethod + async def _parse(client, effect: "raw.types.AvailableEffect", document: "raw.types.Document" = None) -> "AvailableEffect": + sticker = None + + if document: + attributes = {type(i): i for i in document.attributes} + sticker = await types.Sticker._parse(client, document, attributes) + + return AvailableEffect( + id=effect.id, + emoji=effect.emoticon, + effect_sticker_id=effect.effect_sticker_id, + sticker=sticker, + is_premium=getattr(effect, "premium_required", None), + static_icon_id=getattr(effect, "static_icon_id", None), + effect_animation_id=getattr(effect, "effect_animation_id", None) + ) diff --git a/pyrogram/types/messages_and_media/business_message.py b/pyrogram/types/messages_and_media/business_message.py new file mode 100644 index 00000000..272bde4e --- /dev/null +++ b/pyrogram/types/messages_and_media/business_message.py @@ -0,0 +1,111 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime +from typing import Optional, Union, List + +from pyrogram import types, enums, raw, utils +from ..object import Object + + +class BusinessMessage(Object): + """A Business message. + + Parameters: + shortcut_id (``int``): + ID of the shortcut. + + is_greeting (``bool``, *optional*): + True, if the message is a greeting message. + + is_away (``bool``, *optional*): + True, if the message is an away message. + + no_activity_days (``int``, *optional*): + Period of inactivity after which the greeting message should be sent again. + + offline_only (``bool``, *optional*): + Dont send the away message if you've recently been online. + + recipients (List of :obj:`~pyrogram.types.User`, *optional*): + Recipients of the message. + + schedule (:obj:`~pyrogram.enums.BusinessSchedule`, *optional*): + Schedule of the away message to be sent. + + start_date (:py:obj:`~datetime.datetime`, *optional*): + Start date of the away message. + + end_date (:py:obj:`~datetime.datetime`, *optional*): + End date of the away message. + """ + + def __init__( + self, + *, + shortcut_id: int, + is_greeting: bool = None, + is_away: bool = None, + no_activity_days: int = None, + offline_only: bool = None, + recipients: List["types.User"] = None, + schedule: "enums.BusinessSchedule" = None, + start_date: datetime = None, + end_date: datetime = None, + + ): + self.shortcut_id = shortcut_id + self.is_greeting = is_greeting + self.is_away = is_away + self.no_activity_days = no_activity_days + self.offline_only = offline_only + self.recipients = recipients + self.schedule = schedule + self.start_date = start_date + self.end_date = end_date + + @staticmethod + def _parse( + client, + message: Union["raw.types.BusinessGreetingMessage", "raw.types.BusinessAwayMessage"] = None, + users: dict = None + ) -> Optional["BusinessMessage"]: + if not message: + return None + + schedule = None + + if isinstance(message, raw.types.BusinessAwayMessage): + if isinstance(message.schedule, raw.types.BusinessAwayMessageScheduleAlways): + schedule = enums.BusinessSchedule.ALWAYS + elif isinstance(message.schedule, raw.types.BusinessAwayMessageScheduleOutsideWorkHours): + schedule = enums.BusinessSchedule.OUTSIDE_WORK_HOURS + elif isinstance(message.schedule, raw.types.BusinessAwayMessageScheduleCustom): + schedule = enums.BusinessSchedule.CUSTOM + + return BusinessMessage( + shortcut_id=message.shortcut_id, + is_greeting=isinstance(message, raw.types.BusinessGreetingMessage), + is_away=isinstance(message, raw.types.BusinessAwayMessage), + no_activity_days=getattr(message, "no_activity_days", None), + offline_only=getattr(message, "offline_only", None), + recipients=types.BusinessRecipients._parse(client, message.recipients, users), + schedule=schedule, + start_date=utils.timestamp_to_datetime(message.schedule.start_date) if schedule == enums.BusinessSchedule.CUSTOM else None, + end_date=utils.timestamp_to_datetime(message.schedule.end_date) if schedule == enums.BusinessSchedule.CUSTOM else None + ) diff --git a/pyrogram/types/messages_and_media/checked_gift_code.py b/pyrogram/types/messages_and_media/checked_gift_code.py new file mode 100644 index 00000000..7900c39f --- /dev/null +++ b/pyrogram/types/messages_and_media/checked_gift_code.py @@ -0,0 +1,92 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime + +from pyrogram import raw, types, utils +from ..object import Object + + +class CheckedGiftCode(Object): + """Contains checked gift code data. + + Parameters: + date (:py:obj:`~datetime.datetime`): + Date when the giveaway was launched. + + months (``int``): + Number of months of subscription. + + via_giveaway (``bool``, *optional*): + True if the gift code is received via giveaway. + + from_chat (:obj:`~pyrogram.types.Chat`, *optional*): + The channel where the gift code was won. + + winner (:obj:`~pyrogram.types.User`, *optional*): + The user who won the giveaway. + + giveaway_message_id (``int``, *optional*): + Identifier of the message from chat where the giveaway was launched. + + used_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the gift code was used. + """ + + def __init__( + self, + *, + date: datetime, + months: int, + via_giveaway: bool = None, + from_chat: "types.Chat" = None, + winner: "types.User" = None, + giveaway_message_id: int = None, + used_date: datetime = None + ): + super().__init__() + + self.date = date + self.months = months + self.via_giveaway = via_giveaway + self.from_chat = from_chat + self.winner = winner + self.giveaway_message_id = giveaway_message_id + self.used_date = used_date + + @staticmethod + def _parse(client, checked_gift_code: "raw.types.payments.CheckedGiftCode", users, chats): + from_chat = None + winner = None + + if getattr(checked_gift_code, "from_id", None): + from_chat = types.Chat._parse_chat( + client, chats.get(utils.get_raw_peer_id(checked_gift_code.from_id)) + ) + if getattr(checked_gift_code, "to_id", None): + winner = types.User._parse(client, users.get(checked_gift_code.to_id)) + + return CheckedGiftCode( + date=utils.timestamp_to_datetime(checked_gift_code.date), + months=checked_gift_code.months, + via_giveaway=getattr(checked_gift_code, "via_giveaway", None), + from_chat=from_chat, + winner=winner, + giveaway_message_id=getattr(checked_gift_code, "giveaway_msg_id", None), + used_date=utils.timestamp_to_datetime(checked_gift_code.used_date) if getattr(checked_gift_code, "used_date") else None, + ) diff --git a/pyrogram/types/messages_and_media/invoice.py b/pyrogram/types/messages_and_media/invoice.py new file mode 100644 index 00000000..3ff7e691 --- /dev/null +++ b/pyrogram/types/messages_and_media/invoice.py @@ -0,0 +1,85 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Optional + +from pyrogram import raw +from ..object import Object + + +class Invoice(Object): + """This object contains basic information about an invoice. + + Parameters: + title (``str``): + Product name. + + description (``str``): + Product description. + + start_parameter (``str``): + Unique bot deep-linking parameter that can be used to generate this invoice. + + currency (``str``): + Three-letter ISO 4217 `currency `_ code. + + total_amount (``int``): + Total price in the smallest units of the currency (integer, **not** float/double). For example, for a price of ``US$ 1.45`` pass ``amount = 145``. See the exp parameter in `currencies.json `_, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). + + is_shipping_address_requested (``bool``, *optional*): + True, if the shipping address should be specified. + + is_test (``bool``, *optional*): + True, if the invoice is a test invoice. + """ + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + title: str, + description: str, + currency: str, + total_amount: int, + start_parameter: Optional[str] = None, + is_shipping_address_requested: Optional[bool] = None, + is_test: Optional[bool] = None + ): + super().__init__(client) + + self.title = title + self.description = description + self.is_shipping_address_requested = is_shipping_address_requested + self.currency = currency + self.start_parameter = start_parameter + self.total_amount = total_amount + self.is_test = is_test + + @staticmethod + def _parse(client, invoice: "raw.types.MessageMediaInvoice") -> "Invoice": + return Invoice( + title=invoice.title, + description=invoice.description, + currency=invoice.currency, + total_amount=invoice.total_amount, + start_parameter=invoice.start_param or None, + is_shipping_address_requested=getattr(invoice, "shipping_address_requested", None), + is_test=getattr(invoice, "test", None), + client=client + # TODO: Add photo and extended media + ) diff --git a/pyrogram/types/user_and_chats/birthday.py b/pyrogram/types/user_and_chats/birthday.py new file mode 100644 index 00000000..6d54b4c5 --- /dev/null +++ b/pyrogram/types/user_and_chats/birthday.py @@ -0,0 +1,62 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Optional + +from pyrogram import raw +from ..object import Object + + +class Birthday(Object): + """Birthday information of a user. + + Parameters: + day (``int``): + Birthday day. + + month (``int``): + Birthday month. + + year (``int``, *optional*): + Birthday year. + """ + + def __init__( + self, + *, + day: int, + month: int, + year: int = None + + ): + self.day = day + self.month = month + self.year = year + + @staticmethod + def _parse( + birthday: "raw.types.Birthday" = None + ) -> Optional["Birthday"]: + if not birthday: + return + + return Birthday( + day=birthday.day, + month=birthday.month, + year=getattr(birthday, "year", None) + ) diff --git a/pyrogram/types/user_and_chats/business_connection.py b/pyrogram/types/user_and_chats/business_connection.py new file mode 100644 index 00000000..940c6f76 --- /dev/null +++ b/pyrogram/types/user_and_chats/business_connection.py @@ -0,0 +1,82 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime +from typing import Optional + +from pyrogram import types, raw, utils +from ..object import Object + + +class BusinessConnection(Object): + """Business information of a user. + + Parameters: + id (``str``): + Unique identifier of the business connection that belongs to the user. + + user (:obj:`~pyrogram.types.User`): + User that connected to the business connection. + + dc_id (``int``): + Datacenter identifier of the user. + + date (``datetime``): + Date when the user connected to the business. + + can_reply (``bool``, *optional*): + Whether the user can reply to the business. + + disabled (``bool``, *optional*): + Whether the business connection is disabled. + """ + + def __init__( + self, + *, + id: str, + user: "types.User", + dc_id: int, + date: datetime, + can_reply: bool = None, + disabled: bool = None + ): + self.id = id + self.user = user + self.dc_id = dc_id + self.date = date + self.can_reply = can_reply + self.disabled = disabled + + @staticmethod + def _parse( + client, + connection: "raw.types.BotBusinessConnection" = None, + users = {} + ) -> Optional["BusinessConnection"]: + if not connection: + return None + + return BusinessConnection( + id=connection.connection_id, + user=types.User._parse(client, users.get(connection.user_id)), + dc_id=connection.dc_id, + date=utils.timestamp_to_datetime(connection.date), + can_reply=getattr(connection, "can_reply", None), + disabled=getattr(connection, "disabled", None) + ) diff --git a/pyrogram/types/user_and_chats/business_intro.py b/pyrogram/types/user_and_chats/business_intro.py new file mode 100644 index 00000000..fa5b638f --- /dev/null +++ b/pyrogram/types/user_and_chats/business_intro.py @@ -0,0 +1,74 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from pyrogram import types, raw +from ..object import Object + + +class BusinessIntro(Object): + """Information about intro of this user. + + Parameters: + title (``str``, *optional*): + Title text of the business intro. + + text (``str``, *optional*): + Message text of the business intro. + + sticker (:obj:`~pyrogram.types.Sticker`, *optional*): + Sticker of the business intro. + + """ + + def __init__( + self, + *, + title: str = None, + text: str = None, + sticker: "types.Sticker" = None + ): + super().__init__() + + self.title = title + self.text = text + self.sticker = sticker + + + @staticmethod + async def _parse( + client, + business_intro: "raw.types.BusinessIntro" + ) -> "BusinessIntro": + if not business_intro: + return None + + doc = getattr(business_intro, "sticker", None) + sticker = None + + if doc and isinstance(doc, raw.types.Document): + sticker = await types.Sticker._parse( + client, + doc, + {type(i): i for i in doc.attributes} + ) + + return BusinessIntro( + title=getattr(business_intro, "title", None), + text=getattr(business_intro, "description", None), + sticker=sticker + ) diff --git a/pyrogram/types/user_and_chats/group_call_member.py b/pyrogram/types/user_and_chats/group_call_member.py new file mode 100644 index 00000000..551db102 --- /dev/null +++ b/pyrogram/types/user_and_chats/group_call_member.py @@ -0,0 +1,149 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime +from typing import Dict + +import pyrogram +from pyrogram import raw, types, utils +from ..object import Object + + +class GroupCallMember(Object): + """Contains information about one member of a group call. + + Parameters: + chat (:obj:`~pyrogram.types.Chat`, *optional*): + Information about the user or chat. + + date (:py:obj:`~datetime.datetime`, *optional*): + Date when this participant join this group call. + + active_date (:py:obj:`~datetime.datetime`, *optional*): + Date when this participant last active in this group call. + + volume (``int``, *optional*): + Volume, if not set the volume is set to 100%. + + can_self_unmute (``bool``, *optional*): + Whether the participant can unmute themselves. + + is_muted (``bool``, *optional*): + Whether the participant is muted. + + is_left (``bool``, *optional*): + Whether the participant has left. + + is_just_joined (``bool``, *optional*): + Whether the participant has just joined. + + is_muted_by_you (``bool``, *optional*): + Whether this participant was muted by the current user. + + is_volume_by_admin (``bool``, *optional*): + Whether our volume can only changed by an admin. + + is_self (``bool``, *optional*): + Whether this participant is the current user. + + is_video_joined (``bool``, *optional*): + Whether this participant is currently broadcasting video. + + is_hand_raised (``bool``, *optional*): + Whether this participant is raised hand. + + is_video_enabled (``bool``, *optional*): + Whether this participant is currently broadcasting video. + + is_screen_sharing_enabled (``bool``, *optional*): + Whether this participant is currently shared screen. + """ + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + chat: "types.Chat" = None, + date: datetime = None, + active_date: datetime = None, + volume: int = None, + can_self_unmute: bool = None, + is_muted: bool = None, + is_left: bool = None, + is_just_joined: bool = None, + is_muted_by_you: bool = None, + is_volume_by_admin: bool = None, + is_self: bool = None, + is_video_joined: bool = None, + is_hand_raised: bool = None, + is_video_enabled: bool = None, + is_screen_sharing_enabled: bool = None + ): + super().__init__(client) + + self.chat = chat + self.date = date + self.active_date = active_date + self.volume = volume + self.can_self_unmute = can_self_unmute + self.is_muted = is_muted + self.is_left = is_left + self.is_just_joined = is_just_joined + self.is_muted_by_you = is_muted_by_you + self.is_volume_by_admin = is_volume_by_admin + self.is_self = is_self + self.is_video_joined = is_video_joined + self.is_hand_raised = is_hand_raised + self.is_video_enabled = is_video_enabled + self.is_screen_sharing_enabled = is_screen_sharing_enabled + + @staticmethod + def _parse( + client: "pyrogram.Client", + member: "raw.types.GroupCallParticipant", + users: Dict[int, "raw.base.User"], + chats: Dict[int, "raw.base.Chat"] + ) -> "GroupCallMember": + peer = member.peer + peer_id = utils.get_raw_peer_id(peer) + + parsed_chat = types.Chat._parse_chat( + client, + users[peer_id] if isinstance(peer, raw.types.PeerUser) else chats[peer_id], + ) + + parsed_chat.bio = getattr(member, "about", None) + + return GroupCallMember( + chat=parsed_chat, + date=utils.timestamp_to_datetime(member.date), + active_date=utils.timestamp_to_datetime(member.active_date), + volume=getattr(member, "volume", None), + can_self_unmute=member.can_self_unmute, + is_muted=member.muted, + is_left=member.left, + is_just_joined=member.just_joined, + is_muted_by_you=member.muted_by_you, + is_volume_by_admin=member.volume_by_admin, + is_self=member.is_self, + is_video_joined=member.video_joined, + is_hand_raised=bool(getattr(member, "raise_hand_rating", None)), + is_video_enabled=bool(getattr(member, "video", None)), + is_screen_sharing_enabled=bool(getattr(member, "presentation", None)), + client=client + )