mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2025-03-28 09:17:29 +01:00
API 5.4 (#2767)
Co-authored-by: poolitzer <25934244+Poolitzer@users.noreply.github.com>
This commit is contained in:
parent
bc7c422a11
commit
e4dc80f41d
21 changed files with 1125 additions and 15 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.3-blue?logo=telegram
|
.. image:: https://img.shields.io/badge/Bot%20API-5.4-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.3** are supported.
|
All types and methods of the Telegram Bot API **5.4** 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.3-blue?logo=telegram
|
.. image:: https://img.shields.io/badge/Bot%20API-5.4-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.3** are supported.
|
All types and methods of the Telegram Bot API **5.4** are supported.
|
||||||
|
|
||||||
==========
|
==========
|
||||||
Installing
|
Installing
|
||||||
|
|
|
@ -60,7 +60,7 @@ ignore_errors = True
|
||||||
|
|
||||||
# Disable strict optional for telegram objects with class methods
|
# Disable strict optional for telegram objects with class methods
|
||||||
# We don't want to clutter the code with 'if self.bot is None: raise RuntimeError()'
|
# We don't want to clutter the code with 'if self.bot is None: raise RuntimeError()'
|
||||||
[mypy-telegram.callbackquery,telegram.chat,telegram.message,telegram.user,telegram.files.*,telegram.inline.inlinequery,telegram.payment.precheckoutquery,telegram.payment.shippingquery,telegram.passport.passportdata,telegram.passport.credentials,telegram.passport.passportfile,telegram.ext.filters]
|
[mypy-telegram.callbackquery,telegram.chat,telegram.message,telegram.user,telegram.files.*,telegram.inline.inlinequery,telegram.payment.precheckoutquery,telegram.payment.shippingquery,telegram.passport.passportdata,telegram.passport.credentials,telegram.passport.passportfile,telegram.ext.filters,telegram.chatjoinrequest]
|
||||||
strict_optional = False
|
strict_optional = False
|
||||||
|
|
||||||
# type hinting for asyncio in webhookhandler is a bit tricky because it depends on the OS
|
# type hinting for asyncio in webhookhandler is a bit tricky because it depends on the OS
|
||||||
|
|
|
@ -25,6 +25,7 @@ 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 .chatjoinrequest import ChatJoinRequest
|
||||||
from .chatmember import (
|
from .chatmember import (
|
||||||
ChatMember,
|
ChatMember,
|
||||||
ChatMemberOwner,
|
ChatMemberOwner,
|
||||||
|
@ -194,6 +195,7 @@ __all__ = ( # Keep this alphabetically ordered
|
||||||
'Chat',
|
'Chat',
|
||||||
'ChatAction',
|
'ChatAction',
|
||||||
'ChatInviteLink',
|
'ChatInviteLink',
|
||||||
|
'ChatJoinRequest',
|
||||||
'ChatLocation',
|
'ChatLocation',
|
||||||
'ChatMember',
|
'ChatMember',
|
||||||
'ChatMemberOwner',
|
'ChatMemberOwner',
|
||||||
|
|
132
telegram/bot.py
132
telegram/bot.py
|
@ -3985,6 +3985,8 @@ class Bot(TelegramObject):
|
||||||
member_limit: int = None,
|
member_limit: int = None,
|
||||||
timeout: ODVInput[float] = DEFAULT_NONE,
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
|
name: str = None,
|
||||||
|
creates_join_request: bool = None,
|
||||||
) -> ChatInviteLink:
|
) -> ChatInviteLink:
|
||||||
"""
|
"""
|
||||||
Use this method to create an additional invite link for a chat. The bot must be an
|
Use this method to create an additional invite link for a chat. The bot must be an
|
||||||
|
@ -4007,6 +4009,14 @@ 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.
|
||||||
|
name (:obj:`str`, optional): Invite link name; 0-32 characters.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
creates_join_request (:obj:`bool`, optional): :obj:`True`, if users joining the chat
|
||||||
|
via the link need to be approved by chat administrators.
|
||||||
|
If :obj:`True`, ``member_limit`` can't be specified.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:class:`telegram.ChatInviteLink`
|
:class:`telegram.ChatInviteLink`
|
||||||
|
@ -4015,6 +4025,11 @@ class Bot(TelegramObject):
|
||||||
:class:`telegram.error.TelegramError`
|
:class:`telegram.error.TelegramError`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if creates_join_request and member_limit:
|
||||||
|
raise ValueError(
|
||||||
|
"If `creates_join_request` is `True`, `member_limit` can't be specified."
|
||||||
|
)
|
||||||
|
|
||||||
data: JSONDict = {
|
data: JSONDict = {
|
||||||
'chat_id': chat_id,
|
'chat_id': chat_id,
|
||||||
}
|
}
|
||||||
|
@ -4029,6 +4044,12 @@ class Bot(TelegramObject):
|
||||||
if member_limit is not None:
|
if member_limit is not None:
|
||||||
data['member_limit'] = member_limit
|
data['member_limit'] = member_limit
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
data['name'] = name
|
||||||
|
|
||||||
|
if creates_join_request is not None:
|
||||||
|
data['creates_join_request'] = creates_join_request
|
||||||
|
|
||||||
result = self._post('createChatInviteLink', data, timeout=timeout, api_kwargs=api_kwargs)
|
result = self._post('createChatInviteLink', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
return ChatInviteLink.de_json(result, self) # type: ignore[return-value, arg-type]
|
return ChatInviteLink.de_json(result, self) # type: ignore[return-value, arg-type]
|
||||||
|
@ -4042,11 +4063,19 @@ class Bot(TelegramObject):
|
||||||
member_limit: int = None,
|
member_limit: int = None,
|
||||||
timeout: ODVInput[float] = DEFAULT_NONE,
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
|
name: str = None,
|
||||||
|
creates_join_request: bool = None,
|
||||||
) -> ChatInviteLink:
|
) -> ChatInviteLink:
|
||||||
"""
|
"""
|
||||||
Use this method to edit a non-primary invite link created by the bot. The bot must be an
|
Use this method to edit a non-primary invite link created by the bot. The bot must be an
|
||||||
administrator in the chat for this to work and must have the appropriate admin rights.
|
administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Though not stated explicitly in the official docs, Telegram changes not only the
|
||||||
|
optional parameters that are explicitly passed, but also replaces all other optional
|
||||||
|
parameters to the default values. However, since not documented, this behaviour may
|
||||||
|
change unbeknown to PTB.
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -4064,6 +4093,14 @@ 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.
|
||||||
|
name (:obj:`str`, optional): Invite link name; 0-32 characters.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
creates_join_request (:obj:`bool`, optional): :obj:`True`, if users joining the chat
|
||||||
|
via the link need to be approved by chat administrators.
|
||||||
|
If :obj:`True`, ``member_limit`` can't be specified.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:class:`telegram.ChatInviteLink`
|
:class:`telegram.ChatInviteLink`
|
||||||
|
@ -4072,6 +4109,11 @@ class Bot(TelegramObject):
|
||||||
:class:`telegram.error.TelegramError`
|
:class:`telegram.error.TelegramError`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if creates_join_request and member_limit:
|
||||||
|
raise ValueError(
|
||||||
|
"If `creates_join_request` is `True`, `member_limit` can't be specified."
|
||||||
|
)
|
||||||
|
|
||||||
data: JSONDict = {'chat_id': chat_id, 'invite_link': invite_link}
|
data: JSONDict = {'chat_id': chat_id, 'invite_link': invite_link}
|
||||||
|
|
||||||
if expire_date is not None:
|
if expire_date is not None:
|
||||||
|
@ -4084,6 +4126,12 @@ class Bot(TelegramObject):
|
||||||
if member_limit is not None:
|
if member_limit is not None:
|
||||||
data['member_limit'] = member_limit
|
data['member_limit'] = member_limit
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
data['name'] = name
|
||||||
|
|
||||||
|
if creates_join_request is not None:
|
||||||
|
data['creates_join_request'] = creates_join_request
|
||||||
|
|
||||||
result = self._post('editChatInviteLink', data, timeout=timeout, api_kwargs=api_kwargs)
|
result = self._post('editChatInviteLink', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
return ChatInviteLink.de_json(result, self) # type: ignore[return-value, arg-type]
|
return ChatInviteLink.de_json(result, self) # type: ignore[return-value, arg-type]
|
||||||
|
@ -4126,6 +4174,80 @@ class Bot(TelegramObject):
|
||||||
|
|
||||||
return ChatInviteLink.de_json(result, self) # type: ignore[return-value, arg-type]
|
return ChatInviteLink.de_json(result, self) # type: ignore[return-value, arg-type]
|
||||||
|
|
||||||
|
@log
|
||||||
|
def approve_chat_join_request(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
user_id: int,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Use this method to approve a chat join request.
|
||||||
|
|
||||||
|
The bot must be an administrator in the chat for this to work and must have the
|
||||||
|
:attr:`telegram.ChatPermissions.can_invite_users` administrator right.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target chat or username
|
||||||
|
of the target channel (in the format ``@channelusername``).
|
||||||
|
user_id (:obj:`int`): Unique identifier of the target user.
|
||||||
|
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 = {'chat_id': chat_id, 'user_id': user_id}
|
||||||
|
|
||||||
|
result = self._post('approveChatJoinRequest', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
return result # type: ignore[return-value]
|
||||||
|
|
||||||
|
@log
|
||||||
|
def decline_chat_join_request(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
user_id: int,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Use this method to decline a chat join request.
|
||||||
|
|
||||||
|
The bot must be an administrator in the chat for this to work and must have the
|
||||||
|
:attr:`telegram.ChatPermissions.can_invite_users` administrator right.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`int` | :obj:`str`): Unique identifier for the target chat or username
|
||||||
|
of the target channel (in the format ``@channelusername``).
|
||||||
|
user_id (:obj:`int`): Unique identifier of the target user.
|
||||||
|
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 = {'chat_id': chat_id, 'user_id': user_id}
|
||||||
|
|
||||||
|
result = self._post('declineChatJoinRequest', data, timeout=timeout, api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
return result # type: ignore[return-value]
|
||||||
|
|
||||||
@log
|
@log
|
||||||
def set_chat_photo(
|
def set_chat_photo(
|
||||||
self,
|
self,
|
||||||
|
@ -5436,11 +5558,15 @@ class Bot(TelegramObject):
|
||||||
exportChatInviteLink = export_chat_invite_link
|
exportChatInviteLink = export_chat_invite_link
|
||||||
"""Alias for :meth:`export_chat_invite_link`"""
|
"""Alias for :meth:`export_chat_invite_link`"""
|
||||||
createChatInviteLink = create_chat_invite_link
|
createChatInviteLink = create_chat_invite_link
|
||||||
"""Alias for :attr:`create_chat_invite_link`"""
|
"""Alias for :meth:`create_chat_invite_link`"""
|
||||||
editChatInviteLink = edit_chat_invite_link
|
editChatInviteLink = edit_chat_invite_link
|
||||||
"""Alias for :attr:`edit_chat_invite_link`"""
|
"""Alias for :meth:`edit_chat_invite_link`"""
|
||||||
revokeChatInviteLink = revoke_chat_invite_link
|
revokeChatInviteLink = revoke_chat_invite_link
|
||||||
"""Alias for :attr:`revoke_chat_invite_link`"""
|
"""Alias for :meth:`revoke_chat_invite_link`"""
|
||||||
|
approveChatJoinRequest = approve_chat_join_request
|
||||||
|
"""Alias for :meth:`approve_chat_join_request`"""
|
||||||
|
declineChatJoinRequest = decline_chat_join_request
|
||||||
|
"""Alias for :meth:`decline_chat_join_request`"""
|
||||||
setChatPhoto = set_chat_photo
|
setChatPhoto = set_chat_photo
|
||||||
"""Alias for :meth:`set_chat_photo`"""
|
"""Alias for :meth:`set_chat_photo`"""
|
||||||
deleteChatPhoto = delete_chat_photo
|
deleteChatPhoto = delete_chat_photo
|
||||||
|
|
|
@ -1524,6 +1524,8 @@ class Chat(TelegramObject):
|
||||||
member_limit: int = None,
|
member_limit: int = None,
|
||||||
timeout: ODVInput[float] = DEFAULT_NONE,
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
|
name: str = None,
|
||||||
|
creates_join_request: bool = None,
|
||||||
) -> 'ChatInviteLink':
|
) -> 'ChatInviteLink':
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
|
||||||
|
@ -1534,6 +1536,10 @@ class Chat(TelegramObject):
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
|
||||||
|
.. versionchanged:: 13.8
|
||||||
|
Edited signature according to the changes of
|
||||||
|
:meth:`telegram.Bot.create_chat_invite_link`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:class:`telegram.ChatInviteLink`
|
:class:`telegram.ChatInviteLink`
|
||||||
|
|
||||||
|
@ -1544,6 +1550,8 @@ class Chat(TelegramObject):
|
||||||
member_limit=member_limit,
|
member_limit=member_limit,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
|
name=name,
|
||||||
|
creates_join_request=creates_join_request,
|
||||||
)
|
)
|
||||||
|
|
||||||
def edit_invite_link(
|
def edit_invite_link(
|
||||||
|
@ -1553,6 +1561,8 @@ class Chat(TelegramObject):
|
||||||
member_limit: int = None,
|
member_limit: int = None,
|
||||||
timeout: ODVInput[float] = DEFAULT_NONE,
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
|
name: str = None,
|
||||||
|
creates_join_request: bool = None,
|
||||||
) -> 'ChatInviteLink':
|
) -> 'ChatInviteLink':
|
||||||
"""Shortcut for::
|
"""Shortcut for::
|
||||||
|
|
||||||
|
@ -1563,6 +1573,9 @@ class Chat(TelegramObject):
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
|
||||||
|
.. versionchanged:: 13.8
|
||||||
|
Edited signature according to the changes of :meth:`telegram.Bot.edit_chat_invite_link`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:class:`telegram.ChatInviteLink`
|
:class:`telegram.ChatInviteLink`
|
||||||
|
|
||||||
|
@ -1574,6 +1587,8 @@ class Chat(TelegramObject):
|
||||||
member_limit=member_limit,
|
member_limit=member_limit,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
|
name=name,
|
||||||
|
creates_join_request=creates_join_request,
|
||||||
)
|
)
|
||||||
|
|
||||||
def revoke_invite_link(
|
def revoke_invite_link(
|
||||||
|
@ -1598,3 +1613,49 @@ class Chat(TelegramObject):
|
||||||
return self.bot.revoke_chat_invite_link(
|
return self.bot.revoke_chat_invite_link(
|
||||||
chat_id=self.id, invite_link=invite_link, timeout=timeout, api_kwargs=api_kwargs
|
chat_id=self.id, invite_link=invite_link, timeout=timeout, api_kwargs=api_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def approve_join_request(
|
||||||
|
self,
|
||||||
|
user_id: int,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
bot.approve_chat_join_request(chat_id=update.effective_chat.id, *args, **kwargs)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.approve_chat_join_request`.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.bot.approve_chat_join_request(
|
||||||
|
chat_id=self.id, user_id=user_id, timeout=timeout, api_kwargs=api_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def decline_join_request(
|
||||||
|
self,
|
||||||
|
user_id: int,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
bot.decline_chat_join_request(chat_id=update.effective_chat.id, *args, **kwargs)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.decline_chat_join_request`.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.bot.decline_chat_join_request(
|
||||||
|
chat_id=self.id, user_id=user_id, timeout=timeout, api_kwargs=api_kwargs
|
||||||
|
)
|
||||||
|
|
|
@ -59,6 +59,10 @@ class ChatAction:
|
||||||
"""
|
"""
|
||||||
UPLOAD_DOCUMENT: ClassVar[str] = constants.CHATACTION_UPLOAD_DOCUMENT
|
UPLOAD_DOCUMENT: ClassVar[str] = constants.CHATACTION_UPLOAD_DOCUMENT
|
||||||
""":const:`telegram.constants.CHATACTION_UPLOAD_DOCUMENT`"""
|
""":const:`telegram.constants.CHATACTION_UPLOAD_DOCUMENT`"""
|
||||||
|
CHOOSE_STICKER: ClassVar[str] = constants.CHATACTION_CHOOSE_STICKER
|
||||||
|
""":const:`telegram.constants.CHOOSE_STICKER`
|
||||||
|
|
||||||
|
.. versionadded:: 13.8"""
|
||||||
UPLOAD_PHOTO: ClassVar[str] = constants.CHATACTION_UPLOAD_PHOTO
|
UPLOAD_PHOTO: ClassVar[str] = constants.CHATACTION_UPLOAD_PHOTO
|
||||||
""":const:`telegram.constants.CHATACTION_UPLOAD_PHOTO`"""
|
""":const:`telegram.constants.CHATACTION_UPLOAD_PHOTO`"""
|
||||||
UPLOAD_VIDEO: ClassVar[str] = constants.CHATACTION_UPLOAD_VIDEO
|
UPLOAD_VIDEO: ClassVar[str] = constants.CHATACTION_UPLOAD_VIDEO
|
||||||
|
|
|
@ -46,6 +46,17 @@ class ChatInviteLink(TelegramObject):
|
||||||
has been expired.
|
has been expired.
|
||||||
member_limit (:obj:`int`, optional): Maximum number of users that can be members of the
|
member_limit (:obj:`int`, optional): Maximum number of users that can be members of the
|
||||||
chat simultaneously after joining the chat via this invite link; 1-99999.
|
chat simultaneously after joining the chat via this invite link; 1-99999.
|
||||||
|
name (:obj:`str`, optional): Invite link name.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
creates_join_request (:obj:`bool`, optional): :obj:`True`, if users joining the chat via
|
||||||
|
the link need to be approved by chat administrators.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
pending_join_request_count (:obj:`int`, optional): Number of pending join requests
|
||||||
|
created using this link.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
invite_link (:obj:`str`): The invite link. If the link was created by another chat
|
invite_link (:obj:`str`): The invite link. If the link was created by another chat
|
||||||
|
@ -57,6 +68,17 @@ class ChatInviteLink(TelegramObject):
|
||||||
has been expired.
|
has been expired.
|
||||||
member_limit (:obj:`int`): Optional. Maximum number of users that can be members
|
member_limit (:obj:`int`): Optional. Maximum number of users that can be members
|
||||||
of the chat simultaneously after joining the chat via this invite link; 1-99999.
|
of the chat simultaneously after joining the chat via this invite link; 1-99999.
|
||||||
|
name (:obj:`str`): Optional. Invite link name.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
creates_join_request (:obj:`bool`): Optional. :obj:`True`, if users joining the chat via
|
||||||
|
the link need to be approved by chat administrators.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
pending_join_request_count (:obj:`int`): Optional. Number of pending join requests
|
||||||
|
created using this link.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -67,6 +89,9 @@ class ChatInviteLink(TelegramObject):
|
||||||
'is_revoked',
|
'is_revoked',
|
||||||
'expire_date',
|
'expire_date',
|
||||||
'member_limit',
|
'member_limit',
|
||||||
|
'name',
|
||||||
|
'creates_join_request',
|
||||||
|
'pending_join_request_count',
|
||||||
'_id_attrs',
|
'_id_attrs',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -78,6 +103,9 @@ class ChatInviteLink(TelegramObject):
|
||||||
is_revoked: bool,
|
is_revoked: bool,
|
||||||
expire_date: datetime.datetime = None,
|
expire_date: datetime.datetime = None,
|
||||||
member_limit: int = None,
|
member_limit: int = None,
|
||||||
|
name: str = None,
|
||||||
|
creates_join_request: bool = None,
|
||||||
|
pending_join_request_count: int = None,
|
||||||
**_kwargs: Any,
|
**_kwargs: Any,
|
||||||
):
|
):
|
||||||
# Required
|
# Required
|
||||||
|
@ -89,7 +117,11 @@ class ChatInviteLink(TelegramObject):
|
||||||
# Optionals
|
# Optionals
|
||||||
self.expire_date = expire_date
|
self.expire_date = expire_date
|
||||||
self.member_limit = int(member_limit) if member_limit is not None else None
|
self.member_limit = int(member_limit) if member_limit is not None else None
|
||||||
|
self.name = name
|
||||||
|
self.creates_join_request = creates_join_request
|
||||||
|
self.pending_join_request_count = (
|
||||||
|
int(pending_join_request_count) if pending_join_request_count is not None else None
|
||||||
|
)
|
||||||
self._id_attrs = (self.invite_link, self.creator, self.is_primary, self.is_revoked)
|
self._id_attrs = (self.invite_link, self.creator, self.is_primary, self.is_revoked)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
153
telegram/chatjoinrequest.py
Normal file
153
telegram/chatjoinrequest.py
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
#!/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/].
|
||||||
|
"""This module contains an object that represents a Telegram ChatJoinRequest."""
|
||||||
|
import datetime
|
||||||
|
from typing import TYPE_CHECKING, Any, Optional
|
||||||
|
|
||||||
|
from telegram import TelegramObject, User, Chat, ChatInviteLink
|
||||||
|
from telegram.utils.helpers import from_timestamp, to_timestamp, DEFAULT_NONE
|
||||||
|
from telegram.utils.types import JSONDict, ODVInput
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from telegram import Bot
|
||||||
|
|
||||||
|
|
||||||
|
class ChatJoinRequest(TelegramObject):
|
||||||
|
"""This object represents a join request sent to a chat.
|
||||||
|
|
||||||
|
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||||
|
considered equal, if their :attr:`chat`, :attr:`from_user` and :attr:`date` are equal.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat (:class:`telegram.Chat`): Chat to which the request was sent.
|
||||||
|
from_user (:class:`telegram.User`): User that sent the join request.
|
||||||
|
date (:class:`datetime.datetime`): Date the request was sent.
|
||||||
|
bio (:obj:`str`, optional): Bio of the user.
|
||||||
|
invite_link (:class:`telegram.ChatInviteLink`, optional): Chat invite link that was used
|
||||||
|
by the user to send the join request.
|
||||||
|
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
chat (:class:`telegram.Chat`): Chat to which the request was sent.
|
||||||
|
from_user (:class:`telegram.User`): User that sent the join request.
|
||||||
|
date (:class:`datetime.datetime`): Date the request was sent.
|
||||||
|
bio (:obj:`str`): Optional. Bio of the user.
|
||||||
|
invite_link (:class:`telegram.ChatInviteLink`): Optional. Chat invite link that was used
|
||||||
|
by the user to send the join request.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
|
'chat',
|
||||||
|
'from_user',
|
||||||
|
'date',
|
||||||
|
'bio',
|
||||||
|
'invite_link',
|
||||||
|
'bot',
|
||||||
|
'_id_attrs',
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
chat: Chat,
|
||||||
|
from_user: User,
|
||||||
|
date: datetime.datetime,
|
||||||
|
bio: str = None,
|
||||||
|
invite_link: ChatInviteLink = None,
|
||||||
|
bot: 'Bot' = None,
|
||||||
|
**_kwargs: Any,
|
||||||
|
):
|
||||||
|
# Required
|
||||||
|
self.chat = chat
|
||||||
|
self.from_user = from_user
|
||||||
|
self.date = date
|
||||||
|
|
||||||
|
# Optionals
|
||||||
|
self.bio = bio
|
||||||
|
self.invite_link = invite_link
|
||||||
|
|
||||||
|
self.bot = bot
|
||||||
|
self._id_attrs = (self.chat, self.from_user, self.date)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['ChatJoinRequest']:
|
||||||
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
data['chat'] = Chat.de_json(data.get('chat'), bot)
|
||||||
|
data['from_user'] = User.de_json(data.get('from'), bot)
|
||||||
|
data['date'] = from_timestamp(data.get('date', None))
|
||||||
|
data['invite_link'] = ChatInviteLink.de_json(data.get('invite_link'), bot)
|
||||||
|
|
||||||
|
return cls(bot=bot, **data)
|
||||||
|
|
||||||
|
def to_dict(self) -> JSONDict:
|
||||||
|
"""See :meth:`telegram.TelegramObject.to_dict`."""
|
||||||
|
data = super().to_dict()
|
||||||
|
|
||||||
|
data['date'] = to_timestamp(self.date)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def approve(
|
||||||
|
self,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
bot.approve_chat_join_request(chat_id=update.effective_chat.id,
|
||||||
|
user_id=update.effective_user.id, *args, **kwargs)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.approve_chat_join_request`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.bot.approve_chat_join_request(
|
||||||
|
chat_id=self.chat.id, user_id=self.from_user.id, timeout=timeout, api_kwargs=api_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def decline(
|
||||||
|
self,
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
bot.decline_chat_join_request(chat_id=update.effective_chat.id,
|
||||||
|
user_id=update.effective_user.id, *args, **kwargs)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.decline_chat_join_request`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.bot.decline_chat_join_request(
|
||||||
|
chat_id=self.chat.id, user_id=self.from_user.id, timeout=timeout, api_kwargs=api_kwargs
|
||||||
|
)
|
|
@ -86,6 +86,9 @@ Attributes:
|
||||||
|
|
||||||
.. versionadded:: 13.5
|
.. versionadded:: 13.5
|
||||||
CHATACTION_UPLOAD_DOCUMENT (:obj:`str`): ``'upload_document'``
|
CHATACTION_UPLOAD_DOCUMENT (:obj:`str`): ``'upload_document'``
|
||||||
|
CHATACTION_CHOOSE_STICKER (:obj:`str`): ``'choose_sticker'``
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
CHATACTION_UPLOAD_PHOTO (:obj:`str`): ``'upload_photo'``
|
CHATACTION_UPLOAD_PHOTO (:obj:`str`): ``'upload_photo'``
|
||||||
CHATACTION_UPLOAD_VIDEO (:obj:`str`): ``'upload_video'``
|
CHATACTION_UPLOAD_VIDEO (:obj:`str`): ``'upload_video'``
|
||||||
CHATACTION_UPLOAD_VIDEO_NOTE (:obj:`str`): ``'upload_video_note'``
|
CHATACTION_UPLOAD_VIDEO_NOTE (:obj:`str`): ``'upload_video_note'``
|
||||||
|
@ -201,9 +204,13 @@ Attributes:
|
||||||
UPDATE_CHAT_MEMBER (:obj:`str`): ``'chat_member'``
|
UPDATE_CHAT_MEMBER (:obj:`str`): ``'chat_member'``
|
||||||
|
|
||||||
.. versionadded:: 13.5
|
.. versionadded:: 13.5
|
||||||
|
UPDATE_CHAT_JOIN_REQUEST (:obj:`str`): ``'chat_join_request'``
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
UPDATE_ALL_TYPES (List[:obj:`str`]): List of all update types.
|
UPDATE_ALL_TYPES (List[:obj:`str`]): List of all update types.
|
||||||
|
|
||||||
.. versionadded:: 13.5
|
.. versionadded:: 13.5
|
||||||
|
.. versionchanged:: 13.8
|
||||||
|
|
||||||
:class:`telegram.BotCommandScope`:
|
:class:`telegram.BotCommandScope`:
|
||||||
|
|
||||||
|
@ -233,7 +240,7 @@ Attributes:
|
||||||
"""
|
"""
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
BOT_API_VERSION: str = '5.3'
|
BOT_API_VERSION: str = '5.4'
|
||||||
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
|
||||||
|
@ -267,6 +274,7 @@ CHATACTION_TYPING: str = 'typing'
|
||||||
CHATACTION_UPLOAD_AUDIO: str = 'upload_audio'
|
CHATACTION_UPLOAD_AUDIO: str = 'upload_audio'
|
||||||
CHATACTION_UPLOAD_VOICE: str = 'upload_voice'
|
CHATACTION_UPLOAD_VOICE: str = 'upload_voice'
|
||||||
CHATACTION_UPLOAD_DOCUMENT: str = 'upload_document'
|
CHATACTION_UPLOAD_DOCUMENT: str = 'upload_document'
|
||||||
|
CHATACTION_CHOOSE_STICKER: str = 'choose_sticker'
|
||||||
CHATACTION_UPLOAD_PHOTO: str = 'upload_photo'
|
CHATACTION_UPLOAD_PHOTO: str = 'upload_photo'
|
||||||
CHATACTION_UPLOAD_VIDEO: str = 'upload_video'
|
CHATACTION_UPLOAD_VIDEO: str = 'upload_video'
|
||||||
CHATACTION_UPLOAD_VIDEO_NOTE: str = 'upload_video_note'
|
CHATACTION_UPLOAD_VIDEO_NOTE: str = 'upload_video_note'
|
||||||
|
@ -353,6 +361,7 @@ UPDATE_POLL = 'poll'
|
||||||
UPDATE_POLL_ANSWER = 'poll_answer'
|
UPDATE_POLL_ANSWER = 'poll_answer'
|
||||||
UPDATE_MY_CHAT_MEMBER = 'my_chat_member'
|
UPDATE_MY_CHAT_MEMBER = 'my_chat_member'
|
||||||
UPDATE_CHAT_MEMBER = 'chat_member'
|
UPDATE_CHAT_MEMBER = 'chat_member'
|
||||||
|
UPDATE_CHAT_JOIN_REQUEST = 'chat_join_request'
|
||||||
UPDATE_ALL_TYPES = [
|
UPDATE_ALL_TYPES = [
|
||||||
UPDATE_MESSAGE,
|
UPDATE_MESSAGE,
|
||||||
UPDATE_EDITED_MESSAGE,
|
UPDATE_EDITED_MESSAGE,
|
||||||
|
@ -367,6 +376,7 @@ UPDATE_ALL_TYPES = [
|
||||||
UPDATE_POLL_ANSWER,
|
UPDATE_POLL_ANSWER,
|
||||||
UPDATE_MY_CHAT_MEMBER,
|
UPDATE_MY_CHAT_MEMBER,
|
||||||
UPDATE_CHAT_MEMBER,
|
UPDATE_CHAT_MEMBER,
|
||||||
|
UPDATE_CHAT_JOIN_REQUEST,
|
||||||
]
|
]
|
||||||
|
|
||||||
BOT_COMMAND_SCOPE_DEFAULT = 'default'
|
BOT_COMMAND_SCOPE_DEFAULT = 'default'
|
||||||
|
|
|
@ -59,6 +59,7 @@ from .messagequeue import DelayQueue
|
||||||
from .pollanswerhandler import PollAnswerHandler
|
from .pollanswerhandler import PollAnswerHandler
|
||||||
from .pollhandler import PollHandler
|
from .pollhandler import PollHandler
|
||||||
from .chatmemberhandler import ChatMemberHandler
|
from .chatmemberhandler import ChatMemberHandler
|
||||||
|
from .chatjoinrequesthandler import ChatJoinRequestHandler
|
||||||
from .defaults import Defaults
|
from .defaults import Defaults
|
||||||
from .callbackdatacache import CallbackDataCache, InvalidCallbackData
|
from .callbackdatacache import CallbackDataCache, InvalidCallbackData
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@ __all__ = (
|
||||||
'CallbackContext',
|
'CallbackContext',
|
||||||
'CallbackDataCache',
|
'CallbackDataCache',
|
||||||
'CallbackQueryHandler',
|
'CallbackQueryHandler',
|
||||||
|
'ChatJoinRequestHandler',
|
||||||
'ChatMemberHandler',
|
'ChatMemberHandler',
|
||||||
'ChosenInlineResultHandler',
|
'ChosenInlineResultHandler',
|
||||||
'CommandHandler',
|
'CommandHandler',
|
||||||
|
|
100
telegram/ext/chatjoinrequesthandler.py
Normal file
100
telegram/ext/chatjoinrequesthandler.py
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#!/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/].
|
||||||
|
"""This module contains the ChatJoinRequestHandler class."""
|
||||||
|
|
||||||
|
|
||||||
|
from telegram import Update
|
||||||
|
|
||||||
|
from .handler import Handler
|
||||||
|
from .utils.types import CCT
|
||||||
|
|
||||||
|
|
||||||
|
class ChatJoinRequestHandler(Handler[Update, CCT]):
|
||||||
|
"""Handler class to handle Telegram updates that contain a chat join request.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
|
||||||
|
can use to keep any data in will be sent to the :attr:`callback` function. Related to
|
||||||
|
either the user or the chat that the update was sent in. For each update from the same user
|
||||||
|
or in the same chat, it will be the same ``dict``.
|
||||||
|
|
||||||
|
Note that this is DEPRECATED, and you should use context based callbacks. See
|
||||||
|
https://git.io/fxJuV for more info.
|
||||||
|
|
||||||
|
Warning:
|
||||||
|
When setting ``run_async`` to :obj:`True`, you cannot rely on adding custom
|
||||||
|
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback (:obj:`callable`): The callback function for this handler. Will be called when
|
||||||
|
:attr:`check_update` has determined that an update should be processed by this handler.
|
||||||
|
Callback signature for context based API:
|
||||||
|
|
||||||
|
``def callback(update: Update, context: CallbackContext)``
|
||||||
|
|
||||||
|
The return value of the callback is usually ignored except for the special case of
|
||||||
|
:class:`telegram.ext.ConversationHandler`.
|
||||||
|
pass_update_queue (:obj:`bool`, optional): If set to :obj:`True`, a keyword argument called
|
||||||
|
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||||
|
instance used by the :class:`telegram.ext.Updater` and :class:`telegram.ext.Dispatcher`
|
||||||
|
that contains new updates which can be used to insert updates. Default is :obj:`False`.
|
||||||
|
DEPRECATED: Please switch to context based callbacks.
|
||||||
|
pass_job_queue (:obj:`bool`, optional): If set to :obj:`True`, a keyword argument called
|
||||||
|
``job_queue`` will be passed to the callback function. It will be a
|
||||||
|
:class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater`
|
||||||
|
which can be used to schedule new jobs. Default is :obj:`False`.
|
||||||
|
DEPRECATED: Please switch to context based callbacks.
|
||||||
|
pass_user_data (:obj:`bool`, optional): If set to :obj:`True`, a keyword argument called
|
||||||
|
``user_data`` will be passed to the callback function. Default is :obj:`False`.
|
||||||
|
DEPRECATED: Please switch to context based callbacks.
|
||||||
|
pass_chat_data (:obj:`bool`, optional): If set to :obj:`True`, a keyword argument called
|
||||||
|
``chat_data`` will be passed to the callback function. Default is :obj:`False`.
|
||||||
|
DEPRECATED: Please switch to context based callbacks.
|
||||||
|
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
|
||||||
|
Defaults to :obj:`False`.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
callback (:obj:`callable`): The callback function for this handler.
|
||||||
|
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
|
||||||
|
passed to the callback function.
|
||||||
|
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
|
||||||
|
the callback function.
|
||||||
|
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
|
||||||
|
the callback function.
|
||||||
|
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
|
||||||
|
the callback function.
|
||||||
|
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def check_update(self, update: object) -> bool:
|
||||||
|
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`
|
||||||
|
|
||||||
|
"""
|
||||||
|
return isinstance(update, Update) and bool(update.chat_join_request)
|
|
@ -31,6 +31,7 @@ from telegram import (
|
||||||
TelegramObject,
|
TelegramObject,
|
||||||
ChatMemberUpdated,
|
ChatMemberUpdated,
|
||||||
constants,
|
constants,
|
||||||
|
ChatJoinRequest,
|
||||||
)
|
)
|
||||||
from telegram.poll import PollAnswer
|
from telegram.poll import PollAnswer
|
||||||
from telegram.utils.types import JSONDict
|
from telegram.utils.types import JSONDict
|
||||||
|
@ -89,6 +90,12 @@ class Update(TelegramObject):
|
||||||
:meth:`telegram.ext.Updater.start_webhook`).
|
:meth:`telegram.ext.Updater.start_webhook`).
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
chat_join_request (:class:`telegram.ChatJoinRequest`, optional): A request to join the
|
||||||
|
chat has been sent. The bot must have the
|
||||||
|
:attr:`telegram.ChatPermissions.can_invite_users` administrator right in the chat to
|
||||||
|
receive these updates.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -122,6 +129,11 @@ class Update(TelegramObject):
|
||||||
:meth:`telegram.ext.Updater.start_webhook`).
|
:meth:`telegram.ext.Updater.start_webhook`).
|
||||||
|
|
||||||
.. versionadded:: 13.4
|
.. versionadded:: 13.4
|
||||||
|
chat_join_request (:class:`telegram.ChatJoinRequest`): Optional. A request to join the
|
||||||
|
chat has been sent. The bot must have the ``'can_invite_users'`` administrator
|
||||||
|
right in the chat to receive these updates.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -143,6 +155,7 @@ class Update(TelegramObject):
|
||||||
'_effective_message',
|
'_effective_message',
|
||||||
'my_chat_member',
|
'my_chat_member',
|
||||||
'chat_member',
|
'chat_member',
|
||||||
|
'chat_join_request',
|
||||||
'_id_attrs',
|
'_id_attrs',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -198,6 +211,10 @@ class Update(TelegramObject):
|
||||||
""":const:`telegram.constants.UPDATE_CHAT_MEMBER`
|
""":const:`telegram.constants.UPDATE_CHAT_MEMBER`
|
||||||
|
|
||||||
.. versionadded:: 13.5"""
|
.. versionadded:: 13.5"""
|
||||||
|
CHAT_JOIN_REQUEST = constants.UPDATE_CHAT_JOIN_REQUEST
|
||||||
|
""":const:`telegram.constants.UPDATE_CHAT_JOIN_REQUEST`
|
||||||
|
|
||||||
|
.. versionadded:: 13.8"""
|
||||||
ALL_TYPES = constants.UPDATE_ALL_TYPES
|
ALL_TYPES = constants.UPDATE_ALL_TYPES
|
||||||
""":const:`telegram.constants.UPDATE_ALL_TYPES`
|
""":const:`telegram.constants.UPDATE_ALL_TYPES`
|
||||||
|
|
||||||
|
@ -219,6 +236,7 @@ class Update(TelegramObject):
|
||||||
poll_answer: PollAnswer = None,
|
poll_answer: PollAnswer = None,
|
||||||
my_chat_member: ChatMemberUpdated = None,
|
my_chat_member: ChatMemberUpdated = None,
|
||||||
chat_member: ChatMemberUpdated = None,
|
chat_member: ChatMemberUpdated = None,
|
||||||
|
chat_join_request: ChatJoinRequest = None,
|
||||||
**_kwargs: Any,
|
**_kwargs: Any,
|
||||||
):
|
):
|
||||||
# Required
|
# Required
|
||||||
|
@ -237,6 +255,7 @@ class Update(TelegramObject):
|
||||||
self.poll_answer = poll_answer
|
self.poll_answer = poll_answer
|
||||||
self.my_chat_member = my_chat_member
|
self.my_chat_member = my_chat_member
|
||||||
self.chat_member = chat_member
|
self.chat_member = chat_member
|
||||||
|
self.chat_join_request = chat_join_request
|
||||||
|
|
||||||
self._effective_user: Optional['User'] = None
|
self._effective_user: Optional['User'] = None
|
||||||
self._effective_chat: Optional['Chat'] = None
|
self._effective_chat: Optional['Chat'] = None
|
||||||
|
@ -286,6 +305,9 @@ class Update(TelegramObject):
|
||||||
elif self.chat_member:
|
elif self.chat_member:
|
||||||
user = self.chat_member.from_user
|
user = self.chat_member.from_user
|
||||||
|
|
||||||
|
elif self.chat_join_request:
|
||||||
|
user = self.chat_join_request.from_user
|
||||||
|
|
||||||
self._effective_user = user
|
self._effective_user = user
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
@ -325,6 +347,9 @@ class Update(TelegramObject):
|
||||||
elif self.chat_member:
|
elif self.chat_member:
|
||||||
chat = self.chat_member.chat
|
chat = self.chat_member.chat
|
||||||
|
|
||||||
|
elif self.chat_join_request:
|
||||||
|
chat = self.chat_join_request.chat
|
||||||
|
|
||||||
self._effective_chat = chat
|
self._effective_chat = chat
|
||||||
return chat
|
return chat
|
||||||
|
|
||||||
|
@ -335,7 +360,9 @@ class Update(TelegramObject):
|
||||||
update this is. Will be :obj:`None` for :attr:`inline_query`,
|
update this is. Will be :obj:`None` for :attr:`inline_query`,
|
||||||
:attr:`chosen_inline_result`, :attr:`callback_query` from inline messages,
|
:attr:`chosen_inline_result`, :attr:`callback_query` from inline messages,
|
||||||
:attr:`shipping_query`, :attr:`pre_checkout_query`, :attr:`poll`,
|
:attr:`shipping_query`, :attr:`pre_checkout_query`, :attr:`poll`,
|
||||||
:attr:`poll_answer`, :attr:`my_chat_member` and :attr:`chat_member`.
|
:attr:`poll_answer`, :attr:`my_chat_member`, :attr:`chat_member` as well as
|
||||||
|
:attr:`chat_join_request` in case the bot is missing the
|
||||||
|
:attr:`telegram.ChatPermissions.can_invite_users` administrator right in the chat.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self._effective_message:
|
if self._effective_message:
|
||||||
|
@ -384,5 +411,6 @@ class Update(TelegramObject):
|
||||||
data['poll_answer'] = PollAnswer.de_json(data.get('poll_answer'), bot)
|
data['poll_answer'] = PollAnswer.de_json(data.get('poll_answer'), bot)
|
||||||
data['my_chat_member'] = ChatMemberUpdated.de_json(data.get('my_chat_member'), bot)
|
data['my_chat_member'] = ChatMemberUpdated.de_json(data.get('my_chat_member'), bot)
|
||||||
data['chat_member'] = ChatMemberUpdated.de_json(data.get('chat_member'), bot)
|
data['chat_member'] = ChatMemberUpdated.de_json(data.get('chat_member'), bot)
|
||||||
|
data['chat_join_request'] = ChatJoinRequest.de_json(data.get('chat_join_request'), bot)
|
||||||
|
|
||||||
return cls(**data)
|
return cls(**data)
|
||||||
|
|
|
@ -1140,3 +1140,49 @@ class User(TelegramObject):
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def approve_join_request(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
bot.approve_chat_join_request(user_id=update.effective_user.id, *args, **kwargs)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.approve_chat_join_request`.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.bot.approve_chat_join_request(
|
||||||
|
user_id=self.id, chat_id=chat_id, timeout=timeout, api_kwargs=api_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
def decline_join_request(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: JSONDict = None,
|
||||||
|
) -> bool:
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
bot.decline_chat_join_request(user_id=update.effective_user.id, *args, **kwargs)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.decline_chat_join_request`.
|
||||||
|
|
||||||
|
.. versionadded:: 13.8
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.bot.decline_chat_join_request(
|
||||||
|
user_id=self.id, chat_id=chat_id, timeout=timeout, api_kwargs=api_kwargs
|
||||||
|
)
|
||||||
|
|
|
@ -718,6 +718,7 @@ class TestBot:
|
||||||
ChatAction.UPLOAD_VIDEO,
|
ChatAction.UPLOAD_VIDEO,
|
||||||
ChatAction.UPLOAD_VIDEO_NOTE,
|
ChatAction.UPLOAD_VIDEO_NOTE,
|
||||||
ChatAction.UPLOAD_VOICE,
|
ChatAction.UPLOAD_VOICE,
|
||||||
|
ChatAction.CHOOSE_STICKER,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_send_chat_action(self, bot, chat_id, chat_action):
|
def test_send_chat_action(self, bot, chat_id, chat_action):
|
||||||
|
@ -1696,6 +1697,37 @@ class TestBot:
|
||||||
assert isinstance(invite_link, str)
|
assert isinstance(invite_link, str)
|
||||||
assert invite_link != ''
|
assert invite_link != ''
|
||||||
|
|
||||||
|
def test_create_edit_invite_link_mutually_exclusive_arguments(self, bot, channel_id):
|
||||||
|
data = {'chat_id': channel_id, 'member_limit': 17, 'creates_join_request': True}
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="`member_limit` can't be specified"):
|
||||||
|
bot.create_chat_invite_link(**data)
|
||||||
|
|
||||||
|
data.update({'invite_link': 'https://invite.link'})
|
||||||
|
with pytest.raises(ValueError, match="`member_limit` can't be specified"):
|
||||||
|
bot.edit_chat_invite_link(**data)
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
@pytest.mark.parametrize('creates_join_request', [True, False])
|
||||||
|
@pytest.mark.parametrize('name', [None, 'name'])
|
||||||
|
def test_create_chat_invite_link_basics(self, bot, creates_join_request, name, channel_id):
|
||||||
|
data = {}
|
||||||
|
if creates_join_request:
|
||||||
|
data['creates_join_request'] = True
|
||||||
|
if name:
|
||||||
|
data['name'] = name
|
||||||
|
invite_link = bot.create_chat_invite_link(chat_id=channel_id, **data)
|
||||||
|
|
||||||
|
assert invite_link.member_limit is None
|
||||||
|
assert invite_link.expire_date is None
|
||||||
|
assert invite_link.creates_join_request == creates_join_request
|
||||||
|
assert invite_link.name == name
|
||||||
|
|
||||||
|
revoked_link = bot.revoke_chat_invite_link(
|
||||||
|
chat_id=channel_id, invite_link=invite_link.invite_link
|
||||||
|
)
|
||||||
|
assert revoked_link.is_revoked
|
||||||
|
|
||||||
@flaky(3, 1)
|
@flaky(3, 1)
|
||||||
@pytest.mark.parametrize('datetime', argvalues=[True, False], ids=['datetime', 'integer'])
|
@pytest.mark.parametrize('datetime', argvalues=[True, False], ids=['datetime', 'integer'])
|
||||||
def test_advanced_chat_invite_links(self, bot, channel_id, datetime):
|
def test_advanced_chat_invite_links(self, bot, channel_id, datetime):
|
||||||
|
@ -1720,12 +1752,29 @@ class TestBot:
|
||||||
aware_time_in_future = pytz.UTC.localize(time_in_future)
|
aware_time_in_future = pytz.UTC.localize(time_in_future)
|
||||||
|
|
||||||
edited_invite_link = bot.edit_chat_invite_link(
|
edited_invite_link = bot.edit_chat_invite_link(
|
||||||
channel_id, invite_link.invite_link, expire_date=expire_time, member_limit=20
|
channel_id,
|
||||||
|
invite_link.invite_link,
|
||||||
|
expire_date=expire_time,
|
||||||
|
member_limit=20,
|
||||||
|
name='NewName',
|
||||||
)
|
)
|
||||||
assert edited_invite_link.invite_link == invite_link.invite_link
|
assert edited_invite_link.invite_link == invite_link.invite_link
|
||||||
assert pytest.approx(edited_invite_link.expire_date == aware_time_in_future)
|
assert pytest.approx(edited_invite_link.expire_date == aware_time_in_future)
|
||||||
|
assert edited_invite_link.name == 'NewName'
|
||||||
assert edited_invite_link.member_limit == 20
|
assert edited_invite_link.member_limit == 20
|
||||||
|
|
||||||
|
edited_invite_link = bot.edit_chat_invite_link(
|
||||||
|
channel_id,
|
||||||
|
invite_link.invite_link,
|
||||||
|
name='EvenNewerName',
|
||||||
|
creates_join_request=True,
|
||||||
|
)
|
||||||
|
assert edited_invite_link.invite_link == invite_link.invite_link
|
||||||
|
assert pytest.approx(edited_invite_link.expire_date == aware_time_in_future)
|
||||||
|
assert edited_invite_link.name == 'EvenNewerName'
|
||||||
|
assert edited_invite_link.creates_join_request is True
|
||||||
|
assert edited_invite_link.member_limit is None
|
||||||
|
|
||||||
revoked_invite_link = bot.revoke_chat_invite_link(channel_id, invite_link.invite_link)
|
revoked_invite_link = bot.revoke_chat_invite_link(channel_id, invite_link.invite_link)
|
||||||
assert revoked_invite_link.invite_link == invite_link.invite_link
|
assert revoked_invite_link.invite_link == invite_link.invite_link
|
||||||
assert revoked_invite_link.is_revoked is True
|
assert revoked_invite_link.is_revoked is True
|
||||||
|
@ -1750,16 +1799,49 @@ class TestBot:
|
||||||
time_in_future = aware_expire_date.replace(tzinfo=None)
|
time_in_future = aware_expire_date.replace(tzinfo=None)
|
||||||
|
|
||||||
edited_invite_link = tz_bot.edit_chat_invite_link(
|
edited_invite_link = tz_bot.edit_chat_invite_link(
|
||||||
channel_id, invite_link.invite_link, expire_date=time_in_future, member_limit=20
|
channel_id,
|
||||||
|
invite_link.invite_link,
|
||||||
|
expire_date=time_in_future,
|
||||||
|
member_limit=20,
|
||||||
|
name='NewName',
|
||||||
)
|
)
|
||||||
assert edited_invite_link.invite_link == invite_link.invite_link
|
assert edited_invite_link.invite_link == invite_link.invite_link
|
||||||
assert pytest.approx(edited_invite_link.expire_date == aware_expire_date)
|
assert pytest.approx(edited_invite_link.expire_date == aware_expire_date)
|
||||||
|
assert edited_invite_link.name == 'NewName'
|
||||||
assert edited_invite_link.member_limit == 20
|
assert edited_invite_link.member_limit == 20
|
||||||
|
|
||||||
|
edited_invite_link = tz_bot.edit_chat_invite_link(
|
||||||
|
channel_id,
|
||||||
|
invite_link.invite_link,
|
||||||
|
name='EvenNewerName',
|
||||||
|
creates_join_request=True,
|
||||||
|
)
|
||||||
|
assert edited_invite_link.invite_link == invite_link.invite_link
|
||||||
|
assert pytest.approx(edited_invite_link.expire_date == aware_expire_date)
|
||||||
|
assert edited_invite_link.name == 'EvenNewerName'
|
||||||
|
assert edited_invite_link.creates_join_request is True
|
||||||
|
assert edited_invite_link.member_limit is None
|
||||||
|
|
||||||
revoked_invite_link = tz_bot.revoke_chat_invite_link(channel_id, invite_link.invite_link)
|
revoked_invite_link = tz_bot.revoke_chat_invite_link(channel_id, invite_link.invite_link)
|
||||||
assert revoked_invite_link.invite_link == invite_link.invite_link
|
assert revoked_invite_link.invite_link == invite_link.invite_link
|
||||||
assert revoked_invite_link.is_revoked is True
|
assert revoked_invite_link.is_revoked is True
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
def test_approve_chat_join_request(self, bot, chat_id, channel_id):
|
||||||
|
# TODO: Need incoming join request to properly test
|
||||||
|
# Since we can't create join requests on the fly, we just tests the call to TG
|
||||||
|
# by checking that it complains about approving a user who is already in the chat
|
||||||
|
with pytest.raises(BadRequest, match='User_already_participant'):
|
||||||
|
bot.approve_chat_join_request(chat_id=channel_id, user_id=chat_id)
|
||||||
|
|
||||||
|
@flaky(3, 1)
|
||||||
|
def test_decline_chat_join_request(self, bot, chat_id, channel_id):
|
||||||
|
# TODO: Need incoming join request to properly test
|
||||||
|
# Since we can't create join requests on the fly, we just tests the call to TG
|
||||||
|
# by checking that it complains about declining a user who is already in the chat
|
||||||
|
with pytest.raises(BadRequest, match='User_already_participant'):
|
||||||
|
bot.decline_chat_join_request(chat_id=channel_id, user_id=chat_id)
|
||||||
|
|
||||||
@flaky(3, 1)
|
@flaky(3, 1)
|
||||||
def test_set_chat_photo(self, bot, channel_id):
|
def test_set_chat_photo(self, bot, channel_id):
|
||||||
def func():
|
def func():
|
||||||
|
|
|
@ -636,6 +636,36 @@ class TestChat:
|
||||||
monkeypatch.setattr(chat.bot, 'revoke_chat_invite_link', make_assertion)
|
monkeypatch.setattr(chat.bot, 'revoke_chat_invite_link', make_assertion)
|
||||||
assert chat.revoke_invite_link(invite_link=link)
|
assert chat.revoke_invite_link(invite_link=link)
|
||||||
|
|
||||||
|
def test_approve_join_request(self, monkeypatch, chat):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
return kwargs['chat_id'] == chat.id and kwargs['user_id'] == 42
|
||||||
|
|
||||||
|
assert check_shortcut_signature(
|
||||||
|
Chat.approve_join_request, Bot.approve_chat_join_request, ['chat_id'], []
|
||||||
|
)
|
||||||
|
assert check_shortcut_call(
|
||||||
|
chat.approve_join_request, chat.bot, 'approve_chat_join_request'
|
||||||
|
)
|
||||||
|
assert check_defaults_handling(chat.approve_join_request, chat.bot)
|
||||||
|
|
||||||
|
monkeypatch.setattr(chat.bot, 'approve_chat_join_request', make_assertion)
|
||||||
|
assert chat.approve_join_request(user_id=42)
|
||||||
|
|
||||||
|
def test_decline_join_request(self, monkeypatch, chat):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
return kwargs['chat_id'] == chat.id and kwargs['user_id'] == 42
|
||||||
|
|
||||||
|
assert check_shortcut_signature(
|
||||||
|
Chat.decline_join_request, Bot.decline_chat_join_request, ['chat_id'], []
|
||||||
|
)
|
||||||
|
assert check_shortcut_call(
|
||||||
|
chat.decline_join_request, chat.bot, 'decline_chat_join_request'
|
||||||
|
)
|
||||||
|
assert check_defaults_handling(chat.decline_join_request, chat.bot)
|
||||||
|
|
||||||
|
monkeypatch.setattr(chat.bot, 'decline_chat_join_request', make_assertion)
|
||||||
|
assert chat.decline_join_request(user_id=42)
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
a = Chat(self.id_, self.title, self.type_)
|
a = Chat(self.id_, self.title, self.type_)
|
||||||
b = Chat(self.id_, self.title, self.type_)
|
b = Chat(self.id_, self.title, self.type_)
|
||||||
|
|
|
@ -38,6 +38,8 @@ def invite_link(creator):
|
||||||
TestChatInviteLink.revoked,
|
TestChatInviteLink.revoked,
|
||||||
expire_date=TestChatInviteLink.expire_date,
|
expire_date=TestChatInviteLink.expire_date,
|
||||||
member_limit=TestChatInviteLink.member_limit,
|
member_limit=TestChatInviteLink.member_limit,
|
||||||
|
name=TestChatInviteLink.name,
|
||||||
|
pending_join_request_count=TestChatInviteLink.pending_join_request_count,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +50,8 @@ class TestChatInviteLink:
|
||||||
revoked = False
|
revoked = False
|
||||||
expire_date = datetime.datetime.utcnow()
|
expire_date = datetime.datetime.utcnow()
|
||||||
member_limit = 42
|
member_limit = 42
|
||||||
|
name = 'LinkName'
|
||||||
|
pending_join_request_count = 42
|
||||||
|
|
||||||
def test_slot_behaviour(self, recwarn, mro_slots, invite_link):
|
def test_slot_behaviour(self, recwarn, mro_slots, invite_link):
|
||||||
for attr in invite_link.__slots__:
|
for attr in invite_link.__slots__:
|
||||||
|
@ -79,7 +83,9 @@ class TestChatInviteLink:
|
||||||
'is_primary': self.primary,
|
'is_primary': self.primary,
|
||||||
'is_revoked': self.revoked,
|
'is_revoked': self.revoked,
|
||||||
'expire_date': to_timestamp(self.expire_date),
|
'expire_date': to_timestamp(self.expire_date),
|
||||||
'member_limit': self.member_limit,
|
'member_limit': str(self.member_limit),
|
||||||
|
'name': self.name,
|
||||||
|
'pending_join_request_count': str(self.pending_join_request_count),
|
||||||
}
|
}
|
||||||
|
|
||||||
invite_link = ChatInviteLink.de_json(json_dict, bot)
|
invite_link = ChatInviteLink.de_json(json_dict, bot)
|
||||||
|
@ -91,6 +97,8 @@ class TestChatInviteLink:
|
||||||
assert pytest.approx(invite_link.expire_date == self.expire_date)
|
assert pytest.approx(invite_link.expire_date == self.expire_date)
|
||||||
assert to_timestamp(invite_link.expire_date) == to_timestamp(self.expire_date)
|
assert to_timestamp(invite_link.expire_date) == to_timestamp(self.expire_date)
|
||||||
assert invite_link.member_limit == self.member_limit
|
assert invite_link.member_limit == self.member_limit
|
||||||
|
assert invite_link.name == self.name
|
||||||
|
assert invite_link.pending_join_request_count == self.pending_join_request_count
|
||||||
|
|
||||||
def test_to_dict(self, invite_link):
|
def test_to_dict(self, invite_link):
|
||||||
invite_link_dict = invite_link.to_dict()
|
invite_link_dict = invite_link.to_dict()
|
||||||
|
@ -101,6 +109,8 @@ class TestChatInviteLink:
|
||||||
assert invite_link_dict['is_revoked'] == self.revoked
|
assert invite_link_dict['is_revoked'] == self.revoked
|
||||||
assert invite_link_dict['expire_date'] == to_timestamp(self.expire_date)
|
assert invite_link_dict['expire_date'] == to_timestamp(self.expire_date)
|
||||||
assert invite_link_dict['member_limit'] == self.member_limit
|
assert invite_link_dict['member_limit'] == self.member_limit
|
||||||
|
assert invite_link_dict['name'] == self.name
|
||||||
|
assert invite_link_dict['pending_join_request_count'] == self.pending_join_request_count
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
a = ChatInviteLink("link", User(1, '', False), True, True)
|
a = ChatInviteLink("link", User(1, '', False), True, True)
|
||||||
|
|
158
tests/test_chatjoinrequest.py
Normal file
158
tests/test_chatjoinrequest.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
#!/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/].
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
from telegram import ChatJoinRequest, User, Chat, ChatInviteLink, Bot
|
||||||
|
from telegram.utils.helpers import to_timestamp
|
||||||
|
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def time():
|
||||||
|
return datetime.datetime.now(tz=pytz.utc)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def chat_join_request(bot, time):
|
||||||
|
return ChatJoinRequest(
|
||||||
|
chat=TestChatJoinRequest.chat,
|
||||||
|
from_user=TestChatJoinRequest.from_user,
|
||||||
|
date=time,
|
||||||
|
bio=TestChatJoinRequest.bio,
|
||||||
|
invite_link=TestChatJoinRequest.invite_link,
|
||||||
|
bot=bot,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestChatJoinRequest:
|
||||||
|
chat = Chat(1, Chat.SUPERGROUP)
|
||||||
|
from_user = User(2, 'first_name', False)
|
||||||
|
bio = 'bio'
|
||||||
|
invite_link = ChatInviteLink(
|
||||||
|
'https://invite.link',
|
||||||
|
User(42, 'creator', False),
|
||||||
|
name='InviteLink',
|
||||||
|
is_revoked=False,
|
||||||
|
is_primary=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_slot_behaviour(self, chat_join_request, recwarn, mro_slots):
|
||||||
|
inst = chat_join_request
|
||||||
|
for attr in inst.__slots__:
|
||||||
|
assert getattr(inst, attr, 'err') != 'err', f"got extra slot '{attr}'"
|
||||||
|
assert not inst.__dict__, f"got missing slot(s): {inst.__dict__}"
|
||||||
|
assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
|
||||||
|
inst.custom, inst.bio = 'should give warning', self.bio
|
||||||
|
assert len(recwarn) == 1 and 'custom' in str(recwarn[0].message), recwarn.list
|
||||||
|
|
||||||
|
def test_de_json(self, bot, time):
|
||||||
|
json_dict = {
|
||||||
|
'chat': self.chat.to_dict(),
|
||||||
|
'from': self.from_user.to_dict(),
|
||||||
|
'date': to_timestamp(time),
|
||||||
|
}
|
||||||
|
chat_join_request = ChatJoinRequest.de_json(json_dict, bot)
|
||||||
|
|
||||||
|
assert chat_join_request.chat == self.chat
|
||||||
|
assert chat_join_request.from_user == self.from_user
|
||||||
|
assert pytest.approx(chat_join_request.date == time)
|
||||||
|
assert to_timestamp(chat_join_request.date) == to_timestamp(time)
|
||||||
|
|
||||||
|
json_dict.update({'bio': self.bio, 'invite_link': self.invite_link.to_dict()})
|
||||||
|
chat_join_request = ChatJoinRequest.de_json(json_dict, bot)
|
||||||
|
|
||||||
|
assert chat_join_request.chat == self.chat
|
||||||
|
assert chat_join_request.from_user == self.from_user
|
||||||
|
assert pytest.approx(chat_join_request.date == time)
|
||||||
|
assert to_timestamp(chat_join_request.date) == to_timestamp(time)
|
||||||
|
assert chat_join_request.bio == self.bio
|
||||||
|
assert chat_join_request.invite_link == self.invite_link
|
||||||
|
|
||||||
|
def test_to_dict(self, chat_join_request, time):
|
||||||
|
chat_join_request_dict = chat_join_request.to_dict()
|
||||||
|
|
||||||
|
assert isinstance(chat_join_request_dict, dict)
|
||||||
|
assert chat_join_request_dict['chat'] == chat_join_request.chat.to_dict()
|
||||||
|
assert chat_join_request_dict['from'] == chat_join_request.from_user.to_dict()
|
||||||
|
assert chat_join_request_dict['date'] == to_timestamp(chat_join_request.date)
|
||||||
|
assert chat_join_request_dict['bio'] == chat_join_request.bio
|
||||||
|
assert chat_join_request_dict['invite_link'] == chat_join_request.invite_link.to_dict()
|
||||||
|
|
||||||
|
def test_equality(self, chat_join_request, time):
|
||||||
|
a = chat_join_request
|
||||||
|
b = ChatJoinRequest(self.chat, self.from_user, time)
|
||||||
|
c = ChatJoinRequest(self.chat, self.from_user, time, bio='bio')
|
||||||
|
d = ChatJoinRequest(self.chat, self.from_user, time + datetime.timedelta(1))
|
||||||
|
e = ChatJoinRequest(self.chat, User(-1, 'last_name', True), time)
|
||||||
|
f = User(456, '', False)
|
||||||
|
|
||||||
|
assert a == b
|
||||||
|
assert hash(a) == hash(b)
|
||||||
|
assert a is not 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 a != f
|
||||||
|
assert hash(a) != hash(f)
|
||||||
|
|
||||||
|
def test_approve(self, monkeypatch, chat_join_request):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
chat_id_test = kwargs['chat_id'] == chat_join_request.chat.id
|
||||||
|
user_id_test = kwargs['user_id'] == chat_join_request.from_user.id
|
||||||
|
|
||||||
|
return chat_id_test and user_id_test
|
||||||
|
|
||||||
|
assert check_shortcut_signature(
|
||||||
|
ChatJoinRequest.approve, Bot.approve_chat_join_request, ['chat_id', 'user_id'], []
|
||||||
|
)
|
||||||
|
assert check_shortcut_call(
|
||||||
|
chat_join_request.approve, chat_join_request.bot, 'approve_chat_join_request'
|
||||||
|
)
|
||||||
|
assert check_defaults_handling(chat_join_request.approve, chat_join_request.bot)
|
||||||
|
|
||||||
|
monkeypatch.setattr(chat_join_request.bot, 'approve_chat_join_request', make_assertion)
|
||||||
|
assert chat_join_request.approve()
|
||||||
|
|
||||||
|
def test_decline(self, monkeypatch, chat_join_request):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
chat_id_test = kwargs['chat_id'] == chat_join_request.chat.id
|
||||||
|
user_id_test = kwargs['user_id'] == chat_join_request.from_user.id
|
||||||
|
|
||||||
|
return chat_id_test and user_id_test
|
||||||
|
|
||||||
|
assert check_shortcut_signature(
|
||||||
|
ChatJoinRequest.decline, Bot.decline_chat_join_request, ['chat_id', 'user_id'], []
|
||||||
|
)
|
||||||
|
assert check_shortcut_call(
|
||||||
|
chat_join_request.decline, chat_join_request.bot, 'decline_chat_join_request'
|
||||||
|
)
|
||||||
|
assert check_defaults_handling(chat_join_request.decline, chat_join_request.bot)
|
||||||
|
|
||||||
|
monkeypatch.setattr(chat_join_request.bot, 'decline_chat_join_request', make_assertion)
|
||||||
|
assert chat_join_request.decline()
|
219
tests/test_chatjoinrequesthandler.py
Normal file
219
tests/test_chatjoinrequesthandler.py
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# A library that provides a Python interface to the Telegram Bot API
|
||||||
|
# Copyright (C) 2015-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/].
|
||||||
|
import datetime
|
||||||
|
from queue import Queue
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
from telegram import (
|
||||||
|
Update,
|
||||||
|
Bot,
|
||||||
|
Message,
|
||||||
|
User,
|
||||||
|
Chat,
|
||||||
|
CallbackQuery,
|
||||||
|
ChosenInlineResult,
|
||||||
|
ShippingQuery,
|
||||||
|
PreCheckoutQuery,
|
||||||
|
ChatJoinRequest,
|
||||||
|
ChatInviteLink,
|
||||||
|
)
|
||||||
|
from telegram.ext import CallbackContext, JobQueue, ChatJoinRequestHandler
|
||||||
|
|
||||||
|
|
||||||
|
message = Message(1, None, Chat(1, ''), from_user=User(1, '', False), text='Text')
|
||||||
|
|
||||||
|
params = [
|
||||||
|
{'message': message},
|
||||||
|
{'edited_message': message},
|
||||||
|
{'callback_query': CallbackQuery(1, User(1, '', False), 'chat', message=message)},
|
||||||
|
{'channel_post': message},
|
||||||
|
{'edited_channel_post': message},
|
||||||
|
{'chosen_inline_result': ChosenInlineResult('id', User(1, '', False), '')},
|
||||||
|
{'shipping_query': ShippingQuery('id', User(1, '', False), '', None)},
|
||||||
|
{'pre_checkout_query': PreCheckoutQuery('id', User(1, '', False), '', 0, '')},
|
||||||
|
{'callback_query': CallbackQuery(1, User(1, '', False), 'chat')},
|
||||||
|
]
|
||||||
|
|
||||||
|
ids = (
|
||||||
|
'message',
|
||||||
|
'edited_message',
|
||||||
|
'callback_query',
|
||||||
|
'channel_post',
|
||||||
|
'edited_channel_post',
|
||||||
|
'chosen_inline_result',
|
||||||
|
'shipping_query',
|
||||||
|
'pre_checkout_query',
|
||||||
|
'callback_query_without_message',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class', params=params, ids=ids)
|
||||||
|
def false_update(request):
|
||||||
|
return Update(update_id=2, **request.param)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def time():
|
||||||
|
return datetime.datetime.now(tz=pytz.utc)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def chat_join_request(time, bot):
|
||||||
|
return ChatJoinRequest(
|
||||||
|
chat=Chat(1, Chat.SUPERGROUP),
|
||||||
|
from_user=User(2, 'first_name', False),
|
||||||
|
date=time,
|
||||||
|
bio='bio',
|
||||||
|
invite_link=ChatInviteLink(
|
||||||
|
'https://invite.link',
|
||||||
|
User(42, 'creator', False),
|
||||||
|
name='InviteLink',
|
||||||
|
is_revoked=False,
|
||||||
|
is_primary=False,
|
||||||
|
),
|
||||||
|
bot=bot,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def chat_join_request_update(bot, chat_join_request):
|
||||||
|
return Update(0, chat_join_request=chat_join_request)
|
||||||
|
|
||||||
|
|
||||||
|
class TestChatJoinRequestHandler:
|
||||||
|
test_flag = False
|
||||||
|
|
||||||
|
def test_slot_behaviour(self, recwarn, mro_slots):
|
||||||
|
action = ChatJoinRequestHandler(self.callback_basic)
|
||||||
|
for attr in action.__slots__:
|
||||||
|
assert getattr(action, attr, 'err') != 'err', f"got extra slot '{attr}'"
|
||||||
|
assert not action.__dict__, f"got missing slot(s): {action.__dict__}"
|
||||||
|
assert len(mro_slots(action)) == len(set(mro_slots(action))), "duplicate slot"
|
||||||
|
action.custom = 'should give warning'
|
||||||
|
assert len(recwarn) == 1 and 'custom' in str(recwarn[0].message), recwarn.list
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def reset(self):
|
||||||
|
self.test_flag = False
|
||||||
|
|
||||||
|
def callback_basic(self, bot, update):
|
||||||
|
test_bot = isinstance(bot, Bot)
|
||||||
|
test_update = isinstance(update, Update)
|
||||||
|
self.test_flag = test_bot and test_update
|
||||||
|
|
||||||
|
def callback_data_1(self, bot, update, user_data=None, chat_data=None):
|
||||||
|
self.test_flag = (user_data is not None) or (chat_data is not None)
|
||||||
|
|
||||||
|
def callback_data_2(self, bot, update, user_data=None, chat_data=None):
|
||||||
|
self.test_flag = (user_data is not None) and (chat_data is not None)
|
||||||
|
|
||||||
|
def callback_queue_1(self, bot, update, job_queue=None, update_queue=None):
|
||||||
|
self.test_flag = (job_queue is not None) or (update_queue is not None)
|
||||||
|
|
||||||
|
def callback_queue_2(self, bot, update, job_queue=None, update_queue=None):
|
||||||
|
self.test_flag = (job_queue is not None) and (update_queue is not None)
|
||||||
|
|
||||||
|
def callback_context(self, update, context):
|
||||||
|
self.test_flag = (
|
||||||
|
isinstance(context, CallbackContext)
|
||||||
|
and isinstance(context.bot, Bot)
|
||||||
|
and isinstance(update, Update)
|
||||||
|
and isinstance(context.update_queue, Queue)
|
||||||
|
and isinstance(context.job_queue, JobQueue)
|
||||||
|
and isinstance(context.user_data, dict)
|
||||||
|
and isinstance(context.chat_data, dict)
|
||||||
|
and isinstance(context.bot_data, dict)
|
||||||
|
and isinstance(
|
||||||
|
update.chat_join_request,
|
||||||
|
ChatJoinRequest,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_basic(self, dp, chat_join_request_update):
|
||||||
|
handler = ChatJoinRequestHandler(self.callback_basic)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
assert handler.check_update(chat_join_request_update)
|
||||||
|
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
def test_pass_user_or_chat_data(self, dp, chat_join_request_update):
|
||||||
|
handler = ChatJoinRequestHandler(self.callback_data_1, pass_user_data=True)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
dp.remove_handler(handler)
|
||||||
|
handler = ChatJoinRequestHandler(self.callback_data_1, pass_chat_data=True)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
self.test_flag = False
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
dp.remove_handler(handler)
|
||||||
|
handler = ChatJoinRequestHandler(
|
||||||
|
self.callback_data_2, pass_chat_data=True, pass_user_data=True
|
||||||
|
)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
self.test_flag = False
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
def test_pass_job_or_update_queue(self, dp, chat_join_request_update):
|
||||||
|
handler = ChatJoinRequestHandler(self.callback_queue_1, pass_job_queue=True)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
dp.remove_handler(handler)
|
||||||
|
handler = ChatJoinRequestHandler(self.callback_queue_1, pass_update_queue=True)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
self.test_flag = False
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
dp.remove_handler(handler)
|
||||||
|
handler = ChatJoinRequestHandler(
|
||||||
|
self.callback_queue_2, pass_job_queue=True, pass_update_queue=True
|
||||||
|
)
|
||||||
|
dp.add_handler(handler)
|
||||||
|
|
||||||
|
self.test_flag = False
|
||||||
|
dp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
||||||
|
|
||||||
|
def test_other_update_types(self, false_update):
|
||||||
|
handler = ChatJoinRequestHandler(self.callback_basic)
|
||||||
|
assert not handler.check_update(false_update)
|
||||||
|
assert not handler.check_update(True)
|
||||||
|
|
||||||
|
def test_context(self, cdp, chat_join_request_update):
|
||||||
|
handler = ChatJoinRequestHandler(callback=self.callback_context)
|
||||||
|
cdp.add_handler(handler)
|
||||||
|
|
||||||
|
cdp.process_update(chat_join_request_update)
|
||||||
|
assert self.test_flag
|
|
@ -34,6 +34,7 @@ from telegram import (
|
||||||
PollOption,
|
PollOption,
|
||||||
ChatMemberUpdated,
|
ChatMemberUpdated,
|
||||||
ChatMember,
|
ChatMember,
|
||||||
|
ChatJoinRequest,
|
||||||
)
|
)
|
||||||
from telegram.poll import PollAnswer
|
from telegram.poll import PollAnswer
|
||||||
from telegram.utils.helpers import from_timestamp
|
from telegram.utils.helpers import from_timestamp
|
||||||
|
@ -47,6 +48,14 @@ chat_member_updated = ChatMemberUpdated(
|
||||||
ChatMember(User(1, '', False), ChatMember.CREATOR),
|
ChatMember(User(1, '', False), ChatMember.CREATOR),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
chat_join_request = ChatJoinRequest(
|
||||||
|
chat=Chat(1, Chat.SUPERGROUP),
|
||||||
|
from_user=User(1, 'first_name', False),
|
||||||
|
date=from_timestamp(int(time.time())),
|
||||||
|
bio='bio',
|
||||||
|
)
|
||||||
|
|
||||||
params = [
|
params = [
|
||||||
{'message': message},
|
{'message': message},
|
||||||
{'edited_message': message},
|
{'edited_message': message},
|
||||||
|
@ -57,11 +66,13 @@ params = [
|
||||||
{'chosen_inline_result': ChosenInlineResult('id', User(1, '', False), '')},
|
{'chosen_inline_result': ChosenInlineResult('id', User(1, '', False), '')},
|
||||||
{'shipping_query': ShippingQuery('id', User(1, '', False), '', None)},
|
{'shipping_query': ShippingQuery('id', User(1, '', False), '', None)},
|
||||||
{'pre_checkout_query': PreCheckoutQuery('id', User(1, '', False), '', 0, '')},
|
{'pre_checkout_query': PreCheckoutQuery('id', User(1, '', False), '', 0, '')},
|
||||||
{'callback_query': CallbackQuery(1, User(1, '', False), 'chat')},
|
|
||||||
{'poll': Poll('id', '?', [PollOption('.', 1)], False, False, False, Poll.REGULAR, True)},
|
{'poll': Poll('id', '?', [PollOption('.', 1)], False, False, False, Poll.REGULAR, True)},
|
||||||
{'poll_answer': PollAnswer("id", User(1, '', False), [1])},
|
{'poll_answer': PollAnswer("id", User(1, '', False), [1])},
|
||||||
{'my_chat_member': chat_member_updated},
|
{'my_chat_member': chat_member_updated},
|
||||||
{'chat_member': chat_member_updated},
|
{'chat_member': chat_member_updated},
|
||||||
|
{'chat_join_request': chat_join_request},
|
||||||
|
# Must be last to conform with `ids` below!
|
||||||
|
{'callback_query': CallbackQuery(1, User(1, '', False), 'chat')},
|
||||||
]
|
]
|
||||||
|
|
||||||
all_types = (
|
all_types = (
|
||||||
|
@ -78,6 +89,7 @@ all_types = (
|
||||||
'poll_answer',
|
'poll_answer',
|
||||||
'my_chat_member',
|
'my_chat_member',
|
||||||
'chat_member',
|
'chat_member',
|
||||||
|
'chat_join_request',
|
||||||
)
|
)
|
||||||
|
|
||||||
ids = all_types + ('callback_query_without_message',)
|
ids = all_types + ('callback_query_without_message',)
|
||||||
|
@ -171,6 +183,7 @@ class TestUpdate:
|
||||||
or update.poll_answer is not None
|
or update.poll_answer is not None
|
||||||
or update.my_chat_member is not None
|
or update.my_chat_member is not None
|
||||||
or update.chat_member is not None
|
or update.chat_member is not None
|
||||||
|
or update.chat_join_request is not None
|
||||||
):
|
):
|
||||||
assert eff_message.message_id == message.message_id
|
assert eff_message.message_id == message.message_id
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -430,6 +430,40 @@ class TestUser:
|
||||||
monkeypatch.setattr(user.bot, 'copy_message', make_assertion)
|
monkeypatch.setattr(user.bot, 'copy_message', make_assertion)
|
||||||
assert user.copy_message(chat_id='chat_id', message_id='message_id')
|
assert user.copy_message(chat_id='chat_id', message_id='message_id')
|
||||||
|
|
||||||
|
def test_instance_method_approve_join_request(self, monkeypatch, user):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
chat_id = kwargs['chat_id'] == 'chat_id'
|
||||||
|
user_id = kwargs['user_id'] == user.id
|
||||||
|
return chat_id and user_id
|
||||||
|
|
||||||
|
assert check_shortcut_signature(
|
||||||
|
User.approve_join_request, Bot.approve_chat_join_request, ['user_id'], []
|
||||||
|
)
|
||||||
|
assert check_shortcut_call(
|
||||||
|
user.approve_join_request, user.bot, 'approve_chat_join_request'
|
||||||
|
)
|
||||||
|
assert check_defaults_handling(user.approve_join_request, user.bot)
|
||||||
|
|
||||||
|
monkeypatch.setattr(user.bot, 'approve_chat_join_request', make_assertion)
|
||||||
|
assert user.approve_join_request(chat_id='chat_id')
|
||||||
|
|
||||||
|
def test_instance_method_decline_join_request(self, monkeypatch, user):
|
||||||
|
def make_assertion(*_, **kwargs):
|
||||||
|
chat_id = kwargs['chat_id'] == 'chat_id'
|
||||||
|
user_id = kwargs['user_id'] == user.id
|
||||||
|
return chat_id and user_id
|
||||||
|
|
||||||
|
assert check_shortcut_signature(
|
||||||
|
User.decline_join_request, Bot.decline_chat_join_request, ['user_id'], []
|
||||||
|
)
|
||||||
|
assert check_shortcut_call(
|
||||||
|
user.decline_join_request, user.bot, 'decline_chat_join_request'
|
||||||
|
)
|
||||||
|
assert check_defaults_handling(user.decline_join_request, user.bot)
|
||||||
|
|
||||||
|
monkeypatch.setattr(user.bot, 'decline_chat_join_request', make_assertion)
|
||||||
|
assert user.decline_join_request(chat_id='chat_id')
|
||||||
|
|
||||||
def test_mention_html(self, user):
|
def test_mention_html(self, user):
|
||||||
expected = '<a href="tg://user?id={}">{}</a>'
|
expected = '<a href="tg://user?id={}">{}</a>'
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue