diff --git a/pyrogram/types/user_and_chats/__init__.py b/pyrogram/types/user_and_chats/__init__.py index 348ecd9f..2710f56a 100644 --- a/pyrogram/types/user_and_chats/__init__.py +++ b/pyrogram/types/user_and_chats/__init__.py @@ -35,6 +35,7 @@ from .emoji_status import EmojiStatus from .invite_link_importer import InviteLinkImporter from .restriction import Restriction from .user import User +from .username import Username from .video_chat_ended import VideoChatEnded from .video_chat_members_invited import VideoChatMembersInvited from .video_chat_scheduled import VideoChatScheduled @@ -48,6 +49,7 @@ __all__ = [ "ChatPreview", "Dialog", "User", + "Username", "Restriction", "ChatEvent", "ChatEventFilter", diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py index f37542fb..7a710e93 100644 --- a/pyrogram/types/user_and_chats/chat.py +++ b/pyrogram/types/user_and_chats/chat.py @@ -61,6 +61,9 @@ class Chat(Object): username (``str``, *optional*): Username, for private chats, bots, supergroups and channels if available. + usernames (List of :obj:`~pyrogram.types.Username`, *optional*): + The list of chat's collectible (and basic) usernames if available. + first_name (``str``, *optional*): First name of the other party in a private chat, for private chats and bots. @@ -145,6 +148,7 @@ class Chat(Object): is_support: bool = None, title: str = None, username: str = None, + usernames: List["types.Username"] = None, first_name: str = None, last_name: str = None, photo: "types.ChatPhoto" = None, @@ -176,6 +180,7 @@ class Chat(Object): self.is_support = is_support self.title = title self.username = username + self.usernames = usernames self.first_name = first_name self.last_name = last_name self.photo = photo @@ -208,6 +213,7 @@ class Chat(Object): is_fake=getattr(user, "fake", None), is_support=getattr(user, "support", None), username=user.username, + usernames=types.List([types.Username._parse(r) for r in user.usernames]) or None, first_name=user.first_name, last_name=user.last_name, photo=types.ChatPhoto._parse(client, user.photo, peer_id, user.access_hash), @@ -219,12 +225,14 @@ class Chat(Object): @staticmethod def _parse_chat_chat(client, chat: raw.types.Chat) -> "Chat": peer_id = -chat.id + usernames = getattr(chat, "usernames", []) return Chat( id=peer_id, type=enums.ChatType.GROUP, title=chat.title, is_creator=getattr(chat, "creator", None), + usernames=types.List([types.Username._parse(r) for r in usernames]) or None, photo=types.ChatPhoto._parse(client, getattr(chat, "photo", None), peer_id, 0), permissions=types.ChatPermissions._parse(getattr(chat, "default_banned_rights", None)), members_count=getattr(chat, "participants_count", None), @@ -237,6 +245,7 @@ class Chat(Object): def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat": peer_id = utils.get_channel_id(channel.id) restriction_reason = getattr(channel, "restriction_reason", []) + usernames = getattr(channel, "usernames", []) return Chat( id=peer_id, @@ -248,6 +257,7 @@ class Chat(Object): is_fake=getattr(channel, "fake", None), title=channel.title, username=getattr(channel, "username", None), + usernames=types.List([types.Username._parse(r) for r in usernames]) or None, photo=types.ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id, getattr(channel, "access_hash", 0)), restrictions=types.List([types.Restriction._parse(r) for r in restriction_reason]) or None, diff --git a/pyrogram/types/user_and_chats/user.py b/pyrogram/types/user_and_chats/user.py index e9813578..5a3313e3 100644 --- a/pyrogram/types/user_and_chats/user.py +++ b/pyrogram/types/user_and_chats/user.py @@ -118,6 +118,9 @@ class User(Object, Update): username (``str``, *optional*): User's or bot's username. + usernames (List of :obj:`~pyrogram.types.Username`, *optional*): + The list of user's collectible (and basic) usernames if available. + language_code (``str``, *optional*): IETF language tag of the user's language. @@ -169,6 +172,7 @@ class User(Object, Update): last_online_date: datetime = None, next_offline_date: datetime = None, username: str = None, + usernames: List["types.Username"] = None, language_code: str = None, emoji_status: Optional["types.EmojiStatus"] = None, dc_id: int = None, @@ -196,6 +200,7 @@ class User(Object, Update): self.last_online_date = last_online_date self.next_offline_date = next_offline_date self.username = username + self.usernames = usernames self.language_code = language_code self.emoji_status = emoji_status self.dc_id = dc_id @@ -233,6 +238,7 @@ class User(Object, Update): last_name=user.last_name, **User._parse_status(user.status, user.bot), username=user.username, + usernames=types.List([types.Username._parse(r) for r in user.usernames]) or None, language_code=user.lang_code, emoji_status=types.EmojiStatus._parse(client, user.emoji_status), dc_id=getattr(user.photo, "dc_id", None), diff --git a/pyrogram/types/user_and_chats/username.py b/pyrogram/types/user_and_chats/username.py new file mode 100644 index 00000000..55c6115c --- /dev/null +++ b/pyrogram/types/user_and_chats/username.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 pyrogram import raw +from ..object import Object + + +class Username(Object): + """A Telegram user's or chat's username. + + Parameters: + username (``str``): + User's or chat's username. + editable (``bool``, *optional*): + True, if it's a basic username; False, if it's a collectible username. + active (``bool``, *optional*): + True, if the collectible username is active. + """ + + def __init__(self, *, username: str, editable: bool = None, active: bool = None): + super().__init__(None) + + self.username = username + self.editable = editable + self.active = active + + @staticmethod + def _parse(username: "raw.types.Username") -> "Username": + return Username( + username=username.username, + editable=username.editable, + active=username.active + )