mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2025-01-03 09:49:21 +01:00
API 5.3 (#2572)
* BotCommandScopes
* pre-commit
* typo
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
* rename kickChatMember & getChatMembersCount method
Signed-off-by: starry69 <starry369126@outlook.com>
* add `language_code` and `scope` to `get/set_my_commands`
and add `delete_my_commands()`
* add `input_field_placeholder` to replykeyboardmarkup.py and forcereply.py
also improved/fixed docs along the way
* showcase `input_field_placeholder` in conversationbot.py
* review 1
'i will not go away' has gone away 😢
* deprecate `Bot.commands` and make sure its only used for default scope
* review 2 (use constants for scope)
* Review
Signed-off-by: starry69 <starry369126@outlook.com>
* doc updates
* New ChatMember classes
Signed-off-by: starry69 <starry369126@outlook.com>
* Address review
Signed-off-by: starry69 <starry369126@outlook.com>
* add versionadded tags again
Signed-off-by: starry69 <starry369126@outlook.com>
* Improve tests & add a deprecation note to ChatMember
* test_official
* Documentation tweaks
* Bump bot api version number
* but bot
* Rename chat shortcuts
Signed-off-by: starry69 <starry369126@outlook.com>
* deepsource
Signed-off-by: starry69 <starry369126@outlook.com>
* add missing slot in botcommandscope & missing slot tests
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: starry69 <starry369126@outlook.com>
Co-authored-by: Harshil <ilovebhagwan@gmail.com>
This commit is contained in:
parent
4315225642
commit
ed147813ab
34 changed files with 1776 additions and 123 deletions
|
@ -20,7 +20,7 @@ We have a vibrant community of developers helping each other in our `Telegram gr
|
||||||
:target: https://pypi.org/project/python-telegram-bot/
|
:target: https://pypi.org/project/python-telegram-bot/
|
||||||
:alt: Supported Python versions
|
:alt: Supported Python versions
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/Bot%20API-5.2-blue?logo=telegram
|
.. image:: https://img.shields.io/badge/Bot%20API-5.3-blue?logo=telegram
|
||||||
:target: https://core.telegram.org/bots/api-changelog
|
:target: https://core.telegram.org/bots/api-changelog
|
||||||
:alt: Supported Bot API versions
|
:alt: Supported Bot API versions
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
||||||
Telegram API support
|
Telegram API support
|
||||||
====================
|
====================
|
||||||
|
|
||||||
All types and methods of the Telegram Bot API **5.2** are supported.
|
All types and methods of the Telegram Bot API **5.3** are supported.
|
||||||
|
|
||||||
==========
|
==========
|
||||||
Installing
|
Installing
|
||||||
|
|
|
@ -20,7 +20,7 @@ We have a vibrant community of developers helping each other in our `Telegram gr
|
||||||
:target: https://pypi.org/project/python-telegram-bot-raw/
|
:target: https://pypi.org/project/python-telegram-bot-raw/
|
||||||
:alt: Supported Python versions
|
:alt: Supported Python versions
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/Bot%20API-5.2-blue?logo=telegram
|
.. image:: https://img.shields.io/badge/Bot%20API-5.3-blue?logo=telegram
|
||||||
:target: https://core.telegram.org/bots/api-changelog
|
:target: https://core.telegram.org/bots/api-changelog
|
||||||
:alt: Supported Bot API versions
|
:alt: Supported Bot API versions
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
||||||
Telegram API support
|
Telegram API support
|
||||||
====================
|
====================
|
||||||
|
|
||||||
All types and methods of the Telegram Bot API **5.2** are supported.
|
All types and methods of the Telegram Bot API **5.3** are supported.
|
||||||
|
|
||||||
==========
|
==========
|
||||||
Installing
|
Installing
|
||||||
|
|
8
docs/source/telegram.botcommandscope.rst
Normal file
8
docs/source/telegram.botcommandscope.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScope
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScope
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeAllChatAdministrators
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeAllChatAdministrators
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.botcommandscopeallgroupchats.rst
Normal file
8
docs/source/telegram.botcommandscopeallgroupchats.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeAllGroupChats
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeAllGroupChats
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.botcommandscopeallprivatechats.rst
Normal file
8
docs/source/telegram.botcommandscopeallprivatechats.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeAllPrivateChats
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeAllPrivateChats
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.botcommandscopechat.rst
Normal file
8
docs/source/telegram.botcommandscopechat.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeChat
|
||||||
|
============================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeChat
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeChatAdministrators
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeChatAdministrators
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.botcommandscopechatmember.rst
Normal file
8
docs/source/telegram.botcommandscopechatmember.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeChatMember
|
||||||
|
==================================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeChatMember
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.botcommandscopedefault.rst
Normal file
8
docs/source/telegram.botcommandscopedefault.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/botcommandscope.py
|
||||||
|
|
||||||
|
telegram.BotCommandScopeDefault
|
||||||
|
===============================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.BotCommandScopeDefault
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.chatmemberadministrator.rst
Normal file
8
docs/source/telegram.chatmemberadministrator.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/chatmember.py
|
||||||
|
|
||||||
|
telegram.ChatMemberAdministrator
|
||||||
|
================================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ChatMemberAdministrator
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.chatmemberbanned.rst
Normal file
8
docs/source/telegram.chatmemberbanned.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/chatmember.py
|
||||||
|
|
||||||
|
telegram.ChatMemberBanned
|
||||||
|
=========================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ChatMemberBanned
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.chatmemberleft.rst
Normal file
8
docs/source/telegram.chatmemberleft.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/chatmember.py
|
||||||
|
|
||||||
|
telegram.ChatMemberLeft
|
||||||
|
=======================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ChatMemberLeft
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
8
docs/source/telegram.chatmembermember.rst
Normal file
8
docs/source/telegram.chatmembermember.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/chatmember.py
|
||||||
|
|
||||||
|
telegram.ChatMemberMember
|
||||||
|
=========================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ChatMemberMember
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
9
docs/source/telegram.chatmemberowner.rst
Normal file
9
docs/source/telegram.chatmemberowner.rst
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/chatmember.py
|
||||||
|
|
||||||
|
telegram.ChatMemberOwner
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ChatMemberOwner
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
8
docs/source/telegram.chatmemberrestricted.rst
Normal file
8
docs/source/telegram.chatmemberrestricted.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/chatmember.py
|
||||||
|
|
||||||
|
telegram.ChatMemberRestricted
|
||||||
|
=============================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ChatMemberRestricted
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
|
@ -7,12 +7,26 @@ telegram package
|
||||||
telegram.audio
|
telegram.audio
|
||||||
telegram.bot
|
telegram.bot
|
||||||
telegram.botcommand
|
telegram.botcommand
|
||||||
|
telegram.botcommandscope
|
||||||
|
telegram.botcommandscopedefault
|
||||||
|
telegram.botcommandscopeallprivatechats
|
||||||
|
telegram.botcommandscopeallgroupchats
|
||||||
|
telegram.botcommandscopeallchatadministrators
|
||||||
|
telegram.botcommandscopechat
|
||||||
|
telegram.botcommandscopechatadministrators
|
||||||
|
telegram.botcommandscopechatmember
|
||||||
telegram.callbackquery
|
telegram.callbackquery
|
||||||
telegram.chat
|
telegram.chat
|
||||||
telegram.chataction
|
telegram.chataction
|
||||||
telegram.chatinvitelink
|
telegram.chatinvitelink
|
||||||
telegram.chatlocation
|
telegram.chatlocation
|
||||||
telegram.chatmember
|
telegram.chatmember
|
||||||
|
telegram.chatmemberowner
|
||||||
|
telegram.chatmemberadministrator
|
||||||
|
telegram.chatmembermember
|
||||||
|
telegram.chatmemberrestricted
|
||||||
|
telegram.chatmemberleft
|
||||||
|
telegram.chatmemberbanned
|
||||||
telegram.chatmemberupdated
|
telegram.chatmemberupdated
|
||||||
telegram.chatpermissions
|
telegram.chatpermissions
|
||||||
telegram.chatphoto
|
telegram.chatphoto
|
||||||
|
|
|
@ -44,7 +44,9 @@ def start(update: Update, context: CallbackContext) -> int:
|
||||||
'Hi! My name is Professor Bot. I will hold a conversation with you. '
|
'Hi! My name is Professor Bot. I will hold a conversation with you. '
|
||||||
'Send /cancel to stop talking to me.\n\n'
|
'Send /cancel to stop talking to me.\n\n'
|
||||||
'Are you a boy or a girl?',
|
'Are you a boy or a girl?',
|
||||||
reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True),
|
reply_markup=ReplyKeyboardMarkup(
|
||||||
|
reply_keyboard, one_time_keyboard=True, input_field_placeholder='Boy or Girl?'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return GENDER
|
return GENDER
|
||||||
|
|
|
@ -25,7 +25,15 @@ from .files.chatphoto import ChatPhoto
|
||||||
from .chat import Chat
|
from .chat import Chat
|
||||||
from .chatlocation import ChatLocation
|
from .chatlocation import ChatLocation
|
||||||
from .chatinvitelink import ChatInviteLink
|
from .chatinvitelink import ChatInviteLink
|
||||||
from .chatmember import ChatMember
|
from .chatmember import (
|
||||||
|
ChatMember,
|
||||||
|
ChatMemberOwner,
|
||||||
|
ChatMemberAdministrator,
|
||||||
|
ChatMemberMember,
|
||||||
|
ChatMemberRestricted,
|
||||||
|
ChatMemberLeft,
|
||||||
|
ChatMemberBanned,
|
||||||
|
)
|
||||||
from .chatmemberupdated import ChatMemberUpdated
|
from .chatmemberupdated import ChatMemberUpdated
|
||||||
from .chatpermissions import ChatPermissions
|
from .chatpermissions import ChatPermissions
|
||||||
from .files.photosize import PhotoSize
|
from .files.photosize import PhotoSize
|
||||||
|
@ -153,6 +161,16 @@ from .passport.credentials import (
|
||||||
FileCredentials,
|
FileCredentials,
|
||||||
TelegramDecryptionError,
|
TelegramDecryptionError,
|
||||||
)
|
)
|
||||||
|
from .botcommandscope import (
|
||||||
|
BotCommandScope,
|
||||||
|
BotCommandScopeDefault,
|
||||||
|
BotCommandScopeAllPrivateChats,
|
||||||
|
BotCommandScopeAllGroupChats,
|
||||||
|
BotCommandScopeAllChatAdministrators,
|
||||||
|
BotCommandScopeChat,
|
||||||
|
BotCommandScopeChatAdministrators,
|
||||||
|
BotCommandScopeChatMember,
|
||||||
|
)
|
||||||
from .bot import Bot
|
from .bot import Bot
|
||||||
from .version import __version__, bot_api_version # noqa: F401
|
from .version import __version__, bot_api_version # noqa: F401
|
||||||
|
|
||||||
|
@ -163,6 +181,14 @@ __all__ = ( # Keep this alphabetically ordered
|
||||||
'Audio',
|
'Audio',
|
||||||
'Bot',
|
'Bot',
|
||||||
'BotCommand',
|
'BotCommand',
|
||||||
|
'BotCommandScope',
|
||||||
|
'BotCommandScopeAllChatAdministrators',
|
||||||
|
'BotCommandScopeAllGroupChats',
|
||||||
|
'BotCommandScopeAllPrivateChats',
|
||||||
|
'BotCommandScopeChat',
|
||||||
|
'BotCommandScopeChatAdministrators',
|
||||||
|
'BotCommandScopeChatMember',
|
||||||
|
'BotCommandScopeDefault',
|
||||||
'CallbackGame',
|
'CallbackGame',
|
||||||
'CallbackQuery',
|
'CallbackQuery',
|
||||||
'Chat',
|
'Chat',
|
||||||
|
@ -170,6 +196,12 @@ __all__ = ( # Keep this alphabetically ordered
|
||||||
'ChatInviteLink',
|
'ChatInviteLink',
|
||||||
'ChatLocation',
|
'ChatLocation',
|
||||||
'ChatMember',
|
'ChatMember',
|
||||||
|
'ChatMemberOwner',
|
||||||
|
'ChatMemberAdministrator',
|
||||||
|
'ChatMemberMember',
|
||||||
|
'ChatMemberRestricted',
|
||||||
|
'ChatMemberLeft',
|
||||||
|
'ChatMemberBanned',
|
||||||
'ChatMemberUpdated',
|
'ChatMemberUpdated',
|
||||||
'ChatPermissions',
|
'ChatPermissions',
|
||||||
'ChatPhoto',
|
'ChatPhoto',
|
||||||
|
|
195
telegram/bot.py
195
telegram/bot.py
|
@ -57,6 +57,7 @@ from telegram import (
|
||||||
Animation,
|
Animation,
|
||||||
Audio,
|
Audio,
|
||||||
BotCommand,
|
BotCommand,
|
||||||
|
BotCommandScope,
|
||||||
Chat,
|
Chat,
|
||||||
ChatMember,
|
ChatMember,
|
||||||
ChatPermissions,
|
ChatPermissions,
|
||||||
|
@ -400,7 +401,20 @@ class Bot(TelegramObject):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def commands(self) -> List[BotCommand]:
|
def commands(self) -> List[BotCommand]:
|
||||||
"""List[:class:`BotCommand`]: Bot's commands."""
|
"""
|
||||||
|
List[:class:`BotCommand`]: Bot's commands as available in the default scope.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
This property has been deprecated since there can be different commands available for
|
||||||
|
different scopes.
|
||||||
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"Bot.commands has been deprecated since there can be different command "
|
||||||
|
"lists for different scopes.",
|
||||||
|
TelegramDeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
if self._commands is None:
|
if self._commands is None:
|
||||||
self._commands = self.get_my_commands()
|
self._commands = self.get_my_commands()
|
||||||
return self._commands
|
return self._commands
|
||||||
|
@ -2312,11 +2326,43 @@ class Bot(TelegramObject):
|
||||||
revoke_messages: bool = None,
|
revoke_messages: bool = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Use this method to kick a user from a group, supergroup or a channel. In the case of
|
Deprecated, use :func:`~telegram.Bot.ban_chat_member` instead.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
'`bot.kick_chat_member` is deprecated. Use `bot.ban_chat_member` instead.',
|
||||||
|
TelegramDeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return self.ban_chat_member(
|
||||||
|
chat_id=chat_id,
|
||||||
|
user_id=user_id,
|
||||||
|
timeout=timeout,
|
||||||
|
until_date=until_date,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
revoke_messages=revoke_messages,
|
||||||
|
)
|
||||||
|
|
||||||
|
@log
|
||||||
|
def ban_chat_member(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
user_id: Union[str, int],
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
until_date: Union[int, datetime] = None,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
revoke_messages: bool = None,
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Use this method to ban a user from a group, supergroup or a channel. In the case of
|
||||||
supergroups and channels, the user will not be able to return to the group on their own
|
supergroups and channels, the user will not be able to return to the group on their own
|
||||||
using invite links, etc., unless unbanned first. The bot must be an administrator in the
|
using invite links, etc., unless unbanned first. The bot must be an administrator in the
|
||||||
chat for this to work and must have the appropriate admin rights.
|
chat for this to work and must have the appropriate admin rights.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target group or username
|
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target group or username
|
||||||
of the target supergroup or channel (in the format ``@channelusername``).
|
of the target supergroup or channel (in the format ``@channelusername``).
|
||||||
|
@ -2358,7 +2404,7 @@ class Bot(TelegramObject):
|
||||||
if revoke_messages is not None:
|
if revoke_messages is not None:
|
||||||
data['revoke_messages'] = revoke_messages
|
data['revoke_messages'] = revoke_messages
|
||||||
|
|
||||||
result = self._post('kickChatMember', data, timeout=timeout, api_kwargs=api_kwargs)
|
result = self._post('banChatMember', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
return result # type: ignore[return-value]
|
return result # type: ignore[return-value]
|
||||||
|
|
||||||
|
@ -3061,9 +3107,31 @@ class Bot(TelegramObject):
|
||||||
chat_id: Union[str, int],
|
chat_id: Union[str, int],
|
||||||
timeout: ODVInput[float] = DEFAULT_NONE,
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> int:
|
||||||
|
"""
|
||||||
|
Deprecated, use :func:`~telegram.Bot.get_chat_member_count` instead.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
'`bot.get_chat_members_count` is deprecated. '
|
||||||
|
'Use `bot.get_chat_member_count` instead.',
|
||||||
|
TelegramDeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return self.get_chat_member_count(chat_id=chat_id, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
@log
|
||||||
|
def get_chat_member_count(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Use this method to get the number of members in a chat.
|
"""Use this method to get the number of members in a chat.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target chat or username
|
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target chat or username
|
||||||
of the target supergroup or channel (in the format ``@channelusername``).
|
of the target supergroup or channel (in the format ``@channelusername``).
|
||||||
|
@ -3082,7 +3150,7 @@ class Bot(TelegramObject):
|
||||||
"""
|
"""
|
||||||
data: JSONDict = {'chat_id': chat_id}
|
data: JSONDict = {'chat_id': chat_id}
|
||||||
|
|
||||||
result = self._post('getChatMembersCount', data, timeout=timeout, api_kwargs=api_kwargs)
|
result = self._post('getChatMemberCount', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
return result # type: ignore[return-value]
|
return result # type: ignore[return-value]
|
||||||
|
|
||||||
|
@ -4959,10 +5027,15 @@ class Bot(TelegramObject):
|
||||||
|
|
||||||
@log
|
@log
|
||||||
def get_my_commands(
|
def get_my_commands(
|
||||||
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
|
self,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
scope: BotCommandScope = None,
|
||||||
|
language_code: str = None,
|
||||||
) -> List[BotCommand]:
|
) -> List[BotCommand]:
|
||||||
"""
|
"""
|
||||||
Use this method to get the current list of the bot's commands.
|
Use this method to get the current list of the bot's commands for the given scope and user
|
||||||
|
language.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
|
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
|
||||||
|
@ -4970,29 +5043,53 @@ class Bot(TelegramObject):
|
||||||
the connection pool).
|
the connection pool).
|
||||||
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
|
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
|
||||||
Telegram API.
|
Telegram API.
|
||||||
|
scope (:class:`telegram.BotCommandScope`, optional): A JSON-serialized object,
|
||||||
|
describing scope of users. Defaults to :class:`telegram.BotCommandScopeDefault`.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
language_code (:obj:`str`, optional): A two-letter ISO 639-1 language code or an empty
|
||||||
|
string.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List[:class:`telegram.BotCommand]`: On success, the commands set for the bot
|
List[:class:`telegram.BotCommand`]: On success, the commands set for the bot. An empty
|
||||||
|
list is returned if commands are not set.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`telegram.error.TelegramError`
|
:class:`telegram.error.TelegramError`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
result = self._post('getMyCommands', timeout=timeout, api_kwargs=api_kwargs)
|
data: JSONDict = {}
|
||||||
|
|
||||||
|
if scope:
|
||||||
|
data['scope'] = scope.to_dict()
|
||||||
|
|
||||||
|
if language_code:
|
||||||
|
data['language_code'] = language_code
|
||||||
|
|
||||||
|
result = self._post('getMyCommands', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
if (scope is None or scope.type == scope.DEFAULT) and language_code is None:
|
||||||
self._commands = BotCommand.de_list(result, self) # type: ignore[assignment,arg-type]
|
self._commands = BotCommand.de_list(result, self) # type: ignore[assignment,arg-type]
|
||||||
|
|
||||||
return self._commands # type: ignore[return-value]
|
return self._commands # type: ignore[return-value]
|
||||||
|
|
||||||
|
return BotCommand.de_list(result, self) # type: ignore[return-value,arg-type]
|
||||||
|
|
||||||
@log
|
@log
|
||||||
def set_my_commands(
|
def set_my_commands(
|
||||||
self,
|
self,
|
||||||
commands: List[Union[BotCommand, Tuple[str, str]]],
|
commands: List[Union[BotCommand, Tuple[str, str]]],
|
||||||
timeout: ODVInput[float] = DEFAULT_NONE,
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
|
scope: BotCommandScope = None,
|
||||||
|
language_code: str = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Use this method to change the list of the bot's commands.
|
Use this method to change the list of the bot's commands. See the
|
||||||
|
`Telegram docs <https://core.telegram.org/bots#commands>`_ for more details about bot
|
||||||
|
commands.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
commands (List[:class:`BotCommand` | (:obj:`str`, :obj:`str`)]): A JSON-serialized list
|
commands (List[:class:`BotCommand` | (:obj:`str`, :obj:`str`)]): A JSON-serialized list
|
||||||
|
@ -5003,9 +5100,20 @@ class Bot(TelegramObject):
|
||||||
the connection pool).
|
the connection pool).
|
||||||
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
|
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
|
||||||
Telegram API.
|
Telegram API.
|
||||||
|
scope (:class:`telegram.BotCommandScope`, optional): A JSON-serialized object,
|
||||||
|
describing scope of users for which the commands are relevant. Defaults to
|
||||||
|
:class:`telegram.BotCommandScopeDefault`.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
language_code (:obj:`str`, optional): A two-letter ISO 639-1 language code. If empty,
|
||||||
|
commands will be applied to all users from the given scope, for whose language
|
||||||
|
there are no dedicated commands.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`True`: On success
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`telegram.error.TelegramError`
|
:class:`telegram.error.TelegramError`
|
||||||
|
@ -5015,14 +5123,71 @@ class Bot(TelegramObject):
|
||||||
|
|
||||||
data: JSONDict = {'commands': [c.to_dict() for c in cmds]}
|
data: JSONDict = {'commands': [c.to_dict() for c in cmds]}
|
||||||
|
|
||||||
|
if scope:
|
||||||
|
data['scope'] = scope.to_dict()
|
||||||
|
|
||||||
|
if language_code:
|
||||||
|
data['language_code'] = language_code
|
||||||
|
|
||||||
result = self._post('setMyCommands', data, timeout=timeout, api_kwargs=api_kwargs)
|
result = self._post('setMyCommands', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
# Set commands. No need to check for outcome.
|
# Set commands only for default scope. No need to check for outcome.
|
||||||
# If request failed, we won't come this far
|
# If request failed, we won't come this far
|
||||||
|
if (scope is None or scope.type == scope.DEFAULT) and language_code is None:
|
||||||
self._commands = cmds
|
self._commands = cmds
|
||||||
|
|
||||||
return result # type: ignore[return-value]
|
return result # type: ignore[return-value]
|
||||||
|
|
||||||
|
@log
|
||||||
|
def delete_my_commands(
|
||||||
|
self,
|
||||||
|
scope: BotCommandScope = None,
|
||||||
|
language_code: str = None,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Use this method to delete the list of the bot's commands for the given scope and user
|
||||||
|
language. After deletion,
|
||||||
|
`higher level commands <https://core.telegram.org/bots/api#determining-list-of-commands>`_
|
||||||
|
will be shown to affected users.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
scope (:class:`telegram.BotCommandScope`, optional): A JSON-serialized object,
|
||||||
|
describing scope of users for which the commands are relevant. Defaults to
|
||||||
|
:class:`telegram.BotCommandScopeDefault`.
|
||||||
|
language_code (:obj:`str`, optional): A two-letter ISO 639-1 language code. If empty,
|
||||||
|
commands will be applied to all users from the given scope, for whose language
|
||||||
|
there are no dedicated commands.
|
||||||
|
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
|
||||||
|
the read timeout from the server (instead of the one specified during creation of
|
||||||
|
the connection pool).
|
||||||
|
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
|
||||||
|
Telegram API.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.error.TelegramError`
|
||||||
|
"""
|
||||||
|
data: JSONDict = {}
|
||||||
|
|
||||||
|
if scope:
|
||||||
|
data['scope'] = scope.to_dict()
|
||||||
|
|
||||||
|
if language_code:
|
||||||
|
data['language_code'] = language_code
|
||||||
|
|
||||||
|
result = self._post('deleteMyCommands', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
if (scope is None or scope.type == scope.DEFAULT) and language_code is None:
|
||||||
|
self._commands = []
|
||||||
|
|
||||||
|
return result # type: ignore[return-value]
|
||||||
|
|
||||||
@log
|
@log
|
||||||
def log_out(self, timeout: ODVInput[float] = DEFAULT_NONE) -> bool:
|
def log_out(self, timeout: ODVInput[float] = DEFAULT_NONE) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -5210,6 +5375,8 @@ class Bot(TelegramObject):
|
||||||
"""Alias for :meth:`get_user_profile_photos`"""
|
"""Alias for :meth:`get_user_profile_photos`"""
|
||||||
getFile = get_file
|
getFile = get_file
|
||||||
"""Alias for :meth:`get_file`"""
|
"""Alias for :meth:`get_file`"""
|
||||||
|
banChatMember = ban_chat_member
|
||||||
|
"""Alias for :meth:`ban_chat_member`"""
|
||||||
kickChatMember = kick_chat_member
|
kickChatMember = kick_chat_member
|
||||||
"""Alias for :meth:`kick_chat_member`"""
|
"""Alias for :meth:`kick_chat_member`"""
|
||||||
unbanChatMember = unban_chat_member
|
unbanChatMember = unban_chat_member
|
||||||
|
@ -5242,6 +5409,8 @@ class Bot(TelegramObject):
|
||||||
"""Alias for :meth:`set_chat_sticker_set`"""
|
"""Alias for :meth:`set_chat_sticker_set`"""
|
||||||
deleteChatStickerSet = delete_chat_sticker_set
|
deleteChatStickerSet = delete_chat_sticker_set
|
||||||
"""Alias for :meth:`delete_chat_sticker_set`"""
|
"""Alias for :meth:`delete_chat_sticker_set`"""
|
||||||
|
getChatMemberCount = get_chat_member_count
|
||||||
|
"""Alias for :meth:`get_chat_member_count`"""
|
||||||
getChatMembersCount = get_chat_members_count
|
getChatMembersCount = get_chat_members_count
|
||||||
"""Alias for :meth:`get_chat_members_count`"""
|
"""Alias for :meth:`get_chat_members_count`"""
|
||||||
getWebhookInfo = get_webhook_info
|
getWebhookInfo = get_webhook_info
|
||||||
|
@ -5312,6 +5481,8 @@ class Bot(TelegramObject):
|
||||||
"""Alias for :meth:`get_my_commands`"""
|
"""Alias for :meth:`get_my_commands`"""
|
||||||
setMyCommands = set_my_commands
|
setMyCommands = set_my_commands
|
||||||
"""Alias for :meth:`set_my_commands`"""
|
"""Alias for :meth:`set_my_commands`"""
|
||||||
|
deleteMyCommands = delete_my_commands
|
||||||
|
"""Alias for :meth:`delete_my_commands`"""
|
||||||
logOut = log_out
|
logOut = log_out
|
||||||
"""Alias for :meth:`log_out`"""
|
"""Alias for :meth:`log_out`"""
|
||||||
copyMessage = copy_message
|
copyMessage = copy_message
|
||||||
|
|
263
telegram/botcommandscope.py
Normal file
263
telegram/botcommandscope.py
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# A library that provides a Python interface to the Telegram Bot API
|
||||||
|
# Copyright (C) 2021
|
||||||
|
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
|
# pylint: disable=W0622
|
||||||
|
"""This module contains objects representing Telegram bot command scopes."""
|
||||||
|
from typing import Any, Union, Optional, TYPE_CHECKING, Dict, Type
|
||||||
|
|
||||||
|
from telegram import TelegramObject, constants
|
||||||
|
from telegram.utils.types import JSONDict
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from telegram import Bot
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScope(TelegramObject):
|
||||||
|
"""Base class for objects that represent the scope to which bot commands are applied.
|
||||||
|
Currently, the following 7 scopes are supported:
|
||||||
|
|
||||||
|
* :class:`telegram.BotCommandScopeDefault`
|
||||||
|
* :class:`telegram.BotCommandScopeAllPrivateChats`
|
||||||
|
* :class:`telegram.BotCommandScopeAllGroupChats`
|
||||||
|
* :class:`telegram.BotCommandScopeAllChatAdministrators`
|
||||||
|
* :class:`telegram.BotCommandScopeChat`
|
||||||
|
* :class:`telegram.BotCommandScopeChatAdministrators`
|
||||||
|
* :class:`telegram.BotCommandScopeChatMember`
|
||||||
|
|
||||||
|
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||||
|
considered equal, if their :attr:`type` is equal. For subclasses with additional attributes,
|
||||||
|
the notion of equality is overridden.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Please see the `official docs`_ on how Telegram determines which commands to display.
|
||||||
|
|
||||||
|
.. _`official docs`: https://core.telegram.org/bots/api#determining-list-of-commands
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
type (:obj:`str`): Scope type.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ('type', '_id_attrs')
|
||||||
|
|
||||||
|
DEFAULT = constants.BOT_COMMAND_SCOPE_DEFAULT
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_DEFAULT`"""
|
||||||
|
ALL_PRIVATE_CHATS = constants.BOT_COMMAND_SCOPE_ALL_PRIVATE_CHATS
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_ALL_PRIVATE_CHATS`"""
|
||||||
|
ALL_GROUP_CHATS = constants.BOT_COMMAND_SCOPE_ALL_GROUP_CHATS
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_ALL_GROUP_CHATS`"""
|
||||||
|
ALL_CHAT_ADMINISTRATORS = constants.BOT_COMMAND_SCOPE_ALL_CHAT_ADMINISTRATORS
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_ALL_CHAT_ADMINISTRATORS`"""
|
||||||
|
CHAT = constants.BOT_COMMAND_SCOPE_CHAT
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_CHAT`"""
|
||||||
|
CHAT_ADMINISTRATORS = constants.BOT_COMMAND_SCOPE_CHAT_ADMINISTRATORS
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_CHAT_ADMINISTRATORS`"""
|
||||||
|
CHAT_MEMBER = constants.BOT_COMMAND_SCOPE_CHAT_MEMBER
|
||||||
|
""":const:`telegram.constants.BOT_COMMAND_SCOPE_CHAT_MEMBER`"""
|
||||||
|
|
||||||
|
def __init__(self, type: str, **_kwargs: Any):
|
||||||
|
self.type = type
|
||||||
|
self._id_attrs = (self.type,)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['BotCommandScope']:
|
||||||
|
"""Converts JSON data to the appropriate :class:`BotCommandScope` object, i.e. takes
|
||||||
|
care of selecting the correct subclass.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (Dict[:obj:`str`, ...]): The JSON data.
|
||||||
|
bot (:class:`telegram.Bot`): The bot associated with this object.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The Telegram object.
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
_class_mapping: Dict[str, Type['BotCommandScope']] = {
|
||||||
|
cls.DEFAULT: BotCommandScopeDefault,
|
||||||
|
cls.ALL_PRIVATE_CHATS: BotCommandScopeAllPrivateChats,
|
||||||
|
cls.ALL_GROUP_CHATS: BotCommandScopeAllGroupChats,
|
||||||
|
cls.ALL_CHAT_ADMINISTRATORS: BotCommandScopeAllChatAdministrators,
|
||||||
|
cls.CHAT: BotCommandScopeChat,
|
||||||
|
cls.CHAT_ADMINISTRATORS: BotCommandScopeChatAdministrators,
|
||||||
|
cls.CHAT_MEMBER: BotCommandScopeChatMember,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cls is BotCommandScope:
|
||||||
|
return _class_mapping.get(data['type'], cls)(**data, bot=bot)
|
||||||
|
return cls(**data)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeDefault(BotCommandScope):
|
||||||
|
"""Represents the default scope of bot commands. Default commands are used if no commands with
|
||||||
|
a `narrower scope`_ are specified for the user.
|
||||||
|
|
||||||
|
.. _`narrower scope`: https://core.telegram.org/bots/api#determining-list-of-commands
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.DEFAULT`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeAllPrivateChats(BotCommandScope):
|
||||||
|
"""Represents the scope of bot commands, covering all private chats.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.ALL_PRIVATE_CHATS`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.ALL_PRIVATE_CHATS)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeAllGroupChats(BotCommandScope):
|
||||||
|
"""Represents the scope of bot commands, covering all group and supergroup chats.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.ALL_GROUP_CHATS`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.ALL_GROUP_CHATS)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeAllChatAdministrators(BotCommandScope):
|
||||||
|
"""Represents the scope of bot commands, covering all group and supergroup chat administrators.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.ALL_CHAT_ADMINISTRATORS`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.ALL_CHAT_ADMINISTRATORS)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeChat(BotCommandScope):
|
||||||
|
"""Represents the scope of bot commands, covering a specific chat.
|
||||||
|
|
||||||
|
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||||
|
considered equal, if their :attr:`type` and :attr:`chat_id` are equal.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`str` | :obj:`int`): Unique identifier for the target chat or username of the
|
||||||
|
target supergroup (in the format ``@supergroupusername``)
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.CHAT`.
|
||||||
|
chat_id (:obj:`str` | :obj:`int`): Unique identifier for the target chat or username of the
|
||||||
|
target supergroup (in the format ``@supergroupusername``)
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ('chat_id',)
|
||||||
|
|
||||||
|
def __init__(self, chat_id: Union[str, int], **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.CHAT)
|
||||||
|
self.chat_id = (
|
||||||
|
chat_id if isinstance(chat_id, str) and chat_id.startswith('@') else int(chat_id)
|
||||||
|
)
|
||||||
|
self._id_attrs = (self.type, self.chat_id)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeChatAdministrators(BotCommandScope):
|
||||||
|
"""Represents the scope of bot commands, covering all administrators of a specific group or
|
||||||
|
supergroup chat.
|
||||||
|
|
||||||
|
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||||
|
considered equal, if their :attr:`type` and :attr:`chat_id` are equal.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`str` | :obj:`int`): Unique identifier for the target chat or username of the
|
||||||
|
target supergroup (in the format ``@supergroupusername``)
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.CHAT_ADMINISTRATORS`.
|
||||||
|
chat_id (:obj:`str` | :obj:`int`): Unique identifier for the target chat or username of the
|
||||||
|
target supergroup (in the format ``@supergroupusername``)
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ('chat_id',)
|
||||||
|
|
||||||
|
def __init__(self, chat_id: Union[str, int], **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.CHAT_ADMINISTRATORS)
|
||||||
|
self.chat_id = (
|
||||||
|
chat_id if isinstance(chat_id, str) and chat_id.startswith('@') else int(chat_id)
|
||||||
|
)
|
||||||
|
self._id_attrs = (self.type, self.chat_id)
|
||||||
|
|
||||||
|
|
||||||
|
class BotCommandScopeChatMember(BotCommandScope):
|
||||||
|
"""Represents the scope of bot commands, covering a specific member of a group or supergroup
|
||||||
|
chat.
|
||||||
|
|
||||||
|
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||||
|
considered equal, if their :attr:`type`, :attr:`chat_id` and :attr:`user_id` are equal.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`str` | :obj:`int`): Unique identifier for the target chat or username of the
|
||||||
|
target supergroup (in the format ``@supergroupusername``)
|
||||||
|
user_id (:obj:`int`): Unique identifier of the target user.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Scope type :attr:`telegram.BotCommandScope.CHAT_MEMBER`.
|
||||||
|
chat_id (:obj:`str` | :obj:`int`): Unique identifier for the target chat or username of the
|
||||||
|
target supergroup (in the format ``@supergroupusername``)
|
||||||
|
user_id (:obj:`int`): Unique identifier of the target user.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ('chat_id', 'user_id')
|
||||||
|
|
||||||
|
def __init__(self, chat_id: Union[str, int], user_id: int, **_kwargs: Any):
|
||||||
|
super().__init__(type=BotCommandScope.CHAT_MEMBER)
|
||||||
|
self.chat_id = (
|
||||||
|
chat_id if isinstance(chat_id, str) and chat_id.startswith('@') else int(chat_id)
|
||||||
|
)
|
||||||
|
self.user_id = int(user_id)
|
||||||
|
self._id_attrs = (self.type, self.chat_id, self.user_id)
|
|
@ -18,11 +18,13 @@
|
||||||
# You should have received a copy of the GNU Lesser Public License
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains an object that represents a Telegram Chat."""
|
"""This module contains an object that represents a Telegram Chat."""
|
||||||
|
import warnings
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import TYPE_CHECKING, List, Optional, ClassVar, Union, Tuple, Any
|
from typing import TYPE_CHECKING, List, Optional, ClassVar, Union, Tuple, Any
|
||||||
|
|
||||||
from telegram import ChatPhoto, TelegramObject, constants
|
from telegram import ChatPhoto, TelegramObject, constants
|
||||||
from telegram.utils.types import JSONDict, FileInput, ODVInput, DVInput
|
from telegram.utils.types import JSONDict, FileInput, ODVInput, DVInput
|
||||||
|
from telegram.utils.deprecate import TelegramDeprecationWarning
|
||||||
|
|
||||||
from .chatpermissions import ChatPermissions
|
from .chatpermissions import ChatPermissions
|
||||||
from .chatlocation import ChatLocation
|
from .chatlocation import ChatLocation
|
||||||
|
@ -318,19 +320,37 @@ class Chat(TelegramObject):
|
||||||
|
|
||||||
def get_members_count(
|
def get_members_count(
|
||||||
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
|
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
|
||||||
|
) -> int:
|
||||||
|
"""
|
||||||
|
Deprecated, use :func:`~telegram.Chat.get_member_count` instead.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
'`Chat.get_members_count` is deprecated. Use `Chat.get_member_count` instead.',
|
||||||
|
TelegramDeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.get_member_count(
|
||||||
|
timeout=timeout,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_member_count(
|
||||||
|
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
|
||||||
bot.get_chat_members_count(update.effective_chat.id, *args, **kwargs)
|
bot.get_chat_member_count(update.effective_chat.id, *args, **kwargs)
|
||||||
|
|
||||||
For the documentation of the arguments, please see
|
For the documentation of the arguments, please see
|
||||||
:meth:`telegram.Bot.get_chat_members_count`.
|
:meth:`telegram.Bot.get_chat_member_count`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`int`
|
:obj:`int`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self.bot.get_chat_members_count(
|
return self.bot.get_chat_member_count(
|
||||||
chat_id=self.id,
|
chat_id=self.id,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
|
@ -366,18 +386,45 @@ class Chat(TelegramObject):
|
||||||
until_date: Union[int, datetime] = None,
|
until_date: Union[int, datetime] = None,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
revoke_messages: bool = None,
|
revoke_messages: bool = None,
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Deprecated, use :func:`~telegram.Chat.ban_member` instead.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
'`Chat.kick_member` is deprecated. Use `Chat.ban_member` instead.',
|
||||||
|
TelegramDeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.ban_member(
|
||||||
|
user_id=user_id,
|
||||||
|
timeout=timeout,
|
||||||
|
until_date=until_date,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
revoke_messages=revoke_messages,
|
||||||
|
)
|
||||||
|
|
||||||
|
def ban_member(
|
||||||
|
self,
|
||||||
|
user_id: Union[str, int],
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
until_date: Union[int, datetime] = None,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
revoke_messages: bool = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
|
||||||
bot.kick_chat_member(update.effective_chat.id, *args, **kwargs)
|
bot.ban_chat_member(update.effective_chat.id, *args, **kwargs)
|
||||||
|
|
||||||
For the documentation of the arguments, please see
|
For the documentation of the arguments, please see
|
||||||
:meth:`telegram.Bot.kick_chat_member`.
|
:meth:`telegram.Bot.ban_chat_member`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`bool`: On success, :obj:`True` is returned.
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
"""
|
"""
|
||||||
return self.bot.kick_chat_member(
|
return self.bot.ban_chat_member(
|
||||||
chat_id=self.id,
|
chat_id=self.id,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains an object that represents a Telegram ChatMember."""
|
"""This module contains an object that represents a Telegram ChatMember."""
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Any, Optional, ClassVar
|
from typing import TYPE_CHECKING, Any, Optional, ClassVar, Dict, Type
|
||||||
|
|
||||||
from telegram import TelegramObject, User, constants
|
from telegram import TelegramObject, User, constants
|
||||||
from telegram.utils.helpers import from_timestamp, to_timestamp
|
from telegram.utils.helpers import from_timestamp, to_timestamp
|
||||||
|
@ -29,113 +29,239 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class ChatMember(TelegramObject):
|
class ChatMember(TelegramObject):
|
||||||
"""This object contains information about one member of a chat.
|
"""Base class for Telegram ChatMember Objects.
|
||||||
|
Currently, the following 6 types of chat members are supported:
|
||||||
|
|
||||||
|
* :class:`telegram.ChatMemberOwner`
|
||||||
|
* :class:`telegram.ChatMemberAdministrator`
|
||||||
|
* :class:`telegram.ChatMemberMember`
|
||||||
|
* :class:`telegram.ChatMemberRestricted`
|
||||||
|
* :class:`telegram.ChatMemberLeft`
|
||||||
|
* :class:`telegram.ChatMemberBanned`
|
||||||
|
|
||||||
Objects of this class are comparable in terms of equality. Two objects of this class are
|
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||||
considered equal, if their :attr:`user` and :attr:`status` are equal.
|
considered equal, if their :attr:`user` and :attr:`status` are equal.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
As of Bot API 5.3, :class:`ChatMember` is nothing but the base class for the subclasses
|
||||||
|
listed above and is no longer returned directly by :meth:`~telegram.Bot.get_chat`.
|
||||||
|
Therefore, most of the arguments and attributes were deprecated and you should no longer
|
||||||
|
use :class:`ChatMember` directly.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user (:class:`telegram.User`): Information about the user.
|
user (:class:`telegram.User`): Information about the user.
|
||||||
status (:obj:`str`): The member's status in the chat. Can be 'creator', 'administrator',
|
status (:obj:`str`): The member's status in the chat. Can be
|
||||||
'member', 'restricted', 'left' or 'kicked'.
|
:attr:`~telegram.ChatMember.ADMINISTRATOR`, :attr:`~telegram.ChatMember.CREATOR`,
|
||||||
|
:attr:`~telegram.ChatMember.KICKED`, :attr:`~telegram.ChatMember.LEFT`,
|
||||||
|
:attr:`~telegram.ChatMember.MEMBER` or :attr:`~telegram.ChatMember.RESTRICTED`.
|
||||||
custom_title (:obj:`str`, optional): Owner and administrators only.
|
custom_title (:obj:`str`, optional): Owner and administrators only.
|
||||||
Custom title for this user.
|
Custom title for this user.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
is_anonymous (:obj:`bool`, optional): Owner and administrators only. :obj:`True`, if the
|
is_anonymous (:obj:`bool`, optional): Owner and administrators only. :obj:`True`, if the
|
||||||
user's presence in the chat is hidden.
|
user's presence in the chat is hidden.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
until_date (:class:`datetime.datetime`, optional): Restricted and kicked only. Date when
|
until_date (:class:`datetime.datetime`, optional): Restricted and kicked only. Date when
|
||||||
restrictions will be lifted for this user.
|
restrictions will be lifted for this user.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_be_edited (:obj:`bool`, optional): Administrators only. :obj:`True`, if the bot is
|
can_be_edited (:obj:`bool`, optional): Administrators only. :obj:`True`, if the bot is
|
||||||
allowed to edit administrator privileges of that user.
|
allowed to edit administrator privileges of that user.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_manage_chat (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_manage_chat (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can access the chat event log, chat statistics, message statistics in
|
administrator can access the chat event log, chat statistics, message statistics in
|
||||||
channels, see channel members, see anonymous administrators in supergroups and ignore
|
channels, see channel members, see anonymous administrators in supergroups and ignore
|
||||||
slow mode. Implied by any other administrator privilege.
|
slow mode. Implied by any other administrator privilege.
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_manage_voice_chats (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_manage_voice_chats (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can manage voice chats.
|
administrator can manage voice chats.
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_change_info (:obj:`bool`, optional): Administrators and restricted only. :obj:`True`,
|
can_change_info (:obj:`bool`, optional): Administrators and restricted only. :obj:`True`,
|
||||||
if the user can change the chat title, photo and other settings.
|
if the user can change the chat title, photo and other settings.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_post_messages (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_post_messages (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can post in the channel, channels only.
|
administrator can post in the channel, channels only.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_edit_messages (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_edit_messages (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can edit messages of other users and can pin messages; channels only.
|
administrator can edit messages of other users and can pin messages; channels only.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_delete_messages (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_delete_messages (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can delete messages of other users.
|
administrator can delete messages of other users.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_invite_users (:obj:`bool`, optional): Administrators and restricted only. :obj:`True`,
|
can_invite_users (:obj:`bool`, optional): Administrators and restricted only. :obj:`True`,
|
||||||
if the user can invite new users to the chat.
|
if the user can invite new users to the chat.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_restrict_members (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_restrict_members (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can restrict, ban or unban chat members.
|
administrator can restrict, ban or unban chat members.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_pin_messages (:obj:`bool`, optional): Administrators and restricted only. :obj:`True`,
|
can_pin_messages (:obj:`bool`, optional): Administrators and restricted only. :obj:`True`,
|
||||||
if the user can pin messages, groups and supergroups only.
|
if the user can pin messages, groups and supergroups only.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_promote_members (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
can_promote_members (:obj:`bool`, optional): Administrators only. :obj:`True`, if the
|
||||||
administrator can add new administrators with a subset of his own privileges or demote
|
administrator can add new administrators with a subset of his own privileges or demote
|
||||||
administrators that he has promoted, directly or indirectly (promoted by administrators
|
administrators that he has promoted, directly or indirectly (promoted by administrators
|
||||||
that were appointed by the user).
|
that were appointed by the user).
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
is_member (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user is a member of
|
is_member (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user is a member of
|
||||||
the chat at the moment of the request.
|
the chat at the moment of the request.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_messages (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user can
|
can_send_messages (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user can
|
||||||
send text messages, contacts, locations and venues.
|
send text messages, contacts, locations and venues.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_media_messages (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user
|
can_send_media_messages (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user
|
||||||
can send audios, documents, photos, videos, video notes and voice notes.
|
can send audios, documents, photos, videos, video notes and voice notes.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_polls (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user is
|
can_send_polls (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user is
|
||||||
allowed to send polls.
|
allowed to send polls.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_other_messages (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user
|
can_send_other_messages (:obj:`bool`, optional): Restricted only. :obj:`True`, if the user
|
||||||
can send animations, games, stickers and use inline bots.
|
can send animations, games, stickers and use inline bots.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_add_web_page_previews (:obj:`bool`, optional): Restricted only. :obj:`True`, if user
|
can_add_web_page_previews (:obj:`bool`, optional): Restricted only. :obj:`True`, if user
|
||||||
may add web page previews to his messages.
|
may add web page previews to his messages.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
user (:class:`telegram.User`): Information about the user.
|
user (:class:`telegram.User`): Information about the user.
|
||||||
status (:obj:`str`): The member's status in the chat.
|
status (:obj:`str`): The member's status in the chat.
|
||||||
custom_title (:obj:`str`): Optional. Custom title for owner and administrators.
|
custom_title (:obj:`str`): Optional. Custom title for owner and administrators.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
is_anonymous (:obj:`bool`): Optional. :obj:`True`, if the user's presence in the chat is
|
is_anonymous (:obj:`bool`): Optional. :obj:`True`, if the user's presence in the chat is
|
||||||
hidden.
|
hidden.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
until_date (:class:`datetime.datetime`): Optional. Date when restrictions will be lifted
|
until_date (:class:`datetime.datetime`): Optional. Date when restrictions will be lifted
|
||||||
for this user.
|
for this user.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_be_edited (:obj:`bool`): Optional. If the bot is allowed to edit administrator
|
can_be_edited (:obj:`bool`): Optional. If the bot is allowed to edit administrator
|
||||||
privileges of that user.
|
privileges of that user.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_manage_chat (:obj:`bool`): Optional. If the administrator can access the chat event
|
can_manage_chat (:obj:`bool`): Optional. If the administrator can access the chat event
|
||||||
log, chat statistics, message statistics in channels, see channel members, see
|
log, chat statistics, message statistics in channels, see channel members, see
|
||||||
anonymous administrators in supergroups and ignore slow mode.
|
anonymous administrators in supergroups and ignore slow mode.
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_manage_voice_chats (:obj:`bool`): Optional. if the administrator can manage
|
can_manage_voice_chats (:obj:`bool`): Optional. if the administrator can manage
|
||||||
voice chats.
|
voice chats.
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_change_info (:obj:`bool`): Optional. If the user can change the chat title, photo and
|
can_change_info (:obj:`bool`): Optional. If the user can change the chat title, photo and
|
||||||
other settings.
|
other settings.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_post_messages (:obj:`bool`): Optional. If the administrator can post in the channel.
|
can_post_messages (:obj:`bool`): Optional. If the administrator can post in the channel.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_edit_messages (:obj:`bool`): Optional. If the administrator can edit messages of other
|
can_edit_messages (:obj:`bool`): Optional. If the administrator can edit messages of other
|
||||||
users.
|
users.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_delete_messages (:obj:`bool`): Optional. If the administrator can delete messages of
|
can_delete_messages (:obj:`bool`): Optional. If the administrator can delete messages of
|
||||||
other users.
|
other users.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_invite_users (:obj:`bool`): Optional. If the user can invite new users to the chat.
|
can_invite_users (:obj:`bool`): Optional. If the user can invite new users to the chat.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_restrict_members (:obj:`bool`): Optional. If the administrator can restrict, ban or
|
can_restrict_members (:obj:`bool`): Optional. If the administrator can restrict, ban or
|
||||||
unban chat members.
|
unban chat members.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_pin_messages (:obj:`bool`): Optional. If the user can pin messages.
|
can_pin_messages (:obj:`bool`): Optional. If the user can pin messages.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_promote_members (:obj:`bool`): Optional. If the administrator can add new
|
can_promote_members (:obj:`bool`): Optional. If the administrator can add new
|
||||||
administrators.
|
administrators.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
is_member (:obj:`bool`): Optional. Restricted only. :obj:`True`, if the user is a member of
|
is_member (:obj:`bool`): Optional. Restricted only. :obj:`True`, if the user is a member of
|
||||||
the chat at the moment of the request.
|
the chat at the moment of the request.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_messages (:obj:`bool`): Optional. If the user can send text messages, contacts,
|
can_send_messages (:obj:`bool`): Optional. If the user can send text messages, contacts,
|
||||||
locations and venues.
|
locations and venues.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_media_messages (:obj:`bool`): Optional. If the user can send media messages,
|
can_send_media_messages (:obj:`bool`): Optional. If the user can send media messages,
|
||||||
implies can_send_messages.
|
implies can_send_messages.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
|
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
|
||||||
send polls.
|
send polls.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_send_other_messages (:obj:`bool`): Optional. If the user can send animations, games,
|
can_send_other_messages (:obj:`bool`): Optional. If the user can send animations, games,
|
||||||
stickers and use inline bots, implies can_send_media_messages.
|
stickers and use inline bots, implies can_send_media_messages.
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
can_add_web_page_previews (:obj:`bool`): Optional. If user may add web page previews to his
|
can_add_web_page_previews (:obj:`bool`): Optional. If user may add web page previews to his
|
||||||
messages, implies can_send_media_messages
|
messages, implies can_send_media_messages
|
||||||
|
|
||||||
|
.. deprecated:: 13.7
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
|
@ -242,6 +368,17 @@ class ChatMember(TelegramObject):
|
||||||
data['user'] = User.de_json(data.get('user'), bot)
|
data['user'] = User.de_json(data.get('user'), bot)
|
||||||
data['until_date'] = from_timestamp(data.get('until_date', None))
|
data['until_date'] = from_timestamp(data.get('until_date', None))
|
||||||
|
|
||||||
|
_class_mapping: Dict[str, Type['ChatMember']] = {
|
||||||
|
cls.CREATOR: ChatMemberOwner,
|
||||||
|
cls.ADMINISTRATOR: ChatMemberAdministrator,
|
||||||
|
cls.MEMBER: ChatMemberMember,
|
||||||
|
cls.RESTRICTED: ChatMemberRestricted,
|
||||||
|
cls.LEFT: ChatMemberLeft,
|
||||||
|
cls.KICKED: ChatMemberBanned,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cls is ChatMember:
|
||||||
|
return _class_mapping.get(data['status'], cls)(**data, bot=bot)
|
||||||
return cls(**data)
|
return cls(**data)
|
||||||
|
|
||||||
def to_dict(self) -> JSONDict:
|
def to_dict(self) -> JSONDict:
|
||||||
|
@ -251,3 +388,328 @@ class ChatMember(TelegramObject):
|
||||||
data['until_date'] = to_timestamp(self.until_date)
|
data['until_date'] = to_timestamp(self.until_date)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMemberOwner(ChatMember):
|
||||||
|
"""
|
||||||
|
Represents a chat member that owns the chat
|
||||||
|
and has all administrator privileges.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
custom_title (:obj:`str`, optional): Custom title for this user.
|
||||||
|
is_anonymous (:obj:`bool`, optional): :obj:`True`, if the
|
||||||
|
user's presence in the chat is hidden.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
status (:obj:`str`): The member's status in the chat,
|
||||||
|
always :attr:`telegram.ChatMember.CREATOR`.
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
custom_title (:obj:`str`): Optional. Custom title for
|
||||||
|
this user.
|
||||||
|
is_anonymous (:obj:`bool`): Optional. :obj:`True`, if the user's
|
||||||
|
presence in the chat is hidden.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
user: User,
|
||||||
|
custom_title: str = None,
|
||||||
|
is_anonymous: bool = None,
|
||||||
|
**_kwargs: Any,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
status=ChatMember.CREATOR,
|
||||||
|
user=user,
|
||||||
|
custom_title=custom_title,
|
||||||
|
is_anonymous=is_anonymous,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMemberAdministrator(ChatMember):
|
||||||
|
"""
|
||||||
|
Represents a chat member that has some additional privileges.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
can_be_edited (:obj:`bool`, optional): :obj:`True`, if the bot
|
||||||
|
is allowed to edit administrator privileges of that user.
|
||||||
|
custom_title (:obj:`str`, optional): Custom title for this user.
|
||||||
|
is_anonymous (:obj:`bool`, optional): :obj:`True`, if the user's
|
||||||
|
presence in the chat is hidden.
|
||||||
|
can_manage_chat (:obj:`bool`, optional): :obj:`True`, if the administrator
|
||||||
|
can access the chat event log, chat statistics, message statistics in
|
||||||
|
channels, see channel members, see anonymous administrators in supergroups
|
||||||
|
and ignore slow mode. Implied by any other administrator privilege.
|
||||||
|
can_post_messages (:obj:`bool`, optional): :obj:`True`, if the
|
||||||
|
administrator can post in the channel, channels only.
|
||||||
|
can_edit_messages (:obj:`bool`, optional): :obj:`True`, if the
|
||||||
|
administrator can edit messages of other users and can pin
|
||||||
|
messages; channels only.
|
||||||
|
can_delete_messages (:obj:`bool`, optional): :obj:`True`, if the
|
||||||
|
administrator can delete messages of other users.
|
||||||
|
can_manage_voice_chats (:obj:`bool`, optional): :obj:`True`, if the
|
||||||
|
administrator can manage voice chats.
|
||||||
|
can_restrict_members (:obj:`bool`, optional): :obj:`True`, if the
|
||||||
|
administrator can restrict, ban or unban chat members.
|
||||||
|
can_promote_members (:obj:`bool`, optional): :obj:`True`, if the administrator
|
||||||
|
can add new administrators with a subset of his own privileges or demote
|
||||||
|
administrators that he has promoted, directly or indirectly (promoted by
|
||||||
|
administrators that were appointed by the user).
|
||||||
|
can_change_info (:obj:`bool`, optional): :obj:`True`, if the user can change
|
||||||
|
the chat title, photo and other settings.
|
||||||
|
can_invite_users (:obj:`bool`, optional): :obj:`True`, if the user can invite
|
||||||
|
new users to the chat.
|
||||||
|
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
|
||||||
|
to pin messages; groups and supergroups only.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
status (:obj:`str`): The member's status in the chat,
|
||||||
|
always :attr:`telegram.ChatMember.ADMINISTRATOR`.
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
can_be_edited (:obj:`bool`): Optional. :obj:`True`, if the bot
|
||||||
|
is allowed to edit administrator privileges of that user.
|
||||||
|
custom_title (:obj:`str`): Optional. Custom title for this user.
|
||||||
|
is_anonymous (:obj:`bool`): Optional. :obj:`True`, if the user's
|
||||||
|
presence in the chat is hidden.
|
||||||
|
can_manage_chat (:obj:`bool`): Optional. :obj:`True`, if the administrator
|
||||||
|
can access the chat event log, chat statistics, message statistics in
|
||||||
|
channels, see channel members, see anonymous administrators in supergroups
|
||||||
|
and ignore slow mode. Implied by any other administrator privilege.
|
||||||
|
can_post_messages (:obj:`bool`): Optional. :obj:`True`, if the
|
||||||
|
administrator can post in the channel, channels only.
|
||||||
|
can_edit_messages (:obj:`bool`): Optional. :obj:`True`, if the
|
||||||
|
administrator can edit messages of other users and can pin
|
||||||
|
messages; channels only.
|
||||||
|
can_delete_messages (:obj:`bool`): Optional. :obj:`True`, if the
|
||||||
|
administrator can delete messages of other users.
|
||||||
|
can_manage_voice_chats (:obj:`bool`): Optional. :obj:`True`, if the
|
||||||
|
administrator can manage voice chats.
|
||||||
|
can_restrict_members (:obj:`bool`): Optional. :obj:`True`, if the
|
||||||
|
administrator can restrict, ban or unban chat members.
|
||||||
|
can_promote_members (:obj:`bool`): Optional. :obj:`True`, if the administrator
|
||||||
|
can add new administrators with a subset of his own privileges or demote
|
||||||
|
administrators that he has promoted, directly or indirectly (promoted by
|
||||||
|
administrators that were appointed by the user).
|
||||||
|
can_change_info (:obj:`bool`): Optional. :obj:`True`, if the user can change
|
||||||
|
the chat title, photo and other settings.
|
||||||
|
can_invite_users (:obj:`bool`): Optional. :obj:`True`, if the user can invite
|
||||||
|
new users to the chat.
|
||||||
|
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
|
||||||
|
to pin messages; groups and supergroups only.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
user: User,
|
||||||
|
can_be_edited: bool = None,
|
||||||
|
custom_title: str = None,
|
||||||
|
is_anonymous: bool = None,
|
||||||
|
can_manage_chat: bool = None,
|
||||||
|
can_post_messages: bool = None,
|
||||||
|
can_edit_messages: bool = None,
|
||||||
|
can_delete_messages: bool = None,
|
||||||
|
can_manage_voice_chats: bool = None,
|
||||||
|
can_restrict_members: bool = None,
|
||||||
|
can_promote_members: bool = None,
|
||||||
|
can_change_info: bool = None,
|
||||||
|
can_invite_users: bool = None,
|
||||||
|
can_pin_messages: bool = None,
|
||||||
|
**_kwargs: Any,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
status=ChatMember.ADMINISTRATOR,
|
||||||
|
user=user,
|
||||||
|
can_be_edited=can_be_edited,
|
||||||
|
custom_title=custom_title,
|
||||||
|
is_anonymous=is_anonymous,
|
||||||
|
can_manage_chat=can_manage_chat,
|
||||||
|
can_post_messages=can_post_messages,
|
||||||
|
can_edit_messages=can_edit_messages,
|
||||||
|
can_delete_messages=can_delete_messages,
|
||||||
|
can_manage_voice_chats=can_manage_voice_chats,
|
||||||
|
can_restrict_members=can_restrict_members,
|
||||||
|
can_promote_members=can_promote_members,
|
||||||
|
can_change_info=can_change_info,
|
||||||
|
can_invite_users=can_invite_users,
|
||||||
|
can_pin_messages=can_pin_messages,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMemberMember(ChatMember):
|
||||||
|
"""
|
||||||
|
Represents a chat member that has no additional
|
||||||
|
privileges or restrictions.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
status (:obj:`str`): The member's status in the chat,
|
||||||
|
always :attr:`telegram.ChatMember.MEMBER`.
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, user: User, **_kwargs: Any):
|
||||||
|
super().__init__(status=ChatMember.MEMBER, user=user)
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMemberRestricted(ChatMember):
|
||||||
|
"""
|
||||||
|
Represents a chat member that is under certain restrictions
|
||||||
|
in the chat. Supergroups only.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
is_member (:obj:`bool`, optional): :obj:`True`, if the user is a
|
||||||
|
member of the chat at the moment of the request.
|
||||||
|
can_change_info (:obj:`bool`, optional): :obj:`True`, if the user can change
|
||||||
|
the chat title, photo and other settings.
|
||||||
|
can_invite_users (:obj:`bool`, optional): :obj:`True`, if the user can invite
|
||||||
|
new users to the chat.
|
||||||
|
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
|
||||||
|
to pin messages; groups and supergroups only.
|
||||||
|
can_send_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
|
||||||
|
to send text messages, contacts, locations and venues.
|
||||||
|
can_send_media_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
|
||||||
|
to send audios, documents, photos, videos, video notes and voice notes.
|
||||||
|
can_send_polls (:obj:`bool`, optional): :obj:`True`, if the user is allowed
|
||||||
|
to send polls.
|
||||||
|
can_send_other_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
|
||||||
|
to send animations, games, stickers and use inline bots.
|
||||||
|
can_add_web_page_previews (:obj:`bool`, optional): :obj:`True`, if the user is
|
||||||
|
allowed to add web page previews to their messages.
|
||||||
|
until_date (:class:`datetime.datetime`, optional): Date when restrictions
|
||||||
|
will be lifted for this user.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
status (:obj:`str`): The member's status in the chat,
|
||||||
|
always :attr:`telegram.ChatMember.RESTRICTED`.
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
is_member (:obj:`bool`): Optional. :obj:`True`, if the user is a
|
||||||
|
member of the chat at the moment of the request.
|
||||||
|
can_change_info (:obj:`bool`): Optional. :obj:`True`, if the user can change
|
||||||
|
the chat title, photo and other settings.
|
||||||
|
can_invite_users (:obj:`bool`): Optional. :obj:`True`, if the user can invite
|
||||||
|
new users to the chat.
|
||||||
|
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
|
||||||
|
to pin messages; groups and supergroups only.
|
||||||
|
can_send_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
|
||||||
|
to send text messages, contacts, locations and venues.
|
||||||
|
can_send_media_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
|
||||||
|
to send audios, documents, photos, videos, video notes and voice notes.
|
||||||
|
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
|
||||||
|
to send polls.
|
||||||
|
can_send_other_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
|
||||||
|
to send animations, games, stickers and use inline bots.
|
||||||
|
can_add_web_page_previews (:obj:`bool`): Optional. :obj:`True`, if the user is
|
||||||
|
allowed to add web page previews to their messages.
|
||||||
|
until_date (:class:`datetime.datetime`): Optional. Date when restrictions
|
||||||
|
will be lifted for this user.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
user: User,
|
||||||
|
is_member: bool = None,
|
||||||
|
can_change_info: bool = None,
|
||||||
|
can_invite_users: bool = None,
|
||||||
|
can_pin_messages: bool = None,
|
||||||
|
can_send_messages: bool = None,
|
||||||
|
can_send_media_messages: bool = None,
|
||||||
|
can_send_polls: bool = None,
|
||||||
|
can_send_other_messages: bool = None,
|
||||||
|
can_add_web_page_previews: bool = None,
|
||||||
|
until_date: datetime.datetime = None,
|
||||||
|
**_kwargs: Any,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
status=ChatMember.RESTRICTED,
|
||||||
|
user=user,
|
||||||
|
is_member=is_member,
|
||||||
|
can_change_info=can_change_info,
|
||||||
|
can_invite_users=can_invite_users,
|
||||||
|
can_pin_messages=can_pin_messages,
|
||||||
|
can_send_messages=can_send_messages,
|
||||||
|
can_send_media_messages=can_send_media_messages,
|
||||||
|
can_send_polls=can_send_polls,
|
||||||
|
can_send_other_messages=can_send_other_messages,
|
||||||
|
can_add_web_page_previews=can_add_web_page_previews,
|
||||||
|
until_date=until_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMemberLeft(ChatMember):
|
||||||
|
"""
|
||||||
|
Represents a chat member that isn't currently a member of the chat,
|
||||||
|
but may join it themselves.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
status (:obj:`str`): The member's status in the chat,
|
||||||
|
always :attr:`telegram.ChatMember.LEFT`.
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, user: User, **_kwargs: Any):
|
||||||
|
super().__init__(status=ChatMember.LEFT, user=user)
|
||||||
|
|
||||||
|
|
||||||
|
class ChatMemberBanned(ChatMember):
|
||||||
|
"""
|
||||||
|
Represents a chat member that was banned in the chat and
|
||||||
|
can't return to the chat or view chat messages.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
until_date (:class:`datetime.datetime`, optional): Date when restrictions
|
||||||
|
will be lifted for this user.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
status (:obj:`str`): The member's status in the chat,
|
||||||
|
always :attr:`telegram.ChatMember.KICKED`.
|
||||||
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
until_date (:class:`datetime.datetime`): Optional. Date when restrictions
|
||||||
|
will be lifted for this user.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
user: User,
|
||||||
|
until_date: datetime.datetime = None,
|
||||||
|
**_kwargs: Any,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
status=ChatMember.KICKED,
|
||||||
|
user=user,
|
||||||
|
until_date=until_date,
|
||||||
|
)
|
||||||
|
|
|
@ -21,7 +21,7 @@ The following constants were extracted from the
|
||||||
`Telegram Bots API <https://core.telegram.org/bots/api>`_.
|
`Telegram Bots API <https://core.telegram.org/bots/api>`_.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
BOT_API_VERSION (:obj:`str`): `5.2`. Telegram Bot API version supported by this
|
BOT_API_VERSION (:obj:`str`): `5.3`. Telegram Bot API version supported by this
|
||||||
version of `python-telegram-bot`. Also available as ``telegram.bot_api_version``.
|
version of `python-telegram-bot`. Also available as ``telegram.bot_api_version``.
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
@ -205,10 +205,35 @@ Attributes:
|
||||||
|
|
||||||
.. versionadded:: 13.5
|
.. versionadded:: 13.5
|
||||||
|
|
||||||
|
:class:`telegram.BotCommandScope`:
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
BOT_COMMAND_SCOPE_DEFAULT (:obj:`str`): ``'default'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
BOT_COMMAND_SCOPE_ALL_PRIVATE_CHATS (:obj:`str`): ``'all_private_chats'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
BOT_COMMAND_SCOPE_ALL_GROUP_CHATS (:obj:`str`): ``'all_group_chats'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
BOT_COMMAND_SCOPE_ALL_CHAT_ADMINISTRATORS (:obj:`str`): ``'all_chat_administrators'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
BOT_COMMAND_SCOPE_CHAT (:obj:`str`): ``'chat'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
BOT_COMMAND_SCOPE_CHAT_ADMINISTRATORS (:obj:`str`): ``'chat_administrators'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
BOT_COMMAND_SCOPE_CHAT_MEMBER (:obj:`str`): ``'chat_member'``
|
||||||
|
|
||||||
|
..versionadded:: 13.7
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
BOT_API_VERSION: str = '5.2'
|
BOT_API_VERSION: str = '5.3'
|
||||||
MAX_MESSAGE_LENGTH: int = 4096
|
MAX_MESSAGE_LENGTH: int = 4096
|
||||||
MAX_CAPTION_LENGTH: int = 1024
|
MAX_CAPTION_LENGTH: int = 1024
|
||||||
ANONYMOUS_ADMIN_ID: int = 1087968824
|
ANONYMOUS_ADMIN_ID: int = 1087968824
|
||||||
|
@ -343,3 +368,11 @@ UPDATE_ALL_TYPES = [
|
||||||
UPDATE_MY_CHAT_MEMBER,
|
UPDATE_MY_CHAT_MEMBER,
|
||||||
UPDATE_CHAT_MEMBER,
|
UPDATE_CHAT_MEMBER,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
BOT_COMMAND_SCOPE_DEFAULT = 'default'
|
||||||
|
BOT_COMMAND_SCOPE_ALL_PRIVATE_CHATS = 'all_private_chats'
|
||||||
|
BOT_COMMAND_SCOPE_ALL_GROUP_CHATS = 'all_group_chats'
|
||||||
|
BOT_COMMAND_SCOPE_ALL_CHAT_ADMINISTRATORS = 'all_chat_administrators'
|
||||||
|
BOT_COMMAND_SCOPE_CHAT = 'chat'
|
||||||
|
BOT_COMMAND_SCOPE_CHAT_ADMINISTRATORS = 'chat_administrators'
|
||||||
|
BOT_COMMAND_SCOPE_CHAT_MEMBER = 'chat_member'
|
||||||
|
|
|
@ -32,7 +32,7 @@ from .dispatcher import Dispatcher, DispatcherHandlerStop, run_async
|
||||||
# try-except is just here in case the __init__ is called twice (like in the tests)
|
# try-except is just here in case the __init__ is called twice (like in the tests)
|
||||||
# this block is also the reason for the pylint-ignore at the top of the file
|
# this block is also the reason for the pylint-ignore at the top of the file
|
||||||
try:
|
try:
|
||||||
del Dispatcher.__slots__ # type: ignore[has-type]
|
del Dispatcher.__slots__
|
||||||
except AttributeError as exc:
|
except AttributeError as exc:
|
||||||
if str(exc) == '__slots__':
|
if str(exc) == '__slots__':
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -37,25 +37,42 @@ class ForceReply(ReplyMarkup):
|
||||||
selective (:obj:`bool`, optional): Use this parameter if you want to force reply from
|
selective (:obj:`bool`, optional): Use this parameter if you want to force reply from
|
||||||
specific users only. Targets:
|
specific users only. Targets:
|
||||||
|
|
||||||
1) Users that are @mentioned in the text of the Message object.
|
1) Users that are @mentioned in the :attr:`~telegram.Message.text` of the
|
||||||
2) If the bot's message is a reply (has reply_to_message_id), sender of the
|
:class:`telegram.Message` object.
|
||||||
|
2) If the bot's message is a reply (has ``reply_to_message_id``), sender of the
|
||||||
original message.
|
original message.
|
||||||
|
|
||||||
|
input_field_placeholder (:obj:`str`, optional): The placeholder to be shown in the input
|
||||||
|
field when the reply is active; 1-64 characters.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
force_reply (:obj:`True`): Shows reply interface to the user, as if they manually selected
|
force_reply (:obj:`True`): Shows reply interface to the user, as if they manually selected
|
||||||
the bots message and tapped 'Reply'.
|
the bots message and tapped 'Reply'.
|
||||||
selective (:obj:`bool`): Optional. Force reply from specific users only.
|
selective (:obj:`bool`): Optional. Force reply from specific users only.
|
||||||
|
input_field_placeholder (:obj:`str`): Optional. The placeholder shown in the input
|
||||||
|
field when the reply is active.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('selective', 'force_reply', '_id_attrs')
|
__slots__ = ('selective', 'force_reply', 'input_field_placeholder', '_id_attrs')
|
||||||
|
|
||||||
def __init__(self, force_reply: bool = True, selective: bool = False, **_kwargs: Any):
|
def __init__(
|
||||||
|
self,
|
||||||
|
force_reply: bool = True,
|
||||||
|
selective: bool = False,
|
||||||
|
input_field_placeholder: str = None,
|
||||||
|
**_kwargs: Any,
|
||||||
|
):
|
||||||
# Required
|
# Required
|
||||||
self.force_reply = bool(force_reply)
|
self.force_reply = bool(force_reply)
|
||||||
# Optionals
|
# Optionals
|
||||||
self.selective = bool(selective)
|
self.selective = bool(selective)
|
||||||
|
self.input_field_placeholder = input_field_placeholder
|
||||||
|
|
||||||
self._id_attrs = (self.selective,)
|
self._id_attrs = (self.selective,)
|
||||||
|
|
|
@ -48,12 +48,18 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
selective (:obj:`bool`, optional): Use this parameter if you want to show the keyboard to
|
selective (:obj:`bool`, optional): Use this parameter if you want to show the keyboard to
|
||||||
specific users only. Targets:
|
specific users only. Targets:
|
||||||
|
|
||||||
1) Users that are @mentioned in the text of the Message object.
|
1) Users that are @mentioned in the :attr:`~telegram.Message.text` of the
|
||||||
|
:class:`telegram.Message` object.
|
||||||
2) If the bot's message is a reply (has ``reply_to_message_id``), sender of the
|
2) If the bot's message is a reply (has ``reply_to_message_id``), sender of the
|
||||||
original message.
|
original message.
|
||||||
|
|
||||||
Defaults to :obj:`False`.
|
Defaults to :obj:`False`.
|
||||||
|
|
||||||
|
input_field_placeholder (:obj:`str`, optional): The placeholder to be shown in the input
|
||||||
|
field when the keyboard is active; 1-64 characters.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -62,10 +68,21 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
one_time_keyboard (:obj:`bool`): Optional. Requests clients to hide the keyboard as soon as
|
one_time_keyboard (:obj:`bool`): Optional. Requests clients to hide the keyboard as soon as
|
||||||
it's been used.
|
it's been used.
|
||||||
selective (:obj:`bool`): Optional. Show the keyboard to specific users only.
|
selective (:obj:`bool`): Optional. Show the keyboard to specific users only.
|
||||||
|
input_field_placeholder (:obj:`str`): Optional. The placeholder shown in the input
|
||||||
|
field when the reply is active.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ('selective', 'keyboard', 'resize_keyboard', 'one_time_keyboard', '_id_attrs')
|
__slots__ = (
|
||||||
|
'selective',
|
||||||
|
'keyboard',
|
||||||
|
'resize_keyboard',
|
||||||
|
'one_time_keyboard',
|
||||||
|
'input_field_placeholder',
|
||||||
|
'_id_attrs',
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -73,6 +90,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard: bool = False,
|
resize_keyboard: bool = False,
|
||||||
one_time_keyboard: bool = False,
|
one_time_keyboard: bool = False,
|
||||||
selective: bool = False,
|
selective: bool = False,
|
||||||
|
input_field_placeholder: str = None,
|
||||||
**_kwargs: Any,
|
**_kwargs: Any,
|
||||||
):
|
):
|
||||||
# Required
|
# Required
|
||||||
|
@ -90,6 +108,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
self.resize_keyboard = bool(resize_keyboard)
|
self.resize_keyboard = bool(resize_keyboard)
|
||||||
self.one_time_keyboard = bool(one_time_keyboard)
|
self.one_time_keyboard = bool(one_time_keyboard)
|
||||||
self.selective = bool(selective)
|
self.selective = bool(selective)
|
||||||
|
self.input_field_placeholder = input_field_placeholder
|
||||||
|
|
||||||
self._id_attrs = (self.keyboard,)
|
self._id_attrs = (self.keyboard,)
|
||||||
|
|
||||||
|
@ -109,6 +128,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard: bool = False,
|
resize_keyboard: bool = False,
|
||||||
one_time_keyboard: bool = False,
|
one_time_keyboard: bool = False,
|
||||||
selective: bool = False,
|
selective: bool = False,
|
||||||
|
input_field_placeholder: str = None,
|
||||||
**kwargs: object,
|
**kwargs: object,
|
||||||
) -> 'ReplyKeyboardMarkup':
|
) -> 'ReplyKeyboardMarkup':
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
@ -133,10 +153,15 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
to specific users only. Targets:
|
to specific users only. Targets:
|
||||||
|
|
||||||
1) Users that are @mentioned in the text of the Message object.
|
1) Users that are @mentioned in the text of the Message object.
|
||||||
2) If the bot's message is a reply (has reply_to_message_id), sender of the
|
2) If the bot's message is a reply (has ``reply_to_message_id``), sender of the
|
||||||
original message.
|
original message.
|
||||||
|
|
||||||
Defaults to :obj:`False`.
|
Defaults to :obj:`False`.
|
||||||
|
|
||||||
|
input_field_placeholder (:obj:`str`): Optional. The placeholder shown in the input
|
||||||
|
field when the reply is active.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||||
"""
|
"""
|
||||||
return cls(
|
return cls(
|
||||||
|
@ -144,6 +169,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard=resize_keyboard,
|
resize_keyboard=resize_keyboard,
|
||||||
one_time_keyboard=one_time_keyboard,
|
one_time_keyboard=one_time_keyboard,
|
||||||
selective=selective,
|
selective=selective,
|
||||||
|
input_field_placeholder=input_field_placeholder,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -154,6 +180,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard: bool = False,
|
resize_keyboard: bool = False,
|
||||||
one_time_keyboard: bool = False,
|
one_time_keyboard: bool = False,
|
||||||
selective: bool = False,
|
selective: bool = False,
|
||||||
|
input_field_placeholder: str = None,
|
||||||
**kwargs: object,
|
**kwargs: object,
|
||||||
) -> 'ReplyKeyboardMarkup':
|
) -> 'ReplyKeyboardMarkup':
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
@ -178,10 +205,15 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
to specific users only. Targets:
|
to specific users only. Targets:
|
||||||
|
|
||||||
1) Users that are @mentioned in the text of the Message object.
|
1) Users that are @mentioned in the text of the Message object.
|
||||||
2) If the bot's message is a reply (has reply_to_message_id), sender of the
|
2) If the bot's message is a reply (has ``reply_to_message_id``), sender of the
|
||||||
original message.
|
original message.
|
||||||
|
|
||||||
Defaults to :obj:`False`.
|
Defaults to :obj:`False`.
|
||||||
|
|
||||||
|
input_field_placeholder (:obj:`str`): Optional. The placeholder shown in the input
|
||||||
|
field when the reply is active.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -190,6 +222,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard=resize_keyboard,
|
resize_keyboard=resize_keyboard,
|
||||||
one_time_keyboard=one_time_keyboard,
|
one_time_keyboard=one_time_keyboard,
|
||||||
selective=selective,
|
selective=selective,
|
||||||
|
input_field_placeholder=input_field_placeholder,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -200,6 +233,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard: bool = False,
|
resize_keyboard: bool = False,
|
||||||
one_time_keyboard: bool = False,
|
one_time_keyboard: bool = False,
|
||||||
selective: bool = False,
|
selective: bool = False,
|
||||||
|
input_field_placeholder: str = None,
|
||||||
**kwargs: object,
|
**kwargs: object,
|
||||||
) -> 'ReplyKeyboardMarkup':
|
) -> 'ReplyKeyboardMarkup':
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
@ -224,10 +258,15 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
to specific users only. Targets:
|
to specific users only. Targets:
|
||||||
|
|
||||||
1) Users that are @mentioned in the text of the Message object.
|
1) Users that are @mentioned in the text of the Message object.
|
||||||
2) If the bot's message is a reply (has reply_to_message_id), sender of the
|
2) If the bot's message is a reply (has ``reply_to_message_id``), sender of the
|
||||||
original message.
|
original message.
|
||||||
|
|
||||||
Defaults to :obj:`False`.
|
Defaults to :obj:`False`.
|
||||||
|
|
||||||
|
input_field_placeholder (:obj:`str`): Optional. The placeholder shown in the input
|
||||||
|
field when the reply is active.
|
||||||
|
|
||||||
|
.. versionadded:: 13.7
|
||||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -237,6 +276,7 @@ class ReplyKeyboardMarkup(ReplyMarkup):
|
||||||
resize_keyboard=resize_keyboard,
|
resize_keyboard=resize_keyboard,
|
||||||
one_time_keyboard=one_time_keyboard,
|
one_time_keyboard=one_time_keyboard,
|
||||||
selective=selective,
|
selective=selective,
|
||||||
|
input_field_placeholder=input_field_placeholder,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ from telegram import (
|
||||||
Chat,
|
Chat,
|
||||||
InlineQueryResultVoice,
|
InlineQueryResultVoice,
|
||||||
PollOption,
|
PollOption,
|
||||||
|
BotCommandScopeChat,
|
||||||
)
|
)
|
||||||
from telegram.constants import MAX_INLINE_QUERY_RESULTS
|
from telegram.constants import MAX_INLINE_QUERY_RESULTS
|
||||||
from telegram.ext import ExtBot, Defaults
|
from telegram.ext import ExtBot, Defaults
|
||||||
|
@ -969,7 +970,7 @@ class TestBot:
|
||||||
monkeypatch.delattr(bot, '_post')
|
monkeypatch.delattr(bot, '_post')
|
||||||
|
|
||||||
# TODO: Needs improvement. No feasible way to test until bots can add members.
|
# TODO: Needs improvement. No feasible way to test until bots can add members.
|
||||||
def test_kick_chat_member(self, monkeypatch, bot):
|
def test_ban_chat_member(self, monkeypatch, bot):
|
||||||
def test(url, data, *args, **kwargs):
|
def test(url, data, *args, **kwargs):
|
||||||
chat_id = data['chat_id'] == 2
|
chat_id = data['chat_id'] == 2
|
||||||
user_id = data['user_id'] == 32
|
user_id = data['user_id'] == 32
|
||||||
|
@ -980,13 +981,13 @@ class TestBot:
|
||||||
monkeypatch.setattr(bot.request, 'post', test)
|
monkeypatch.setattr(bot.request, 'post', test)
|
||||||
until = from_timestamp(1577887200)
|
until = from_timestamp(1577887200)
|
||||||
|
|
||||||
assert bot.kick_chat_member(2, 32)
|
assert bot.ban_chat_member(2, 32)
|
||||||
assert bot.kick_chat_member(2, 32, until_date=until)
|
assert bot.ban_chat_member(2, 32, until_date=until)
|
||||||
assert bot.kick_chat_member(2, 32, until_date=1577887200)
|
assert bot.ban_chat_member(2, 32, until_date=1577887200)
|
||||||
assert bot.kick_chat_member(2, 32, revoke_messages=True)
|
assert bot.ban_chat_member(2, 32, revoke_messages=True)
|
||||||
monkeypatch.delattr(bot.request, 'post')
|
monkeypatch.delattr(bot.request, 'post')
|
||||||
|
|
||||||
def test_kick_chat_member_default_tz(self, monkeypatch, tz_bot):
|
def test_ban_chat_member_default_tz(self, monkeypatch, tz_bot):
|
||||||
until = dtm.datetime(2020, 1, 11, 16, 13)
|
until = dtm.datetime(2020, 1, 11, 16, 13)
|
||||||
until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
|
until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
|
||||||
|
|
||||||
|
@ -998,9 +999,21 @@ class TestBot:
|
||||||
|
|
||||||
monkeypatch.setattr(tz_bot.request, 'post', test)
|
monkeypatch.setattr(tz_bot.request, 'post', test)
|
||||||
|
|
||||||
assert tz_bot.kick_chat_member(2, 32)
|
assert tz_bot.ban_chat_member(2, 32)
|
||||||
assert tz_bot.kick_chat_member(2, 32, until_date=until)
|
assert tz_bot.ban_chat_member(2, 32, until_date=until)
|
||||||
assert tz_bot.kick_chat_member(2, 32, until_date=until_timestamp)
|
assert tz_bot.ban_chat_member(2, 32, until_date=until_timestamp)
|
||||||
|
|
||||||
|
def test_kick_chat_member_warning(self, monkeypatch, bot, recwarn):
|
||||||
|
def test(url, data, *args, **kwargs):
|
||||||
|
chat_id = data['chat_id'] == 2
|
||||||
|
user_id = data['user_id'] == 32
|
||||||
|
return chat_id and user_id
|
||||||
|
|
||||||
|
monkeypatch.setattr(bot.request, 'post', test)
|
||||||
|
bot.kick_chat_member(2, 32)
|
||||||
|
assert len(recwarn) == 1
|
||||||
|
assert '`bot.kick_chat_member` is deprecated' in str(recwarn[0].message)
|
||||||
|
monkeypatch.delattr(bot.request, 'post')
|
||||||
|
|
||||||
# TODO: Needs improvement.
|
# TODO: Needs improvement.
|
||||||
@pytest.mark.parametrize('only_if_banned', [True, False, None])
|
@pytest.mark.parametrize('only_if_banned', [True, False, None])
|
||||||
|
@ -1338,11 +1351,21 @@ class TestBot:
|
||||||
assert a.status in ('administrator', 'creator')
|
assert a.status in ('administrator', 'creator')
|
||||||
|
|
||||||
@flaky(3, 1)
|
@flaky(3, 1)
|
||||||
def test_get_chat_members_count(self, bot, channel_id):
|
def test_get_chat_member_count(self, bot, channel_id):
|
||||||
count = bot.get_chat_members_count(channel_id)
|
count = bot.get_chat_member_count(channel_id)
|
||||||
assert isinstance(count, int)
|
assert isinstance(count, int)
|
||||||
assert count > 3
|
assert count > 3
|
||||||
|
|
||||||
|
def test_get_chat_members_count_warning(self, bot, channel_id, recwarn):
|
||||||
|
bot.get_chat_members_count(channel_id)
|
||||||
|
assert len(recwarn) == 1
|
||||||
|
assert '`bot.get_chat_members_count` is deprecated' in str(recwarn[0].message)
|
||||||
|
|
||||||
|
def test_bot_command_property_warning(self, bot, recwarn):
|
||||||
|
_ = bot.commands
|
||||||
|
assert len(recwarn) == 1
|
||||||
|
assert 'Bot.commands has been deprecated since there can' in str(recwarn[0].message)
|
||||||
|
|
||||||
@flaky(3, 1)
|
@flaky(3, 1)
|
||||||
def test_get_chat_member(self, bot, channel_id, chat_id):
|
def test_get_chat_member(self, bot, channel_id, chat_id):
|
||||||
chat_member = bot.get_chat_member(channel_id, chat_id)
|
chat_member = bot.get_chat_member(channel_id, chat_id)
|
||||||
|
@ -1943,6 +1966,44 @@ class TestBot:
|
||||||
assert bc[1].command == 'cmd2'
|
assert bc[1].command == 'cmd2'
|
||||||
assert bc[1].description == 'descr2'
|
assert bc[1].description == 'descr2'
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
def test_get_set_delete_my_commands_with_scope(self, bot, super_group_id, chat_id):
|
||||||
|
group_cmds = [BotCommand('group_cmd', 'visible to this supergroup only')]
|
||||||
|
private_cmds = [BotCommand('private_cmd', 'visible to this private chat only')]
|
||||||
|
group_scope = BotCommandScopeChat(super_group_id)
|
||||||
|
private_scope = BotCommandScopeChat(chat_id)
|
||||||
|
|
||||||
|
# Set supergroup command list with lang code and check if the same can be returned from api
|
||||||
|
bot.set_my_commands(group_cmds, scope=group_scope, language_code='en')
|
||||||
|
gotten_group_cmds = bot.get_my_commands(scope=group_scope, language_code='en')
|
||||||
|
|
||||||
|
assert len(gotten_group_cmds) == len(group_cmds)
|
||||||
|
assert gotten_group_cmds[0].command == group_cmds[0].command
|
||||||
|
|
||||||
|
# Set private command list and check if same can be returned from the api
|
||||||
|
bot.set_my_commands(private_cmds, scope=private_scope)
|
||||||
|
gotten_private_cmd = bot.get_my_commands(scope=private_scope)
|
||||||
|
|
||||||
|
assert len(gotten_private_cmd) == len(private_cmds)
|
||||||
|
assert gotten_private_cmd[0].command == private_cmds[0].command
|
||||||
|
|
||||||
|
assert len(bot.commands) == 2 # set from previous test. Makes sure this hasn't changed.
|
||||||
|
assert bot.commands[0].command == 'cmd1'
|
||||||
|
|
||||||
|
# Delete command list from that supergroup and private chat-
|
||||||
|
bot.delete_my_commands(private_scope)
|
||||||
|
bot.delete_my_commands(group_scope, 'en')
|
||||||
|
|
||||||
|
# Check if its been deleted-
|
||||||
|
deleted_priv_cmds = bot.get_my_commands(scope=private_scope)
|
||||||
|
deleted_grp_cmds = bot.get_my_commands(scope=group_scope, language_code='en')
|
||||||
|
|
||||||
|
assert len(deleted_grp_cmds) == 0 == len(group_cmds) - 1
|
||||||
|
assert len(deleted_priv_cmds) == 0 == len(private_cmds) - 1
|
||||||
|
|
||||||
|
bot.delete_my_commands() # Delete commands from default scope
|
||||||
|
assert not bot.commands # Check if this has been updated to reflect the deletion.
|
||||||
|
|
||||||
def test_log_out(self, monkeypatch, bot):
|
def test_log_out(self, monkeypatch, bot):
|
||||||
# We don't actually make a request as to not break the test setup
|
# We don't actually make a request as to not break the test setup
|
||||||
def assertion(url, data, *args, **kwargs):
|
def assertion(url, data, *args, **kwargs):
|
||||||
|
|
205
tests/test_botcommandscope.py
Normal file
205
tests/test_botcommandscope.py
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# A library that provides a Python interface to the Telegram Bot API
|
||||||
|
# Copyright (C) 2021
|
||||||
|
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from telegram import (
|
||||||
|
Dice,
|
||||||
|
BotCommandScope,
|
||||||
|
BotCommandScopeDefault,
|
||||||
|
BotCommandScopeAllPrivateChats,
|
||||||
|
BotCommandScopeAllGroupChats,
|
||||||
|
BotCommandScopeAllChatAdministrators,
|
||||||
|
BotCommandScopeChat,
|
||||||
|
BotCommandScopeChatAdministrators,
|
||||||
|
BotCommandScopeChatMember,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="class", params=['str', 'int'])
|
||||||
|
def chat_id(request):
|
||||||
|
if request.param == 'str':
|
||||||
|
return '@supergroupusername'
|
||||||
|
return 43
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
scope="class",
|
||||||
|
params=[
|
||||||
|
BotCommandScope.DEFAULT,
|
||||||
|
BotCommandScope.ALL_PRIVATE_CHATS,
|
||||||
|
BotCommandScope.ALL_GROUP_CHATS,
|
||||||
|
BotCommandScope.ALL_CHAT_ADMINISTRATORS,
|
||||||
|
BotCommandScope.CHAT,
|
||||||
|
BotCommandScope.CHAT_ADMINISTRATORS,
|
||||||
|
BotCommandScope.CHAT_MEMBER,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def scope_type(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
scope="class",
|
||||||
|
params=[
|
||||||
|
BotCommandScopeDefault,
|
||||||
|
BotCommandScopeAllPrivateChats,
|
||||||
|
BotCommandScopeAllGroupChats,
|
||||||
|
BotCommandScopeAllChatAdministrators,
|
||||||
|
BotCommandScopeChat,
|
||||||
|
BotCommandScopeChatAdministrators,
|
||||||
|
BotCommandScopeChatMember,
|
||||||
|
],
|
||||||
|
ids=[
|
||||||
|
BotCommandScope.DEFAULT,
|
||||||
|
BotCommandScope.ALL_PRIVATE_CHATS,
|
||||||
|
BotCommandScope.ALL_GROUP_CHATS,
|
||||||
|
BotCommandScope.ALL_CHAT_ADMINISTRATORS,
|
||||||
|
BotCommandScope.CHAT,
|
||||||
|
BotCommandScope.CHAT_ADMINISTRATORS,
|
||||||
|
BotCommandScope.CHAT_MEMBER,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def scope_class(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
scope="class",
|
||||||
|
params=[
|
||||||
|
(BotCommandScopeDefault, BotCommandScope.DEFAULT),
|
||||||
|
(BotCommandScopeAllPrivateChats, BotCommandScope.ALL_PRIVATE_CHATS),
|
||||||
|
(BotCommandScopeAllGroupChats, BotCommandScope.ALL_GROUP_CHATS),
|
||||||
|
(BotCommandScopeAllChatAdministrators, BotCommandScope.ALL_CHAT_ADMINISTRATORS),
|
||||||
|
(BotCommandScopeChat, BotCommandScope.CHAT),
|
||||||
|
(BotCommandScopeChatAdministrators, BotCommandScope.CHAT_ADMINISTRATORS),
|
||||||
|
(BotCommandScopeChatMember, BotCommandScope.CHAT_MEMBER),
|
||||||
|
],
|
||||||
|
ids=[
|
||||||
|
BotCommandScope.DEFAULT,
|
||||||
|
BotCommandScope.ALL_PRIVATE_CHATS,
|
||||||
|
BotCommandScope.ALL_GROUP_CHATS,
|
||||||
|
BotCommandScope.ALL_CHAT_ADMINISTRATORS,
|
||||||
|
BotCommandScope.CHAT,
|
||||||
|
BotCommandScope.CHAT_ADMINISTRATORS,
|
||||||
|
BotCommandScope.CHAT_MEMBER,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def scope_class_and_type(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def bot_command_scope(scope_class_and_type, chat_id):
|
||||||
|
return scope_class_and_type[0](type=scope_class_and_type[1], chat_id=chat_id, user_id=42)
|
||||||
|
|
||||||
|
|
||||||
|
# All the scope types are very similar, so we test everything via parametrization
|
||||||
|
class TestBotCommandScope:
|
||||||
|
def test_slot_behaviour(self, bot_command_scope, mro_slots, recwarn):
|
||||||
|
for attr in bot_command_scope.__slots__:
|
||||||
|
assert getattr(bot_command_scope, attr, 'err') != 'err', f"got extra slot '{attr}'"
|
||||||
|
assert not bot_command_scope.__dict__, f"got missing slot(s): {bot_command_scope.__dict__}"
|
||||||
|
assert len(mro_slots(bot_command_scope)) == len(
|
||||||
|
set(mro_slots(bot_command_scope))
|
||||||
|
), "duplicate slot"
|
||||||
|
bot_command_scope.custom, bot_command_scope.type = 'warning!', bot_command_scope.type
|
||||||
|
assert len(recwarn) == 1 and 'custom' in str(recwarn[0].message), recwarn.list
|
||||||
|
|
||||||
|
def test_de_json(self, bot, scope_class_and_type, chat_id):
|
||||||
|
cls = scope_class_and_type[0]
|
||||||
|
type_ = scope_class_and_type[1]
|
||||||
|
|
||||||
|
assert cls.de_json({}, bot) is None
|
||||||
|
|
||||||
|
json_dict = {'type': type_, 'chat_id': chat_id, 'user_id': 42}
|
||||||
|
bot_command_scope = BotCommandScope.de_json(json_dict, bot)
|
||||||
|
|
||||||
|
assert isinstance(bot_command_scope, BotCommandScope)
|
||||||
|
assert isinstance(bot_command_scope, cls)
|
||||||
|
assert bot_command_scope.type == type_
|
||||||
|
if 'chat_id' in cls.__slots__:
|
||||||
|
assert bot_command_scope.chat_id == chat_id
|
||||||
|
if 'user_id' in cls.__slots__:
|
||||||
|
assert bot_command_scope.user_id == 42
|
||||||
|
|
||||||
|
def test_de_json_invalid_type(self, bot):
|
||||||
|
json_dict = {'type': 'invalid', 'chat_id': chat_id, 'user_id': 42}
|
||||||
|
bot_command_scope = BotCommandScope.de_json(json_dict, bot)
|
||||||
|
|
||||||
|
assert type(bot_command_scope) is BotCommandScope
|
||||||
|
assert bot_command_scope.type == 'invalid'
|
||||||
|
|
||||||
|
def test_de_json_subclass(self, scope_class, bot, chat_id):
|
||||||
|
"""This makes sure that e.g. BotCommandScopeDefault(data) never returns a
|
||||||
|
BotCommandScopeChat instance."""
|
||||||
|
json_dict = {'type': 'invalid', 'chat_id': chat_id, 'user_id': 42}
|
||||||
|
assert type(scope_class.de_json(json_dict, bot)) is scope_class
|
||||||
|
|
||||||
|
def test_to_dict(self, bot_command_scope):
|
||||||
|
bot_command_scope_dict = bot_command_scope.to_dict()
|
||||||
|
|
||||||
|
assert isinstance(bot_command_scope_dict, dict)
|
||||||
|
assert bot_command_scope['type'] == bot_command_scope.type
|
||||||
|
if hasattr(bot_command_scope, 'chat_id'):
|
||||||
|
assert bot_command_scope['chat_id'] == bot_command_scope.chat_id
|
||||||
|
if hasattr(bot_command_scope, 'user_id'):
|
||||||
|
assert bot_command_scope['user_id'] == bot_command_scope.user_id
|
||||||
|
|
||||||
|
def test_equality(self, bot_command_scope, bot):
|
||||||
|
a = BotCommandScope('base_type')
|
||||||
|
b = BotCommandScope('base_type')
|
||||||
|
c = bot_command_scope
|
||||||
|
d = deepcopy(bot_command_scope)
|
||||||
|
e = Dice(4, 'emoji')
|
||||||
|
|
||||||
|
assert a == b
|
||||||
|
assert hash(a) == hash(b)
|
||||||
|
|
||||||
|
assert a != c
|
||||||
|
assert hash(a) != hash(c)
|
||||||
|
|
||||||
|
assert a != d
|
||||||
|
assert hash(a) != hash(d)
|
||||||
|
|
||||||
|
assert a != e
|
||||||
|
assert hash(a) != hash(e)
|
||||||
|
|
||||||
|
assert c == d
|
||||||
|
assert hash(c) == hash(d)
|
||||||
|
|
||||||
|
assert c != e
|
||||||
|
assert hash(c) != hash(e)
|
||||||
|
|
||||||
|
if hasattr(c, 'chat_id'):
|
||||||
|
json_dict = c.to_dict()
|
||||||
|
json_dict['chat_id'] = 0
|
||||||
|
f = c.__class__.de_json(json_dict, bot)
|
||||||
|
|
||||||
|
assert c != f
|
||||||
|
assert hash(c) != hash(f)
|
||||||
|
|
||||||
|
if hasattr(c, 'user_id'):
|
||||||
|
json_dict = c.to_dict()
|
||||||
|
json_dict['user_id'] = 0
|
||||||
|
g = c.__class__.de_json(json_dict, bot)
|
||||||
|
|
||||||
|
assert c != g
|
||||||
|
assert hash(c) != hash(g)
|
|
@ -176,18 +176,27 @@ class TestChat:
|
||||||
monkeypatch.setattr(chat.bot, 'get_chat_administrators', make_assertion)
|
monkeypatch.setattr(chat.bot, 'get_chat_administrators', make_assertion)
|
||||||
assert chat.get_administrators()
|
assert chat.get_administrators()
|
||||||
|
|
||||||
def test_get_members_count(self, monkeypatch, chat):
|
def test_get_member_count(self, monkeypatch, chat):
|
||||||
def make_assertion(*_, **kwargs):
|
def make_assertion(*_, **kwargs):
|
||||||
return kwargs['chat_id'] == chat.id
|
return kwargs['chat_id'] == chat.id
|
||||||
|
|
||||||
assert check_shortcut_signature(
|
assert check_shortcut_signature(
|
||||||
Chat.get_members_count, Bot.get_chat_members_count, ['chat_id'], []
|
Chat.get_member_count, Bot.get_chat_member_count, ['chat_id'], []
|
||||||
)
|
)
|
||||||
assert check_shortcut_call(chat.get_members_count, chat.bot, 'get_chat_members_count')
|
assert check_shortcut_call(chat.get_member_count, chat.bot, 'get_chat_member_count')
|
||||||
assert check_defaults_handling(chat.get_members_count, chat.bot)
|
assert check_defaults_handling(chat.get_member_count, chat.bot)
|
||||||
|
|
||||||
monkeypatch.setattr(chat.bot, 'get_chat_members_count', make_assertion)
|
monkeypatch.setattr(chat.bot, 'get_chat_member_count', make_assertion)
|
||||||
|
assert chat.get_member_count()
|
||||||
|
|
||||||
|
def test_get_members_count_warning(self, chat, monkeypatch, recwarn):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
return kwargs['chat_id'] == chat.id
|
||||||
|
|
||||||
|
monkeypatch.setattr(chat.bot, 'get_chat_member_count', make_assertion)
|
||||||
assert chat.get_members_count()
|
assert chat.get_members_count()
|
||||||
|
assert len(recwarn) == 1
|
||||||
|
assert '`Chat.get_members_count` is deprecated' in str(recwarn[0].message)
|
||||||
|
|
||||||
def test_get_member(self, monkeypatch, chat):
|
def test_get_member(self, monkeypatch, chat):
|
||||||
def make_assertion(*_, **kwargs):
|
def make_assertion(*_, **kwargs):
|
||||||
|
@ -202,19 +211,31 @@ class TestChat:
|
||||||
monkeypatch.setattr(chat.bot, 'get_chat_member', make_assertion)
|
monkeypatch.setattr(chat.bot, 'get_chat_member', make_assertion)
|
||||||
assert chat.get_member(user_id=42)
|
assert chat.get_member(user_id=42)
|
||||||
|
|
||||||
def test_kick_member(self, monkeypatch, chat):
|
def test_ban_member(self, monkeypatch, chat):
|
||||||
def make_assertion(*_, **kwargs):
|
def make_assertion(*_, **kwargs):
|
||||||
chat_id = kwargs['chat_id'] == chat.id
|
chat_id = kwargs['chat_id'] == chat.id
|
||||||
user_id = kwargs['user_id'] == 42
|
user_id = kwargs['user_id'] == 42
|
||||||
until = kwargs['until_date'] == 43
|
until = kwargs['until_date'] == 43
|
||||||
return chat_id and user_id and until
|
return chat_id and user_id and until
|
||||||
|
|
||||||
assert check_shortcut_signature(Chat.kick_member, Bot.kick_chat_member, ['chat_id'], [])
|
assert check_shortcut_signature(Chat.ban_member, Bot.ban_chat_member, ['chat_id'], [])
|
||||||
assert check_shortcut_call(chat.kick_member, chat.bot, 'kick_chat_member')
|
assert check_shortcut_call(chat.ban_member, chat.bot, 'ban_chat_member')
|
||||||
assert check_defaults_handling(chat.kick_member, chat.bot)
|
assert check_defaults_handling(chat.ban_member, chat.bot)
|
||||||
|
|
||||||
monkeypatch.setattr(chat.bot, 'kick_chat_member', make_assertion)
|
monkeypatch.setattr(chat.bot, 'ban_chat_member', make_assertion)
|
||||||
|
assert chat.ban_member(user_id=42, until_date=43)
|
||||||
|
|
||||||
|
def test_kick_member_warning(self, chat, monkeypatch, recwarn):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
chat_id = kwargs['chat_id'] == chat.id
|
||||||
|
user_id = kwargs['user_id'] == 42
|
||||||
|
until = kwargs['until_date'] == 43
|
||||||
|
return chat_id and user_id and until
|
||||||
|
|
||||||
|
monkeypatch.setattr(chat.bot, 'ban_chat_member', make_assertion)
|
||||||
assert chat.kick_member(user_id=42, until_date=43)
|
assert chat.kick_member(user_id=42, until_date=43)
|
||||||
|
assert len(recwarn) == 1
|
||||||
|
assert '`Chat.kick_member` is deprecated' in str(recwarn[0].message)
|
||||||
|
|
||||||
@pytest.mark.parametrize('only_if_banned', [True, False, None])
|
@pytest.mark.parametrize('only_if_banned', [True, False, None])
|
||||||
def test_unban_member(self, monkeypatch, chat, only_if_banned):
|
def test_unban_member(self, monkeypatch, chat, only_if_banned):
|
||||||
|
|
|
@ -17,11 +17,22 @@
|
||||||
# You should have received a copy of the GNU Lesser Public License
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
import datetime
|
import datetime
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from telegram import User, ChatMember
|
|
||||||
from telegram.utils.helpers import to_timestamp
|
from telegram.utils.helpers import to_timestamp
|
||||||
|
from telegram import (
|
||||||
|
User,
|
||||||
|
ChatMember,
|
||||||
|
ChatMemberOwner,
|
||||||
|
ChatMemberAdministrator,
|
||||||
|
ChatMemberMember,
|
||||||
|
ChatMemberRestricted,
|
||||||
|
ChatMemberLeft,
|
||||||
|
ChatMemberBanned,
|
||||||
|
Dice,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='class')
|
@pytest.fixture(scope='class')
|
||||||
|
@ -29,38 +40,68 @@ def user():
|
||||||
return User(1, 'First name', False)
|
return User(1, 'First name', False)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
scope="class",
|
||||||
|
params=[
|
||||||
|
(ChatMemberOwner, ChatMember.CREATOR),
|
||||||
|
(ChatMemberAdministrator, ChatMember.ADMINISTRATOR),
|
||||||
|
(ChatMemberMember, ChatMember.MEMBER),
|
||||||
|
(ChatMemberRestricted, ChatMember.RESTRICTED),
|
||||||
|
(ChatMemberLeft, ChatMember.LEFT),
|
||||||
|
(ChatMemberBanned, ChatMember.KICKED),
|
||||||
|
],
|
||||||
|
ids=[
|
||||||
|
ChatMember.CREATOR,
|
||||||
|
ChatMember.ADMINISTRATOR,
|
||||||
|
ChatMember.MEMBER,
|
||||||
|
ChatMember.RESTRICTED,
|
||||||
|
ChatMember.LEFT,
|
||||||
|
ChatMember.KICKED,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def chat_member_class_and_status(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='class')
|
@pytest.fixture(scope='class')
|
||||||
def chat_member(user):
|
def chat_member_types(chat_member_class_and_status, user):
|
||||||
return ChatMember(user, TestChatMember.status)
|
return chat_member_class_and_status[0](status=chat_member_class_and_status[1], user=user)
|
||||||
|
|
||||||
|
|
||||||
class TestChatMember:
|
class TestChatMember:
|
||||||
status = ChatMember.CREATOR
|
def test_slot_behaviour(self, chat_member_types, mro_slots, recwarn):
|
||||||
|
for attr in chat_member_types.__slots__:
|
||||||
def test_slot_behaviour(self, chat_member, recwarn, mro_slots):
|
assert getattr(chat_member_types, attr, 'err') != 'err', f"got extra slot '{attr}'"
|
||||||
for attr in chat_member.__slots__:
|
assert not chat_member_types.__dict__, f"got missing slot(s): {chat_member_types.__dict__}"
|
||||||
assert getattr(chat_member, attr, 'err') != 'err', f"got extra slot '{attr}'"
|
assert len(mro_slots(chat_member_types)) == len(
|
||||||
assert not chat_member.__dict__, f"got missing slot(s): {chat_member.__dict__}"
|
set(mro_slots(chat_member_types))
|
||||||
assert len(mro_slots(chat_member)) == len(set(mro_slots(chat_member))), "duplicate slot"
|
), "duplicate slot"
|
||||||
chat_member.custom, chat_member.status = 'should give warning', self.status
|
chat_member_types.custom, chat_member_types.status = 'warning!', chat_member_types.status
|
||||||
assert len(recwarn) == 1 and 'custom' in str(recwarn[0].message), recwarn.list
|
assert len(recwarn) == 1 and 'custom' in str(recwarn[0].message), recwarn.list
|
||||||
|
|
||||||
def test_de_json_required_args(self, bot, user):
|
def test_de_json_required_args(self, bot, chat_member_class_and_status, user):
|
||||||
json_dict = {'user': user.to_dict(), 'status': self.status}
|
cls = chat_member_class_and_status[0]
|
||||||
|
status = chat_member_class_and_status[1]
|
||||||
|
|
||||||
chat_member = ChatMember.de_json(json_dict, bot)
|
assert cls.de_json({}, bot) is None
|
||||||
|
|
||||||
assert chat_member.user == user
|
json_dict = {'status': status, 'user': user.to_dict()}
|
||||||
assert chat_member.status == self.status
|
chat_member_type = ChatMember.de_json(json_dict, bot)
|
||||||
|
|
||||||
def test_de_json_all_args(self, bot, user):
|
assert isinstance(chat_member_type, ChatMember)
|
||||||
|
assert isinstance(chat_member_type, cls)
|
||||||
|
assert chat_member_type.status == status
|
||||||
|
assert chat_member_type.user == user
|
||||||
|
|
||||||
|
def test_de_json_all_args(self, bot, chat_member_class_and_status, user):
|
||||||
|
cls = chat_member_class_and_status[0]
|
||||||
|
status = chat_member_class_and_status[1]
|
||||||
time = datetime.datetime.utcnow()
|
time = datetime.datetime.utcnow()
|
||||||
custom_title = 'custom_title'
|
|
||||||
|
|
||||||
json_dict = {
|
json_dict = {
|
||||||
'user': user.to_dict(),
|
'user': user.to_dict(),
|
||||||
'status': self.status,
|
'status': status,
|
||||||
'custom_title': custom_title,
|
'custom_title': 'PTB',
|
||||||
'is_anonymous': True,
|
'is_anonymous': True,
|
||||||
'until_date': to_timestamp(time),
|
'until_date': to_timestamp(time),
|
||||||
'can_be_edited': False,
|
'can_be_edited': False,
|
||||||
|
@ -80,48 +121,134 @@ class TestChatMember:
|
||||||
'can_manage_chat': True,
|
'can_manage_chat': True,
|
||||||
'can_manage_voice_chats': True,
|
'can_manage_voice_chats': True,
|
||||||
}
|
}
|
||||||
|
chat_member_type = ChatMember.de_json(json_dict, bot)
|
||||||
|
|
||||||
chat_member = ChatMember.de_json(json_dict, bot)
|
assert isinstance(chat_member_type, ChatMember)
|
||||||
|
assert isinstance(chat_member_type, cls)
|
||||||
|
assert chat_member_type.user == user
|
||||||
|
assert chat_member_type.status == status
|
||||||
|
if chat_member_type.custom_title is not None:
|
||||||
|
assert chat_member_type.custom_title == 'PTB'
|
||||||
|
assert type(chat_member_type) in {ChatMemberOwner, ChatMemberAdministrator}
|
||||||
|
if chat_member_type.is_anonymous is not None:
|
||||||
|
assert chat_member_type.is_anonymous is True
|
||||||
|
assert type(chat_member_type) in {ChatMemberOwner, ChatMemberAdministrator}
|
||||||
|
if chat_member_type.until_date is not None:
|
||||||
|
assert type(chat_member_type) in {ChatMemberBanned, ChatMemberRestricted}
|
||||||
|
if chat_member_type.can_be_edited is not None:
|
||||||
|
assert chat_member_type.can_be_edited is False
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_change_info is not None:
|
||||||
|
assert chat_member_type.can_change_info is True
|
||||||
|
assert type(chat_member_type) in {ChatMemberAdministrator, ChatMemberRestricted}
|
||||||
|
if chat_member_type.can_post_messages is not None:
|
||||||
|
assert chat_member_type.can_post_messages is False
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_edit_messages is not None:
|
||||||
|
assert chat_member_type.can_edit_messages is True
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_delete_messages is not None:
|
||||||
|
assert chat_member_type.can_delete_messages is True
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_invite_users is not None:
|
||||||
|
assert chat_member_type.can_invite_users is False
|
||||||
|
assert type(chat_member_type) in {ChatMemberAdministrator, ChatMemberRestricted}
|
||||||
|
if chat_member_type.can_restrict_members is not None:
|
||||||
|
assert chat_member_type.can_restrict_members is True
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_pin_messages is not None:
|
||||||
|
assert chat_member_type.can_pin_messages is False
|
||||||
|
assert type(chat_member_type) in {ChatMemberAdministrator, ChatMemberRestricted}
|
||||||
|
if chat_member_type.can_promote_members is not None:
|
||||||
|
assert chat_member_type.can_promote_members is True
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_send_messages is not None:
|
||||||
|
assert chat_member_type.can_send_messages is False
|
||||||
|
assert type(chat_member_type) == ChatMemberRestricted
|
||||||
|
if chat_member_type.can_send_media_messages is not None:
|
||||||
|
assert chat_member_type.can_send_media_messages is True
|
||||||
|
assert type(chat_member_type) == ChatMemberRestricted
|
||||||
|
if chat_member_type.can_send_polls is not None:
|
||||||
|
assert chat_member_type.can_send_polls is False
|
||||||
|
assert type(chat_member_type) == ChatMemberRestricted
|
||||||
|
if chat_member_type.can_send_other_messages is not None:
|
||||||
|
assert chat_member_type.can_send_other_messages is True
|
||||||
|
assert type(chat_member_type) == ChatMemberRestricted
|
||||||
|
if chat_member_type.can_add_web_page_previews is not None:
|
||||||
|
assert chat_member_type.can_add_web_page_previews is False
|
||||||
|
assert type(chat_member_type) == ChatMemberRestricted
|
||||||
|
if chat_member_type.can_manage_chat is not None:
|
||||||
|
assert chat_member_type.can_manage_chat is True
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
if chat_member_type.can_manage_voice_chats is not None:
|
||||||
|
assert chat_member_type.can_manage_voice_chats is True
|
||||||
|
assert type(chat_member_type) == ChatMemberAdministrator
|
||||||
|
|
||||||
assert chat_member.user == user
|
def test_de_json_invalid_status(self, bot, user):
|
||||||
assert chat_member.status == self.status
|
json_dict = {'status': 'invalid', 'user': user.to_dict()}
|
||||||
assert chat_member.custom_title == custom_title
|
chat_member_type = ChatMember.de_json(json_dict, bot)
|
||||||
assert chat_member.is_anonymous is True
|
|
||||||
assert chat_member.can_be_edited is False
|
assert type(chat_member_type) is ChatMember
|
||||||
assert chat_member.can_change_info is True
|
assert chat_member_type.status == 'invalid'
|
||||||
assert chat_member.can_post_messages is False
|
|
||||||
assert chat_member.can_edit_messages is True
|
def test_de_json_subclass(self, chat_member_class_and_status, bot, chat_id, user):
|
||||||
assert chat_member.can_delete_messages is True
|
"""This makes sure that e.g. ChatMemberAdministrator(data, bot) never returns a
|
||||||
assert chat_member.can_invite_users is False
|
ChatMemberKicked instance."""
|
||||||
assert chat_member.can_restrict_members is True
|
cls = chat_member_class_and_status[0]
|
||||||
assert chat_member.can_pin_messages is False
|
time = datetime.datetime.utcnow()
|
||||||
assert chat_member.can_promote_members is True
|
json_dict = {
|
||||||
assert chat_member.can_send_messages is False
|
'user': user.to_dict(),
|
||||||
assert chat_member.can_send_media_messages is True
|
'status': 'status',
|
||||||
assert chat_member.can_send_polls is False
|
'custom_title': 'PTB',
|
||||||
assert chat_member.can_send_other_messages is True
|
'is_anonymous': True,
|
||||||
assert chat_member.can_add_web_page_previews is False
|
'until_date': to_timestamp(time),
|
||||||
assert chat_member.can_manage_chat is True
|
'can_be_edited': False,
|
||||||
assert chat_member.can_manage_voice_chats is True
|
'can_change_info': True,
|
||||||
|
'can_post_messages': False,
|
||||||
|
'can_edit_messages': True,
|
||||||
|
'can_delete_messages': True,
|
||||||
|
'can_invite_users': False,
|
||||||
|
'can_restrict_members': True,
|
||||||
|
'can_pin_messages': False,
|
||||||
|
'can_promote_members': True,
|
||||||
|
'can_send_messages': False,
|
||||||
|
'can_send_media_messages': True,
|
||||||
|
'can_send_polls': False,
|
||||||
|
'can_send_other_messages': True,
|
||||||
|
'can_add_web_page_previews': False,
|
||||||
|
'can_manage_chat': True,
|
||||||
|
'can_manage_voice_chats': True,
|
||||||
|
}
|
||||||
|
assert type(cls.de_json(json_dict, bot)) is cls
|
||||||
|
|
||||||
|
def test_to_dict(self, chat_member_types, user):
|
||||||
|
chat_member_dict = chat_member_types.to_dict()
|
||||||
|
|
||||||
def test_to_dict(self, chat_member):
|
|
||||||
chat_member_dict = chat_member.to_dict()
|
|
||||||
assert isinstance(chat_member_dict, dict)
|
assert isinstance(chat_member_dict, dict)
|
||||||
assert chat_member_dict['user'] == chat_member.user.to_dict()
|
assert chat_member_dict['status'] == chat_member_types.status
|
||||||
assert chat_member['status'] == chat_member.status
|
assert chat_member_dict['user'] == user.to_dict()
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self, chat_member_types, user):
|
||||||
a = ChatMember(User(1, '', False), ChatMember.ADMINISTRATOR)
|
a = ChatMember(status='status', user=user)
|
||||||
b = ChatMember(User(1, '', False), ChatMember.ADMINISTRATOR)
|
b = ChatMember(status='status', user=user)
|
||||||
d = ChatMember(User(2, '', False), ChatMember.ADMINISTRATOR)
|
c = chat_member_types
|
||||||
d2 = ChatMember(User(1, '', False), ChatMember.CREATOR)
|
d = deepcopy(chat_member_types)
|
||||||
|
e = Dice(4, 'emoji')
|
||||||
|
|
||||||
assert a == b
|
assert a == b
|
||||||
assert hash(a) == hash(b)
|
assert hash(a) == hash(b)
|
||||||
assert a is not b
|
|
||||||
|
assert a != c
|
||||||
|
assert hash(a) != hash(c)
|
||||||
|
|
||||||
assert a != d
|
assert a != d
|
||||||
assert hash(a) != hash(d)
|
assert hash(a) != hash(d)
|
||||||
|
|
||||||
assert a != d2
|
assert a != e
|
||||||
assert hash(a) != hash(d2)
|
assert hash(a) != hash(e)
|
||||||
|
|
||||||
|
assert c == d
|
||||||
|
assert hash(c) == hash(d)
|
||||||
|
|
||||||
|
assert c != e
|
||||||
|
assert hash(c) != hash(e)
|
||||||
|
|
|
@ -25,12 +25,17 @@ from telegram import ForceReply, ReplyKeyboardRemove
|
||||||
|
|
||||||
@pytest.fixture(scope='class')
|
@pytest.fixture(scope='class')
|
||||||
def force_reply():
|
def force_reply():
|
||||||
return ForceReply(TestForceReply.force_reply, TestForceReply.selective)
|
return ForceReply(
|
||||||
|
TestForceReply.force_reply,
|
||||||
|
TestForceReply.selective,
|
||||||
|
TestForceReply.input_field_placeholder,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestForceReply:
|
class TestForceReply:
|
||||||
force_reply = True
|
force_reply = True
|
||||||
selective = True
|
selective = True
|
||||||
|
input_field_placeholder = 'force replies can be annoying if not used properly'
|
||||||
|
|
||||||
def test_slot_behaviour(self, force_reply, recwarn, mro_slots):
|
def test_slot_behaviour(self, force_reply, recwarn, mro_slots):
|
||||||
for attr in force_reply.__slots__:
|
for attr in force_reply.__slots__:
|
||||||
|
@ -49,6 +54,7 @@ class TestForceReply:
|
||||||
def test_expected(self, force_reply):
|
def test_expected(self, force_reply):
|
||||||
assert force_reply.force_reply == self.force_reply
|
assert force_reply.force_reply == self.force_reply
|
||||||
assert force_reply.selective == self.selective
|
assert force_reply.selective == self.selective
|
||||||
|
assert force_reply.input_field_placeholder == self.input_field_placeholder
|
||||||
|
|
||||||
def test_to_dict(self, force_reply):
|
def test_to_dict(self, force_reply):
|
||||||
force_reply_dict = force_reply.to_dict()
|
force_reply_dict = force_reply.to_dict()
|
||||||
|
@ -56,6 +62,7 @@ class TestForceReply:
|
||||||
assert isinstance(force_reply_dict, dict)
|
assert isinstance(force_reply_dict, dict)
|
||||||
assert force_reply_dict['force_reply'] == force_reply.force_reply
|
assert force_reply_dict['force_reply'] == force_reply.force_reply
|
||||||
assert force_reply_dict['selective'] == force_reply.selective
|
assert force_reply_dict['selective'] == force_reply.selective
|
||||||
|
assert force_reply_dict['input_field_placeholder'] == force_reply.input_field_placeholder
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
a = ForceReply(True, False)
|
a = ForceReply(True, False)
|
||||||
|
|
|
@ -118,9 +118,13 @@ def check_object(h4):
|
||||||
if field == 'from':
|
if field == 'from':
|
||||||
field = 'from_user'
|
field = 'from_user'
|
||||||
elif (
|
elif (
|
||||||
name.startswith('InlineQueryResult') or name.startswith('InputMedia')
|
name.startswith('InlineQueryResult')
|
||||||
|
or name.startswith('InputMedia')
|
||||||
|
or name.startswith('BotCommandScope')
|
||||||
) and field == 'type':
|
) and field == 'type':
|
||||||
continue
|
continue
|
||||||
|
elif (name.startswith('ChatMember')) and field == 'status':
|
||||||
|
continue
|
||||||
elif (
|
elif (
|
||||||
name.startswith('PassportElementError') and field == 'source'
|
name.startswith('PassportElementError') and field == 'source'
|
||||||
) or field == 'remove_keyboard':
|
) or field == 'remove_keyboard':
|
||||||
|
@ -136,7 +140,34 @@ def check_object(h4):
|
||||||
if name == 'InputFile':
|
if name == 'InputFile':
|
||||||
return
|
return
|
||||||
if name == 'InlineQueryResult':
|
if name == 'InlineQueryResult':
|
||||||
ignored |= {'id', 'type'}
|
ignored |= {'id', 'type'} # attributes common to all subclasses
|
||||||
|
if name == 'ChatMember':
|
||||||
|
ignored |= {'user', 'status'} # attributes common to all subclasses
|
||||||
|
if name == 'ChatMember':
|
||||||
|
ignored |= {
|
||||||
|
'can_add_web_page_previews', # for backwards compatibility
|
||||||
|
'can_be_edited',
|
||||||
|
'can_change_info',
|
||||||
|
'can_delete_messages',
|
||||||
|
'can_edit_messages',
|
||||||
|
'can_invite_users',
|
||||||
|
'can_manage_chat',
|
||||||
|
'can_manage_voice_chats',
|
||||||
|
'can_pin_messages',
|
||||||
|
'can_post_messages',
|
||||||
|
'can_promote_members',
|
||||||
|
'can_restrict_members',
|
||||||
|
'can_send_media_messages',
|
||||||
|
'can_send_messages',
|
||||||
|
'can_send_other_messages',
|
||||||
|
'can_send_polls',
|
||||||
|
'custom_title',
|
||||||
|
'is_anonymous',
|
||||||
|
'is_member',
|
||||||
|
'until_date',
|
||||||
|
}
|
||||||
|
if name == 'BotCommandScope':
|
||||||
|
ignored |= {'type'} # attributes common to all subclasses
|
||||||
elif name == 'User':
|
elif name == 'User':
|
||||||
ignored |= {'type'} # TODO: Deprecation
|
ignored |= {'type'} # TODO: Deprecation
|
||||||
elif name in ('PassportFile', 'EncryptedPassportElement'):
|
elif name in ('PassportFile', 'EncryptedPassportElement'):
|
||||||
|
|
|
@ -29,6 +29,7 @@ def reply_keyboard_markup():
|
||||||
resize_keyboard=TestReplyKeyboardMarkup.resize_keyboard,
|
resize_keyboard=TestReplyKeyboardMarkup.resize_keyboard,
|
||||||
one_time_keyboard=TestReplyKeyboardMarkup.one_time_keyboard,
|
one_time_keyboard=TestReplyKeyboardMarkup.one_time_keyboard,
|
||||||
selective=TestReplyKeyboardMarkup.selective,
|
selective=TestReplyKeyboardMarkup.selective,
|
||||||
|
input_field_placeholder=TestReplyKeyboardMarkup.input_field_placeholder,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ class TestReplyKeyboardMarkup:
|
||||||
resize_keyboard = True
|
resize_keyboard = True
|
||||||
one_time_keyboard = True
|
one_time_keyboard = True
|
||||||
selective = True
|
selective = True
|
||||||
|
input_field_placeholder = 'lol a keyboard'
|
||||||
|
|
||||||
def test_slot_behaviour(self, reply_keyboard_markup, mro_slots, recwarn):
|
def test_slot_behaviour(self, reply_keyboard_markup, mro_slots, recwarn):
|
||||||
inst = reply_keyboard_markup
|
inst = reply_keyboard_markup
|
||||||
|
@ -101,6 +103,7 @@ class TestReplyKeyboardMarkup:
|
||||||
assert reply_keyboard_markup.resize_keyboard == self.resize_keyboard
|
assert reply_keyboard_markup.resize_keyboard == self.resize_keyboard
|
||||||
assert reply_keyboard_markup.one_time_keyboard == self.one_time_keyboard
|
assert reply_keyboard_markup.one_time_keyboard == self.one_time_keyboard
|
||||||
assert reply_keyboard_markup.selective == self.selective
|
assert reply_keyboard_markup.selective == self.selective
|
||||||
|
assert reply_keyboard_markup.input_field_placeholder == self.input_field_placeholder
|
||||||
|
|
||||||
def test_to_dict(self, reply_keyboard_markup):
|
def test_to_dict(self, reply_keyboard_markup):
|
||||||
reply_keyboard_markup_dict = reply_keyboard_markup.to_dict()
|
reply_keyboard_markup_dict = reply_keyboard_markup.to_dict()
|
||||||
|
@ -122,6 +125,10 @@ class TestReplyKeyboardMarkup:
|
||||||
== reply_keyboard_markup.one_time_keyboard
|
== reply_keyboard_markup.one_time_keyboard
|
||||||
)
|
)
|
||||||
assert reply_keyboard_markup_dict['selective'] == reply_keyboard_markup.selective
|
assert reply_keyboard_markup_dict['selective'] == reply_keyboard_markup.selective
|
||||||
|
assert (
|
||||||
|
reply_keyboard_markup_dict['input_field_placeholder']
|
||||||
|
== reply_keyboard_markup.input_field_placeholder
|
||||||
|
)
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
a = ReplyKeyboardMarkup.from_column(['button1', 'button2', 'button3'])
|
a = ReplyKeyboardMarkup.from_column(['button1', 'button2', 'button3'])
|
||||||
|
|
Loading…
Reference in a new issue