mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 19:03:46 +03:00
Begin major entity overhaul
Introduce User and Chat as better alternatives to raw API. Document the rationale and new intended usage.
This commit is contained in:
parent
2c4ff8803f
commit
9bfe4cddf5
|
@ -598,14 +598,14 @@ The supported values are:
|
|||
|
||||
If you prefer to avoid hardcoding strings, you may use ``telethon.enums.Participant``.
|
||||
|
||||
The size selector for ``client.download_profile_photo`` and ``client.download_media` is now using
|
||||
The size selector for ``client.download_profile_photo`` and ``client.download_media`` is now using
|
||||
an enumeration:
|
||||
|
||||
```
|
||||
from telethon import enums
|
||||
.. code-block:: python
|
||||
|
||||
await client.download_profile_photo(user, thumb=enums.Size.ORIGINAL)
|
||||
```
|
||||
from telethon import enums
|
||||
|
||||
await client.download_profile_photo(user, thumb=enums.Size.ORIGINAL)
|
||||
|
||||
This new selection mode is also smart enough to pick the "next best" size if the specified one
|
||||
is not available. The parameter is known as ``thumb`` and not ``size`` because documents don't
|
||||
|
@ -639,7 +639,100 @@ The message sender no longer is the channel when no sender is provided by Telegr
|
|||
to patch this value for channels to be the same as the chat, but now it will be faithful to
|
||||
Telegram's value.
|
||||
|
||||
// TODO actually provide the things mentioned here
|
||||
|
||||
Overhaul of users and chats are no longer raw API types
|
||||
-------------------------------------------------------
|
||||
|
||||
Users and chats are no longer raw API types. The goal is to reduce the amount of raw API exposed
|
||||
to the user, and to provide less confusing naming. This also means that **the sender and chat of
|
||||
messages and events is now a different type**. If you were using `isinstance` to check the types,
|
||||
you will need to update that code. However, if you were accessing things like the ``first_name``
|
||||
or ``username``, you will be fine.
|
||||
|
||||
Raw API is not affected by this change. When using it, the raw :tl:`User`, :tl:`Chat` and
|
||||
:tl:`Channel` are still returned.
|
||||
|
||||
For friendly methods and events, There are now two main entity types, `User` and `Chat`.
|
||||
`User`\ s are active entities which can send messages and interact with eachother. There is an
|
||||
account controlling them. `Chat`\ s are passive entities where multiple users can join and
|
||||
interact with each other. This includes small groups, supergroups, and broadcast channels.
|
||||
|
||||
``event.get_sender``, ``event.sender``, ``event.get_chat``, and ``event.chat`` (as well as
|
||||
the same methods on ``message`` and elsewhere) now return this new type. The ``sender`` and
|
||||
``chat`` is **now always returned** (where it makes sense, so no sender in channel messages),
|
||||
even if Telegram did not include information about it in the update. This means you can use
|
||||
send messages to ``event.chat`` without worrying if Telegram included this information or not,
|
||||
or even access ``event.chat.id``. This was often a papercut. However, if you need other
|
||||
information like the title, you might still need to use ``await event.get_chat()``, which is
|
||||
used to signify an API call might be necessary.
|
||||
|
||||
``event.get_input_sender``, ``event.input_sender``, ``message.get_input_sender`` and
|
||||
``message.input_sender`` (among other variations) have been removed. Instead, a new ``compact``
|
||||
method has been added to the new `User` and `Chat` types, which can be used to obtain a compact
|
||||
representation of the sender. The "input" terminology is confusing for end-users, as it's mostly
|
||||
an implementation detail of friendly methods. Because the return type would've been different
|
||||
had these methods been kept, one would have had to review code using them regardless.
|
||||
|
||||
What this means is that, if you now want a compact way to store a user or chat for later use,
|
||||
you should use ``compact``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
compacted_user = message.sender.compact()
|
||||
# store compacted_user in a database or elsewhere for later use
|
||||
|
||||
Public methods accept this type as input parameters. This means you can send messages to a
|
||||
compacted user or chat, for example.
|
||||
|
||||
``event.is_private``, ``event.is_group`` and ``event.is_channel`` have **been removed** (among
|
||||
other variations, such as in ``message``). It didn't make much sense to ask "is this event a
|
||||
group", and there is no such thing as "group messages" currently either. Instead, it's sensible
|
||||
to ask if the sender of a message is a group, or the chat of an event is a channel. New properties
|
||||
have been added to both the `User` and `Chat` classes:
|
||||
|
||||
* ``.is_user`` will always be `True` for `User` and `False` for `Chat`.
|
||||
* ``.is_group`` will be `False` for `User` and be `True` for small group chats and supergroups.
|
||||
* ``.is_broadcast`` will be `False` for `User` and `True` for broadcast channels and broadcast groups.
|
||||
|
||||
Because the properties exist both in `User` and `Chat`, you do not need use `isinstance` to check
|
||||
if a sender is a channel or if a chat is a user.
|
||||
|
||||
Some fields of the new `User` type differ from the naming or value type of its raw API counterpart:
|
||||
|
||||
* ``user.restriction_reason`` has been renamed to ``restriction_reasons`` (with a trailing **s**)
|
||||
and now always returns a list.
|
||||
* ``user.bot_chat_history`` has been renamed to ``user.bot_info.chat_history_access``.
|
||||
* ``user.bot_nochats`` has been renamed to ``user.bot_info.private_only``.
|
||||
* ``user.bot_inline_geo`` has been renamed to ``user.bot_info.inline_geo``.
|
||||
* ``user.bot_info_version`` has been renamed to ``user.bot_info.version``.
|
||||
* ``user.bot_inline_placeholder`` has been renamed to ``user.bot_info.inline_placeholder``.
|
||||
|
||||
The new ``user.bot_info`` field will be `None` for non-bots. The goal is to unify where this
|
||||
information is found and reduce clutter in the main ``user`` type.
|
||||
|
||||
Some fields of the new `Chat` type differ from the naming or value type of its raw API counterpart:
|
||||
|
||||
* ``chat.date`` is currently not available. It's either the chat creation or join date, but due
|
||||
to this inconsistency, it's not included to allow for a better solution in the future.
|
||||
* ``chat.has_link`` is currently not available, to allow for a better alternative in the future.
|
||||
* ``chat.has_geo`` is currently not available, to allow for a better alternative in the future.
|
||||
* ``chat.call_active`` is currently not available, until it's decided what to do about calls.
|
||||
* ``chat.call_not_empty`` is currently not available, until it's decided what to do about calls.
|
||||
* ``chat.version`` was removed. It's an implementation detail.
|
||||
* ``chat.min`` was removed. It's an implementation detail.
|
||||
* ``chat.deactivated`` was removed. It's redundant with ``chat.migrated_to``.
|
||||
* ``chat.forbidden`` has been added as a replacement for ``isinstance(chat, (ChatForbidden, ChannelForbidden))``.
|
||||
* ``chat.forbidden_until`` has been added as a replacement for ``until_date`` in forbidden chats.
|
||||
* ``chat.restriction_reason`` has been renamed to ``restriction_reasons`` (with a trailing **s**)
|
||||
and now always returns a list.
|
||||
* ``chat.migrated_to`` no longer returns a raw type, and instead returns this new `Chat` type.
|
||||
|
||||
If you have a need for these, please step in, and explain your use case, so we can work together
|
||||
to implement a proper design.
|
||||
|
||||
Both the new `User` and `Chat` types offer a ``fetch`` method, which can be used to refetch the
|
||||
instance with fresh information, including the full information about the user (such as the user's
|
||||
biography or a chat's about description).
|
||||
|
||||
|
||||
Using a flat list to define buttons will now create rows and not columns
|
||||
|
@ -662,9 +755,9 @@ If you still want the old behaviour, wrap the list inside another list:
|
|||
|
||||
bot.send_message(chat, message, buttons=[[
|
||||
# +
|
||||
Button.inline('top'),
|
||||
Button.inline('middle'),
|
||||
Button.inline('bottom'),
|
||||
Button.inline('left'),
|
||||
Button.inline('center'),
|
||||
Button.inline('right'),
|
||||
]])
|
||||
#+
|
||||
|
||||
|
|
270
telethon/types/_custom/chat.py
Normal file
270
telethon/types/_custom/chat.py
Normal file
|
@ -0,0 +1,270 @@
|
|||
from typing import Optional, List, TYPE_CHECKING
|
||||
from datetime import datetime
|
||||
import mimetypes
|
||||
from .chatgetter import ChatGetter
|
||||
from .sendergetter import SenderGetter
|
||||
from .messagebutton import MessageButton
|
||||
from .forward import Forward
|
||||
from .file import File
|
||||
from .inputfile import InputFile
|
||||
from .inputmessage import InputMessage
|
||||
from .button import build_reply_markup
|
||||
from ..._misc import utils, helpers, tlobject, markdown, html
|
||||
from ... import _tl, _misc
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..._misc import hints
|
||||
|
||||
|
||||
def _fwd(field, doc):
|
||||
def fget(self):
|
||||
return getattr(self._message, field, None)
|
||||
|
||||
def fset(self, value):
|
||||
object.__setattr__(self._message, field, value)
|
||||
|
||||
return property(fget, fset, None, doc)
|
||||
|
||||
|
||||
class _InputChat:
|
||||
"""
|
||||
Input channels and peer chats use a different name for "id" which breaks the property forwarding.
|
||||
|
||||
This class simply holds the two fields with proper names.
|
||||
"""
|
||||
__slots__ = ('id', 'access_hash')
|
||||
|
||||
def __init__(self, input):
|
||||
self.id = getattr(input, 'channel_id', None) or input.chat_id
|
||||
self.access_hash = getattr(input, 'access_hash', None)
|
||||
|
||||
|
||||
class Chat:
|
||||
"""
|
||||
Represents a :tl:`Chat` or :tl:`Channel` (or their empty and forbidden variants) from the API.
|
||||
"""
|
||||
|
||||
id = _fwd('id', """
|
||||
The chat identifier. This is the only property which will **always** be present.
|
||||
""")
|
||||
|
||||
title = _fwd('title', """
|
||||
The chat title. It will be `None` for empty chats.
|
||||
""")
|
||||
|
||||
username = _fwd('username', """
|
||||
The public `username` of the chat.
|
||||
""")
|
||||
|
||||
participants_count = _fwd('participants_count', """
|
||||
The number of participants who are currently joined to the chat.
|
||||
It will be `None` for forbidden and empty chats or if the information isn't known.
|
||||
""")
|
||||
|
||||
broadcast = _fwd('broadcast', """
|
||||
`True` if the chat is a broadcast channel.
|
||||
""")
|
||||
|
||||
megagroup = _fwd('megagroup', """
|
||||
`True` if the chat is a supergroup.
|
||||
""")
|
||||
|
||||
gigagroup = _fwd('gigagroup', """
|
||||
`True` if the chat used to be a `megagroup` but is now a broadcast group.
|
||||
""")
|
||||
|
||||
verified = _fwd('verified', """
|
||||
`True` if the chat has been verified as official by Telegram.
|
||||
""")
|
||||
|
||||
scam = _fwd('scam', """
|
||||
`True` if the chat has been flagged as scam.
|
||||
""")
|
||||
|
||||
fake = _fwd('fake', """
|
||||
`True` if the chat has been flagged as fake.
|
||||
""")
|
||||
|
||||
creator = _fwd('creator', """
|
||||
`True` if the logged-in account is the creator of the chat.
|
||||
""")
|
||||
|
||||
kicked = _fwd('kicked', """
|
||||
`True` if the logged-in account was kicked from the chat.
|
||||
""")
|
||||
|
||||
left = _fwd('left', """
|
||||
`True` if the logged-in account has left the chat.
|
||||
""")
|
||||
|
||||
restricted = _fwd('restricted', """
|
||||
`True` if the logged-in account cannot write in the chat.
|
||||
""")
|
||||
|
||||
slowmode_enabled = _fwd('slowmode_enabled', """
|
||||
`True` if the chat currently has slowmode enabled.
|
||||
""")
|
||||
|
||||
signatures = _fwd('signatures', """
|
||||
`True` if signatures are enabled in a broadcast channel.
|
||||
""")
|
||||
|
||||
admin_rights = _fwd('admin_rights', """
|
||||
Administrator rights the logged-in account has in the chat.
|
||||
""")
|
||||
|
||||
banned_rights = _fwd('banned_rights', """
|
||||
Banned rights the logged-in account has in the chat.
|
||||
""")
|
||||
|
||||
default_banned_rights = _fwd('default_banned_rights', """
|
||||
The default banned rights for every non-admin user in the chat.
|
||||
""")
|
||||
|
||||
@property
|
||||
def forbidden(self):
|
||||
"""
|
||||
`True` if access to this channel is forbidden.
|
||||
"""
|
||||
return isinstance(self._chat, (_tl.ChatForbidden, _tl.ChannelForbidden))
|
||||
|
||||
@property
|
||||
def forbidden_until(self):
|
||||
"""
|
||||
If access to the chat is only temporarily `forbidden`, returns when access will be regained.
|
||||
"""
|
||||
try:
|
||||
return self._chat.until_date
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
@property
|
||||
def restriction_reasons(self):
|
||||
"""
|
||||
Returns a possibly-empty list of reasons why the chat is restricted to some platforms.
|
||||
"""
|
||||
try:
|
||||
return self._chat.restriction_reason or []
|
||||
except AttributeError:
|
||||
return []
|
||||
|
||||
@property
|
||||
def migrated_to(self):
|
||||
"""
|
||||
If the current chat has migrated to a larger group, returns the new `Chat`.
|
||||
"""
|
||||
try:
|
||||
migrated = self._chat.migrated_to
|
||||
except AttributeError:
|
||||
migrated = None
|
||||
|
||||
return Chat(_InputChat(migrated), self._client) if migrated else None
|
||||
|
||||
def __init__(self):
|
||||
raise TypeError('You cannot create Chat instances by hand!')
|
||||
|
||||
@classmethod
|
||||
def _new(cls, client, chat):
|
||||
self = cls.__new__(cls)
|
||||
self._client = client
|
||||
self._chat = chat
|
||||
self._full = None
|
||||
return self
|
||||
|
||||
async def fetch(self, *, full=False):
|
||||
"""
|
||||
Perform an API call to fetch fresh information about this chat.
|
||||
|
||||
Returns itself, but with the information fetched (allowing you to chain the call).
|
||||
|
||||
If ``full`` is ``True``, the full information about the user will be fetched,
|
||||
which will include things like ``about``.
|
||||
"""
|
||||
return self
|
||||
|
||||
def compact(self):
|
||||
"""
|
||||
Return a compact representation of this user, useful for storing for later use.
|
||||
"""
|
||||
raise RuntimeError('TODO')
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
"""
|
||||
Returns the `TelegramClient <telethon.client.telegramclient.TelegramClient>`
|
||||
which returned this user from a friendly method.
|
||||
"""
|
||||
return self._client
|
||||
|
||||
def to_dict(self):
|
||||
return self._user.to_dict()
|
||||
|
||||
def __repr__(self):
|
||||
return helpers.pretty_print(self)
|
||||
|
||||
def __str__(self):
|
||||
return helpers.pretty_print(self, max_depth=2)
|
||||
|
||||
def stringify(self):
|
||||
return helpers.pretty_print(self, indent=0)
|
||||
|
||||
@property
|
||||
def is_user(self):
|
||||
"""
|
||||
Returns `False`.
|
||||
|
||||
This property also exists in `User`, where it returns `True`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if message.chat.is_user:
|
||||
... # do stuff
|
||||
"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_group(self):
|
||||
"""
|
||||
Returns `True` if the chat is a small group chat or `megagroup`_.
|
||||
|
||||
This property also exists in `User`, where it returns `False`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if message.chat.is_group:
|
||||
... # do stuff
|
||||
|
||||
.. _megagroup: https://telegram.org/blog/supergroups5k
|
||||
"""
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_broadcast(self):
|
||||
"""
|
||||
Returns `True` if the chat is a broadcast channel group chat or `broadcast group`_.
|
||||
|
||||
This property also exists in `User`, where it returns `False`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if message.chat.is_broadcast:
|
||||
... # do stuff
|
||||
|
||||
.. _broadcast group: https://telegram.org/blog/autodelete-inv2#groups-with-unlimited-members
|
||||
"""
|
||||
return True
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
"""
|
||||
Returns `title`.
|
||||
|
||||
This property also exists in `User`, where it returns the first name and last name
|
||||
concatenated.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print(message.chat.full_name):
|
||||
"""
|
||||
return self.title
|
277
telethon/types/_custom/user.py
Normal file
277
telethon/types/_custom/user.py
Normal file
|
@ -0,0 +1,277 @@
|
|||
from typing import Optional, List, TYPE_CHECKING
|
||||
from datetime import datetime
|
||||
import mimetypes
|
||||
from .chatgetter import ChatGetter
|
||||
from .sendergetter import SenderGetter
|
||||
from .messagebutton import MessageButton
|
||||
from .forward import Forward
|
||||
from .file import File
|
||||
from .inputfile import InputFile
|
||||
from .inputmessage import InputMessage
|
||||
from .button import build_reply_markup
|
||||
from ..._misc import utils, helpers, tlobject, markdown, html
|
||||
from ... import _tl, _misc
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..._misc import hints
|
||||
|
||||
|
||||
def _fwd(field, doc):
|
||||
def fget(self):
|
||||
return getattr(self._message, field, None)
|
||||
|
||||
def fset(self, value):
|
||||
object.__setattr__(self._message, field, value)
|
||||
|
||||
return property(fget, fset, None, doc)
|
||||
|
||||
|
||||
class BotInfo:
|
||||
@property
|
||||
def version(self):
|
||||
"""
|
||||
Version number of this information, incremented whenever it changes.
|
||||
"""
|
||||
return self._user.bot_info_version
|
||||
|
||||
@property
|
||||
def chat_history_access(self):
|
||||
"""
|
||||
`True` if the bot has privacy mode disabled via @BotFather and can see *all* messages of the group.
|
||||
"""
|
||||
return self._user.bot_chat_history
|
||||
|
||||
@property
|
||||
def private_only(self):
|
||||
"""
|
||||
`True` if the bot cannot be added to group and can only be used in private messages.
|
||||
"""
|
||||
return self._user.bot_nochats
|
||||
|
||||
@property
|
||||
def inline_geo(self):
|
||||
"""
|
||||
`True` if the bot can request the user's geolocation when used in @bot inline mode.
|
||||
"""
|
||||
return self._user.bot_inline_geo
|
||||
|
||||
@property
|
||||
def inline_placeholder(self):
|
||||
"""
|
||||
The placeholder to show when using the @bot inline mode.
|
||||
"""
|
||||
return self._user.bot_inline_placeholder
|
||||
|
||||
def __init__(self, user):
|
||||
self._user = user
|
||||
|
||||
|
||||
class User:
|
||||
"""
|
||||
Represents a :tl:`User` (or :tl:`UserEmpty`, or :tl:`UserFull`) from the API.
|
||||
"""
|
||||
|
||||
id = _fwd('id', """
|
||||
The user identifier. This is the only property which will **always** be present.
|
||||
""")
|
||||
|
||||
first_name = _fwd('first_name', """
|
||||
The user's first name. It will be ``None`` for deleted accounts.
|
||||
""")
|
||||
|
||||
last_name = _fwd('last_name', """
|
||||
The user's last name. It can be ``None``.
|
||||
""")
|
||||
|
||||
username = _fwd('username', """
|
||||
The user's @username. It can be ``None``.
|
||||
""")
|
||||
|
||||
phone = _fwd('phone', """
|
||||
The user's phone number. It can be ``None`` if the user is not in your contacts or their
|
||||
privacy setting does not allow you to view the phone number.
|
||||
""")
|
||||
|
||||
is_self = _fwd('is_self', """
|
||||
``True`` if this user represents the logged-in account.
|
||||
""")
|
||||
|
||||
bot = _fwd('bot', """
|
||||
``True`` if this user is a bot created via @BotFather.
|
||||
""")
|
||||
|
||||
contact = _fwd('contact', """
|
||||
``True`` if this user is in the contact list of the logged-in account.
|
||||
""")
|
||||
|
||||
mutual_contact = _fwd('mutual_contact', """
|
||||
``True`` if this user is in the contact list of the logged-in account,
|
||||
and the user also has the logged-in account in their contact list.
|
||||
""")
|
||||
|
||||
deleted = _fwd('deleted', """
|
||||
``True`` if this user belongs to a deleted account.
|
||||
""")
|
||||
|
||||
verified = _fwd('verified', """
|
||||
``True`` if this user represents an official account verified by Telegram.
|
||||
""")
|
||||
|
||||
restricted = _fwd('restricted', """
|
||||
`True` if the user has been restricted for some reason.
|
||||
""")
|
||||
|
||||
support = _fwd('support', """
|
||||
``True`` if this user belongs to an official account from Telegram Support.
|
||||
""")
|
||||
|
||||
scam = _fwd('scam', """
|
||||
``True`` if this user has been flagged as spam.
|
||||
""")
|
||||
|
||||
fake = _fwd('fake', """
|
||||
``True`` if this user has been flagged as fake.
|
||||
""")
|
||||
|
||||
lang_code = _fwd('lang_code', """
|
||||
Language code of the user, if it's known.
|
||||
""")
|
||||
|
||||
@property
|
||||
def restriction_reasons(self):
|
||||
"""
|
||||
Returns a possibly-empty list of reasons why the chat is restricted to some platforms.
|
||||
"""
|
||||
try:
|
||||
return self._user.restriction_reason or []
|
||||
except AttributeError:
|
||||
return []
|
||||
|
||||
@property
|
||||
def bot_info(self):
|
||||
"""
|
||||
Additional information about the user if it's a bot, `None` otherwise.
|
||||
"""
|
||||
return BotInfo(self._user) if self.bot else None
|
||||
|
||||
def __init__(self):
|
||||
raise TypeError('You cannot create User instances by hand!')
|
||||
|
||||
@classmethod
|
||||
def _new(cls, client, user):
|
||||
self = cls.__new__(cls)
|
||||
|
||||
self._client = client
|
||||
self._user = user
|
||||
self._full = None
|
||||
raise RuntimeError('self._i_need_to_include_participant_info')
|
||||
|
||||
return self
|
||||
|
||||
async def fetch(self, *, full=False):
|
||||
"""
|
||||
Perform an API call to fetch fresh information about this user.
|
||||
|
||||
Returns itself, but with the information fetched (allowing you to chain the call).
|
||||
|
||||
If ``full`` is ``True``, the full information about the user will be fetched,
|
||||
which will include things like ``about``.
|
||||
"""
|
||||
|
||||
# sender - might just be hash
|
||||
# get sender - might be min
|
||||
# sender fetch - never min
|
||||
|
||||
return self
|
||||
|
||||
def compact(self):
|
||||
"""
|
||||
Return a compact representation of this user, useful for storing for later use.
|
||||
"""
|
||||
raise RuntimeError('TODO')
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
"""
|
||||
Returns the `TelegramClient <telethon.client.telegramclient.TelegramClient>`
|
||||
which returned this user from a friendly method.
|
||||
"""
|
||||
return self._client
|
||||
|
||||
def to_dict(self):
|
||||
return self._user.to_dict()
|
||||
|
||||
def __repr__(self):
|
||||
return helpers.pretty_print(self)
|
||||
|
||||
def __str__(self):
|
||||
return helpers.pretty_print(self, max_depth=2)
|
||||
|
||||
def stringify(self):
|
||||
return helpers.pretty_print(self, indent=0)
|
||||
|
||||
def download_profile_photo():
|
||||
# why'd you want to access photo? just do this
|
||||
pass
|
||||
|
||||
def get_profile_photos():
|
||||
# this i can understand as you can pick other photos... sadly exposing raw api
|
||||
pass
|
||||
|
||||
# TODO status, photo, and full properties
|
||||
|
||||
@property
|
||||
def is_user(self):
|
||||
"""
|
||||
Returns `True`.
|
||||
|
||||
This property also exists in `Chat`, where it returns `False`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if message.sender.is_user:
|
||||
... # do stuff
|
||||
"""
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_group(self):
|
||||
"""
|
||||
Returns `False`.
|
||||
|
||||
This property also exists in `Chat`, where it can return `True`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if message.sender.is_group:
|
||||
... # do stuff
|
||||
"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_broadcast(self):
|
||||
"""
|
||||
Returns `False`.
|
||||
|
||||
This property also exists in `Chat`, where it can return `True`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if message.sender.is_broadcast:
|
||||
... # do stuff
|
||||
"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
"""
|
||||
Returns the user's full name (first name and last name concatenated).
|
||||
|
||||
This property also exists in `Chat`, where it returns the title.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print(message.sender.full_name):
|
||||
"""
|
||||
return f'{self.first_name} {self.last_name}' if self.last_name else self.first_name
|
Loading…
Reference in New Issue
Block a user