Added version 4

This commit is contained in:
2026-01-30 11:47:06 +03:00
parent 05aea043b6
commit 801844807e
2205 changed files with 2048 additions and 0 deletions

View File

@@ -0,0 +1,381 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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/].
"""A library that provides a Python interface to the Telegram Bot API"""
__author__ = "devs@python-telegram-bot.org"
__all__ = ( # Keep this alphabetically ordered
"__bot_api_version__",
"__bot_api_version_info__",
"__version__",
"__version_info__",
"Animation",
"Audio",
"Bot",
"BotCommand",
"BotCommandScope",
"BotCommandScopeAllChatAdministrators",
"BotCommandScopeAllGroupChats",
"BotCommandScopeAllPrivateChats",
"BotCommandScopeChat",
"BotCommandScopeChatAdministrators",
"BotCommandScopeChatMember",
"BotCommandScopeDefault",
"BotDescription",
"BotName",
"BotShortDescription",
"CallbackGame",
"CallbackQuery",
"Chat",
"ChatAdministratorRights",
"ChatInviteLink",
"ChatJoinRequest",
"ChatLocation",
"ChatMember",
"ChatMemberOwner",
"ChatMemberAdministrator",
"ChatMemberMember",
"ChatMemberRestricted",
"ChatMemberLeft",
"ChatMemberBanned",
"ChatMemberUpdated",
"ChatPermissions",
"ChatPhoto",
"ChatShared",
"ChosenInlineResult",
"constants",
"Contact",
"Credentials",
"DataCredentials",
"Dice",
"Document",
"EncryptedCredentials",
"EncryptedPassportElement",
"error",
"File",
"FileCredentials",
"ForceReply",
"ForumTopic",
"ForumTopicClosed",
"ForumTopicCreated",
"ForumTopicEdited",
"ForumTopicReopened",
"Game",
"GameHighScore",
"GeneralForumTopicHidden",
"GeneralForumTopicUnhidden",
"helpers",
"IdDocumentData",
"InlineKeyboardButton",
"InlineKeyboardMarkup",
"InlineQuery",
"InlineQueryResult",
"InlineQueryResultArticle",
"InlineQueryResultAudio",
"InlineQueryResultCachedAudio",
"InlineQueryResultCachedDocument",
"InlineQueryResultCachedGif",
"InlineQueryResultCachedMpeg4Gif",
"InlineQueryResultCachedPhoto",
"InlineQueryResultCachedSticker",
"InlineQueryResultCachedVideo",
"InlineQueryResultCachedVoice",
"InlineQueryResultContact",
"InlineQueryResultDocument",
"InlineQueryResultGame",
"InlineQueryResultGif",
"InlineQueryResultLocation",
"InlineQueryResultMpeg4Gif",
"InlineQueryResultPhoto",
"InlineQueryResultsButton",
"InlineQueryResultVenue",
"InlineQueryResultVideo",
"InlineQueryResultVoice",
"InputContactMessageContent",
"InputFile",
"InputInvoiceMessageContent",
"InputLocationMessageContent",
"InputMedia",
"InputMediaAnimation",
"InputMediaAudio",
"InputMediaDocument",
"InputMediaPhoto",
"InputMediaVideo",
"InputMessageContent",
"InputSticker",
"InputTextMessageContent",
"InputVenueMessageContent",
"Invoice",
"KeyboardButton",
"KeyboardButtonPollType",
"KeyboardButtonRequestChat",
"KeyboardButtonRequestUser",
"LabeledPrice",
"Location",
"LoginUrl",
"MaskPosition",
"MenuButton",
"MenuButtonCommands",
"MenuButtonDefault",
"MenuButtonWebApp",
"Message",
"MessageAutoDeleteTimerChanged",
"MessageEntity",
"MessageId",
"OrderInfo",
"PassportData",
"PassportElementError",
"PassportElementErrorDataField",
"PassportElementErrorFile",
"PassportElementErrorFiles",
"PassportElementErrorFrontSide",
"PassportElementErrorReverseSide",
"PassportElementErrorSelfie",
"PassportElementErrorTranslationFile",
"PassportElementErrorTranslationFiles",
"PassportElementErrorUnspecified",
"PassportFile",
"PersonalDetails",
"PhotoSize",
"Poll",
"PollAnswer",
"PollOption",
"PreCheckoutQuery",
"ProximityAlertTriggered",
"ReplyKeyboardMarkup",
"ReplyKeyboardRemove",
"request",
"ResidentialAddress",
"SecureData",
"SecureValue",
"SentWebAppMessage",
"ShippingAddress",
"ShippingOption",
"ShippingQuery",
"Sticker",
"StickerSet",
"SuccessfulPayment",
"SwitchInlineQueryChosenChat",
"TelegramObject",
"Update",
"User",
"UserProfilePhotos",
"UserShared",
"Venue",
"Video",
"VideoChatEnded",
"VideoChatParticipantsInvited",
"VideoChatScheduled",
"VideoChatStarted",
"VideoNote",
"Voice",
"warnings",
"WebAppData",
"WebAppInfo",
"WebhookInfo",
"WriteAccessAllowed",
)
from . import _version, constants, error, helpers, request, warnings
from ._bot import Bot
from ._botcommand import BotCommand
from ._botcommandscope import (
BotCommandScope,
BotCommandScopeAllChatAdministrators,
BotCommandScopeAllGroupChats,
BotCommandScopeAllPrivateChats,
BotCommandScopeChat,
BotCommandScopeChatAdministrators,
BotCommandScopeChatMember,
BotCommandScopeDefault,
)
from ._botdescription import BotDescription, BotShortDescription
from ._botname import BotName
from ._callbackquery import CallbackQuery
from ._chat import Chat
from ._chatadministratorrights import ChatAdministratorRights
from ._chatinvitelink import ChatInviteLink
from ._chatjoinrequest import ChatJoinRequest
from ._chatlocation import ChatLocation
from ._chatmember import (
ChatMember,
ChatMemberAdministrator,
ChatMemberBanned,
ChatMemberLeft,
ChatMemberMember,
ChatMemberOwner,
ChatMemberRestricted,
)
from ._chatmemberupdated import ChatMemberUpdated
from ._chatpermissions import ChatPermissions
from ._choseninlineresult import ChosenInlineResult
from ._dice import Dice
from ._files.animation import Animation
from ._files.audio import Audio
from ._files.chatphoto import ChatPhoto
from ._files.contact import Contact
from ._files.document import Document
from ._files.file import File
from ._files.inputfile import InputFile
from ._files.inputmedia import (
InputMedia,
InputMediaAnimation,
InputMediaAudio,
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
)
from ._files.inputsticker import InputSticker
from ._files.location import Location
from ._files.photosize import PhotoSize
from ._files.sticker import MaskPosition, Sticker, StickerSet
from ._files.venue import Venue
from ._files.video import Video
from ._files.videonote import VideoNote
from ._files.voice import Voice
from ._forcereply import ForceReply
from ._forumtopic import (
ForumTopic,
ForumTopicClosed,
ForumTopicCreated,
ForumTopicEdited,
ForumTopicReopened,
GeneralForumTopicHidden,
GeneralForumTopicUnhidden,
)
from ._games.callbackgame import CallbackGame
from ._games.game import Game
from ._games.gamehighscore import GameHighScore
from ._inline.inlinekeyboardbutton import InlineKeyboardButton
from ._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from ._inline.inlinequery import InlineQuery
from ._inline.inlinequeryresult import InlineQueryResult
from ._inline.inlinequeryresultarticle import InlineQueryResultArticle
from ._inline.inlinequeryresultaudio import InlineQueryResultAudio
from ._inline.inlinequeryresultcachedaudio import InlineQueryResultCachedAudio
from ._inline.inlinequeryresultcacheddocument import InlineQueryResultCachedDocument
from ._inline.inlinequeryresultcachedgif import InlineQueryResultCachedGif
from ._inline.inlinequeryresultcachedmpeg4gif import InlineQueryResultCachedMpeg4Gif
from ._inline.inlinequeryresultcachedphoto import InlineQueryResultCachedPhoto
from ._inline.inlinequeryresultcachedsticker import InlineQueryResultCachedSticker
from ._inline.inlinequeryresultcachedvideo import InlineQueryResultCachedVideo
from ._inline.inlinequeryresultcachedvoice import InlineQueryResultCachedVoice
from ._inline.inlinequeryresultcontact import InlineQueryResultContact
from ._inline.inlinequeryresultdocument import InlineQueryResultDocument
from ._inline.inlinequeryresultgame import InlineQueryResultGame
from ._inline.inlinequeryresultgif import InlineQueryResultGif
from ._inline.inlinequeryresultlocation import InlineQueryResultLocation
from ._inline.inlinequeryresultmpeg4gif import InlineQueryResultMpeg4Gif
from ._inline.inlinequeryresultphoto import InlineQueryResultPhoto
from ._inline.inlinequeryresultsbutton import InlineQueryResultsButton
from ._inline.inlinequeryresultvenue import InlineQueryResultVenue
from ._inline.inlinequeryresultvideo import InlineQueryResultVideo
from ._inline.inlinequeryresultvoice import InlineQueryResultVoice
from ._inline.inputcontactmessagecontent import InputContactMessageContent
from ._inline.inputinvoicemessagecontent import InputInvoiceMessageContent
from ._inline.inputlocationmessagecontent import InputLocationMessageContent
from ._inline.inputmessagecontent import InputMessageContent
from ._inline.inputtextmessagecontent import InputTextMessageContent
from ._inline.inputvenuemessagecontent import InputVenueMessageContent
from ._keyboardbutton import KeyboardButton
from ._keyboardbuttonpolltype import KeyboardButtonPollType
from ._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUser
from ._loginurl import LoginUrl
from ._menubutton import MenuButton, MenuButtonCommands, MenuButtonDefault, MenuButtonWebApp
from ._message import Message
from ._messageautodeletetimerchanged import MessageAutoDeleteTimerChanged
from ._messageentity import MessageEntity
from ._messageid import MessageId
from ._passport.credentials import (
Credentials,
DataCredentials,
EncryptedCredentials,
FileCredentials,
SecureData,
SecureValue,
)
from ._passport.data import IdDocumentData, PersonalDetails, ResidentialAddress
from ._passport.encryptedpassportelement import EncryptedPassportElement
from ._passport.passportdata import PassportData
from ._passport.passportelementerrors import (
PassportElementError,
PassportElementErrorDataField,
PassportElementErrorFile,
PassportElementErrorFiles,
PassportElementErrorFrontSide,
PassportElementErrorReverseSide,
PassportElementErrorSelfie,
PassportElementErrorTranslationFile,
PassportElementErrorTranslationFiles,
PassportElementErrorUnspecified,
)
from ._passport.passportfile import PassportFile
from ._payment.invoice import Invoice
from ._payment.labeledprice import LabeledPrice
from ._payment.orderinfo import OrderInfo
from ._payment.precheckoutquery import PreCheckoutQuery
from ._payment.shippingaddress import ShippingAddress
from ._payment.shippingoption import ShippingOption
from ._payment.shippingquery import ShippingQuery
from ._payment.successfulpayment import SuccessfulPayment
from ._poll import Poll, PollAnswer, PollOption
from ._proximityalerttriggered import ProximityAlertTriggered
from ._replykeyboardmarkup import ReplyKeyboardMarkup
from ._replykeyboardremove import ReplyKeyboardRemove
from ._sentwebappmessage import SentWebAppMessage
from ._shared import ChatShared, UserShared
from ._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
from ._telegramobject import TelegramObject
from ._update import Update
from ._user import User
from ._userprofilephotos import UserProfilePhotos
from ._videochat import (
VideoChatEnded,
VideoChatParticipantsInvited,
VideoChatScheduled,
VideoChatStarted,
)
from ._webappdata import WebAppData
from ._webappinfo import WebAppInfo
from ._webhookinfo import WebhookInfo
from ._writeaccessallowed import WriteAccessAllowed
#: :obj:`str`: The version of the `python-telegram-bot` library as string.
#: To get detailed information about the version number, please use :data:`__version_info__`
#: instead.
__version__: str = _version.__version__
#: :class:`typing.NamedTuple`: A tuple containing the five components of the version number:
#: `major`, `minor`, `micro`, `releaselevel`, and `serial`.
#: All values except `releaselevel` are integers.
#: The release level is ``'alpha'``, ``'beta'``, ``'candidate'``, or ``'final'``.
#: The components can also be accessed by name, so ``__version_info__[0]`` is equivalent to
#: ``__version_info__.major`` and so on.
#:
#: .. versionadded:: 20.0
__version_info__: _version.Version = _version.__version_info__
#: :obj:`str`: Shortcut for :const:`telegram.constants.BOT_API_VERSION`.
#:
#: .. versionchanged:: 20.0
#: This constant was previously named ``bot_api_version``.
__bot_api_version__: str = _version.__bot_api_version__
#: :class:`typing.NamedTuple`: Shortcut for :const:`telegram.constants.BOT_API_VERSION_INFO`.
#:
#: .. versionadded:: 20.0
__bot_api_version_info__: constants._BotAPIVersion = _version.__bot_api_version_info__

View File

@@ -0,0 +1,53 @@
# !/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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=missing-module-docstring
import subprocess
import sys
from typing import Optional
from . import __version__ as telegram_ver
from .constants import BOT_API_VERSION
def _git_revision() -> Optional[str]:
try:
output = subprocess.check_output( # skipcq: BAN-B607
["git", "describe", "--long", "--tags"], stderr=subprocess.STDOUT
)
except (subprocess.SubprocessError, OSError):
return None
return output.decode().strip()
def print_ver_info() -> None: # skipcq: PY-D0003
"""Prints version information for python-telegram-bot, the Bot API and Python."""
git_revision = _git_revision()
print(f"python-telegram-bot {telegram_ver}" + (f" ({git_revision})" if git_revision else ""))
print(f"Bot API {BOT_API_VERSION}")
sys_version = sys.version.replace("\n", " ")
print(f"Python {sys_version}")
def main() -> None: # skipcq: PY-D0003
"""Prints version information for python-telegram-bot, the Bot API and Python."""
print_ver_info()
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Bot Command."""
from typing import ClassVar
from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class BotCommand(TelegramObject):
"""
This object represents a bot command.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`command` and :attr:`description` are equal.
Args:
command (:obj:`str`): Text of the command; :tg-const:`telegram.BotCommand.MIN_COMMAND`-
:tg-const:`telegram.BotCommand.MAX_COMMAND` characters. Can contain only lowercase
English letters, digits and underscores.
description (:obj:`str`): Description of the command;
:tg-const:`telegram.BotCommand.MIN_DESCRIPTION`-
:tg-const:`telegram.BotCommand.MAX_DESCRIPTION` characters.
Attributes:
command (:obj:`str`): Text of the command; :tg-const:`telegram.BotCommand.MIN_COMMAND`-
:tg-const:`telegram.BotCommand.MAX_COMMAND` characters. Can contain only lowercase
English letters, digits and underscores.
description (:obj:`str`): Description of the command;
:tg-const:`telegram.BotCommand.MIN_DESCRIPTION`-
:tg-const:`telegram.BotCommand.MAX_DESCRIPTION` characters.
"""
__slots__ = ("description", "command")
def __init__(self, command: str, description: str, *, api_kwargs: JSONDict = None):
super().__init__(api_kwargs=api_kwargs)
self.command: str = command
self.description: str = description
self._id_attrs = (self.command, self.description)
self._freeze()
MIN_COMMAND: ClassVar[int] = constants.BotCommandLimit.MIN_COMMAND
""":const:`telegram.constants.BotCommandLimit.MIN_COMMAND`
.. versionadded:: 20.0
"""
MAX_COMMAND: ClassVar[int] = constants.BotCommandLimit.MAX_COMMAND
""":const:`telegram.constants.BotCommandLimit.MAX_COMMAND`
.. versionadded:: 20.0
"""
MIN_DESCRIPTION: ClassVar[int] = constants.BotCommandLimit.MIN_DESCRIPTION
""":const:`telegram.constants.BotCommandLimit.MIN_DESCRIPTION`
.. versionadded:: 20.0
"""
MAX_DESCRIPTION: ClassVar[int] = constants.BotCommandLimit.MAX_DESCRIPTION
""":const:`telegram.constants.BotCommandLimit.MAX_DESCRIPTION`
.. versionadded:: 20.0
"""

View File

@@ -0,0 +1,264 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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=redefined-builtin
"""This module contains objects representing Telegram bot command scopes."""
from typing import TYPE_CHECKING, ClassVar, Dict, Optional, Type, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
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",)
DEFAULT: ClassVar[str] = constants.BotCommandScopeType.DEFAULT
""":const:`telegram.constants.BotCommandScopeType.DEFAULT`"""
ALL_PRIVATE_CHATS: ClassVar[str] = constants.BotCommandScopeType.ALL_PRIVATE_CHATS
""":const:`telegram.constants.BotCommandScopeType.ALL_PRIVATE_CHATS`"""
ALL_GROUP_CHATS: ClassVar[str] = constants.BotCommandScopeType.ALL_GROUP_CHATS
""":const:`telegram.constants.BotCommandScopeType.ALL_GROUP_CHATS`"""
ALL_CHAT_ADMINISTRATORS: ClassVar[str] = constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS
""":const:`telegram.constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS`"""
CHAT: ClassVar[str] = constants.BotCommandScopeType.CHAT
""":const:`telegram.constants.BotCommandScopeType.CHAT`"""
CHAT_ADMINISTRATORS: ClassVar[str] = constants.BotCommandScopeType.CHAT_ADMINISTRATORS
""":const:`telegram.constants.BotCommandScopeType.CHAT_ADMINISTRATORS`"""
CHAT_MEMBER: ClassVar[str] = constants.BotCommandScopeType.CHAT_MEMBER
""":const:`telegram.constants.BotCommandScopeType.CHAT_MEMBER`"""
def __init__(self, type: str, *, api_kwargs: JSONDict = None):
super().__init__(api_kwargs=api_kwargs)
self.type: str = type
self._id_attrs = (self.type,)
self._freeze()
@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 and data.get("type") in _class_mapping:
return _class_mapping[data.pop("type")].de_json(data=data, bot=bot)
return super().de_json(data=data, bot=bot)
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 :tg-const:`telegram.BotCommandScope.DEFAULT`.
"""
__slots__ = ()
def __init__(self, *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.DEFAULT, api_kwargs=api_kwargs)
self._freeze()
class BotCommandScopeAllPrivateChats(BotCommandScope):
"""Represents the scope of bot commands, covering all private chats.
.. versionadded:: 13.7
Attributes:
type (:obj:`str`): Scope type :tg-const:`telegram.BotCommandScope.ALL_PRIVATE_CHATS`.
"""
__slots__ = ()
def __init__(self, *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.ALL_PRIVATE_CHATS, api_kwargs=api_kwargs)
self._freeze()
class BotCommandScopeAllGroupChats(BotCommandScope):
"""Represents the scope of bot commands, covering all group and supergroup chats.
.. versionadded:: 13.7
Attributes:
type (:obj:`str`): Scope type :tg-const:`telegram.BotCommandScope.ALL_GROUP_CHATS`.
"""
__slots__ = ()
def __init__(self, *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.ALL_GROUP_CHATS, api_kwargs=api_kwargs)
self._freeze()
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 :tg-const:`telegram.BotCommandScope.ALL_CHAT_ADMINISTRATORS`.
"""
__slots__ = ()
def __init__(self, *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.ALL_CHAT_ADMINISTRATORS, api_kwargs=api_kwargs)
self._freeze()
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`): |chat_id_group|
Attributes:
type (:obj:`str`): Scope type :tg-const:`telegram.BotCommandScope.CHAT`.
chat_id (:obj:`str` | :obj:`int`): |chat_id_group|
"""
__slots__ = ("chat_id",)
def __init__(self, chat_id: Union[str, int], *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.CHAT, api_kwargs=api_kwargs)
with self._unfrozen():
self.chat_id: Union[str, int] = (
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`): |chat_id_group|
Attributes:
type (:obj:`str`): Scope type :tg-const:`telegram.BotCommandScope.CHAT_ADMINISTRATORS`.
chat_id (:obj:`str` | :obj:`int`): |chat_id_group|
"""
__slots__ = ("chat_id",)
def __init__(self, chat_id: Union[str, int], *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.CHAT_ADMINISTRATORS, api_kwargs=api_kwargs)
with self._unfrozen():
self.chat_id: Union[str, int] = (
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`): |chat_id_group|
user_id (:obj:`int`): Unique identifier of the target user.
Attributes:
type (:obj:`str`): Scope type :tg-const:`telegram.BotCommandScope.CHAT_MEMBER`.
chat_id (:obj:`str` | :obj:`int`): |chat_id_group|
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, *, api_kwargs: JSONDict = None):
super().__init__(type=BotCommandScope.CHAT_MEMBER, api_kwargs=api_kwargs)
with self._unfrozen():
self.chat_id: Union[str, int] = (
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)

View File

@@ -0,0 +1,75 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 two objects that represent a Telegram bots (short) description."""
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class BotDescription(TelegramObject):
"""This object represents the bot's description.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`description` is equal.
.. versionadded:: 20.2
Args:
description (:obj:`str`): The bot's description.
Attributes:
description (:obj:`str`): The bot's description.
"""
__slots__ = ("description",)
def __init__(self, description: str, *, api_kwargs: JSONDict = None):
super().__init__(api_kwargs=api_kwargs)
self.description: str = description
self._id_attrs = (self.description,)
self._freeze()
class BotShortDescription(TelegramObject):
"""This object represents the bot's short description.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`short_description` is equal.
.. versionadded:: 20.2
Args:
short_description (:obj:`str`): The bot's short description.
Attributes:
short_description (:obj:`str`): The bot's short description.
"""
__slots__ = ("short_description",)
def __init__(self, short_description: str, *, api_kwargs: JSONDict = None):
super().__init__(api_kwargs=api_kwargs)
self.short_description: str = short_description
self._id_attrs = (self.short_description,)
self._freeze()

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 represent a Telegram bots name."""
from typing import ClassVar
from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class BotName(TelegramObject):
"""This object represents the bot's name.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`name` is equal.
.. versionadded:: 20.3
Args:
name (:obj:`str`): The bot's name.
Attributes:
name (:obj:`str`): The bot's name.
"""
__slots__ = ("name",)
def __init__(self, name: str, *, api_kwargs: JSONDict = None):
super().__init__(api_kwargs=api_kwargs)
self.name: str = name
self._id_attrs = (self.name,)
self._freeze()
MAX_LENGTH: ClassVar[int] = constants.BotNameLimit.MAX_NAME_LENGTH
""":const:`telegram.constants.BotNameLimit.MAX_NAME_LENGTH`"""

View File

@@ -0,0 +1,781 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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=redefined-builtin
"""This module contains an object that represents a Telegram CallbackQuery"""
from typing import TYPE_CHECKING, ClassVar, Optional, Sequence, Tuple, Union
from telegram import constants
from telegram._files.location import Location
from telegram._message import Message
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import DVInput, JSONDict, ODVInput, ReplyMarkup
if TYPE_CHECKING:
from telegram import (
Bot,
GameHighScore,
InlineKeyboardMarkup,
InputMedia,
MessageEntity,
MessageId,
)
class CallbackQuery(TelegramObject):
"""
This object represents an incoming callback query from a callback button in an inline keyboard.
If the button that originated the query was attached to a message sent by the bot, the field
:attr:`message` will be present. If the button was attached to a message sent via the bot (in
inline mode), the field :attr:`inline_message_id` will be present.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`id` is equal.
Note:
* In Python :keyword:`from` is a reserved word. Use :paramref:`from_user` instead.
* Exactly one of the fields :attr:`data` or :attr:`game_short_name` will be present.
* After the user presses an inline button, Telegram clients will display a progress bar
until you call :attr:`answer`. It is, therefore, necessary to react
by calling :attr:`telegram.Bot.answer_callback_query` even if no notification to the user
is needed (e.g., without specifying any of the optional parameters).
* If you're using :attr:`telegram.ext.ExtBot.callback_data_cache`, :attr:`data` may be
an instance
of :class:`telegram.ext.InvalidCallbackData`. This will be the case, if the data
associated with the button triggering the :class:`telegram.CallbackQuery` was already
deleted or if :attr:`data` was manipulated by a malicious client.
.. versionadded:: 13.6
Args:
id (:obj:`str`): Unique identifier for this query.
from_user (:class:`telegram.User`): Sender.
chat_instance (:obj:`str`): Global identifier, uniquely corresponding to the chat to which
the message with the callback button was sent. Useful for high scores in games.
message (:class:`telegram.Message`, optional): Message with the callback button that
originated the query. Note that message content and message date will not be available
if the message is too old.
data (:obj:`str`, optional): Data associated with the callback button. Be aware that the
message, which originated the query, can contain no callback buttons with this data.
inline_message_id (:obj:`str`, optional): Identifier of the message sent via the bot in
inline mode, that originated the query.
game_short_name (:obj:`str`, optional): Short name of a Game to be returned, serves as
the unique identifier for the game.
Attributes:
id (:obj:`str`): Unique identifier for this query.
from_user (:class:`telegram.User`): Sender.
chat_instance (:obj:`str`): Global identifier, uniquely corresponding to the chat to which
the message with the callback button was sent. Useful for high scores in games.
message (:class:`telegram.Message`): Optional. Message with the callback button that
originated the query. Note that message content and message date will not be available
if the message is too old.
data (:obj:`str` | :obj:`object`): Optional. Data associated with the callback button.
Be aware that the message, which originated the query, can contain no callback buttons
with this data.
Tip:
The value here is the same as the value passed in
:paramref:`telegram.InlineKeyboardButton.callback_data`.
inline_message_id (:obj:`str`): Optional. Identifier of the message sent via the bot in
inline mode, that originated the query.
game_short_name (:obj:`str`): Optional. Short name of a Game to be returned, serves as
the unique identifier for the game.
"""
__slots__ = (
"game_short_name",
"message",
"chat_instance",
"id",
"from_user",
"inline_message_id",
"data",
)
def __init__(
self,
id: str,
from_user: User,
chat_instance: str,
message: Message = None,
data: str = None,
inline_message_id: str = None,
game_short_name: str = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.id: str = id # pylint: disable=invalid-name
self.from_user: User = from_user
self.chat_instance: str = chat_instance
# Optionals
self.message: Optional[Message] = message
self.data: Optional[str] = data
self.inline_message_id: Optional[str] = inline_message_id
self.game_short_name: Optional[str] = game_short_name
self._id_attrs = (self.id,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["CallbackQuery"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["from_user"] = User.de_json(data.pop("from", None), bot)
data["message"] = Message.de_json(data.get("message"), bot)
return super().de_json(data=data, bot=bot)
async def answer(
self,
text: str = None,
show_alert: bool = None,
url: str = None,
cache_time: int = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
await bot.answer_callback_query(update.callback_query.id, *args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.answer_callback_query`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.get_bot().answer_callback_query(
callback_query_id=self.id,
text=text,
show_alert=show_alert,
url=url,
cache_time=cache_time,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def edit_message_text(
self,
text: str,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
reply_markup: "InlineKeyboardMarkup" = None,
entities: Sequence["MessageEntity"] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.edit_text(*args, **kwargs)
or::
await bot.edit_message_text(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs,
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_text` and :meth:`telegram.Message.edit_text`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().edit_message_text(
inline_message_id=self.inline_message_id,
text=text,
parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
entities=entities,
chat_id=None,
message_id=None,
)
return await self.message.edit_text(
text=text,
parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
entities=entities,
)
async def edit_message_caption(
self,
caption: str = None,
reply_markup: "InlineKeyboardMarkup" = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence["MessageEntity"] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.edit_caption(*args, **kwargs)
or::
await bot.edit_message_caption(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs,
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_caption` and :meth:`telegram.Message.edit_caption`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().edit_message_caption(
caption=caption,
inline_message_id=self.inline_message_id,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
parse_mode=parse_mode,
api_kwargs=api_kwargs,
caption_entities=caption_entities,
chat_id=None,
message_id=None,
)
return await self.message.edit_caption(
caption=caption,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
parse_mode=parse_mode,
api_kwargs=api_kwargs,
caption_entities=caption_entities,
)
async def edit_message_reply_markup(
self,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.edit_reply_markup(*args, **kwargs)
or::
await bot.edit_message_reply_markup(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_reply_markup` and
:meth:`telegram.Message.edit_reply_markup`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().edit_message_reply_markup(
reply_markup=reply_markup,
inline_message_id=self.inline_message_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return await self.message.edit_reply_markup(
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def edit_message_media(
self,
media: "InputMedia",
reply_markup: "InlineKeyboardMarkup" = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.edit_media(*args, **kwargs)
or::
await bot.edit_message_media(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_media` and :meth:`telegram.Message.edit_media`.
Returns:
:class:`telegram.Message`: On success, if edited message is not an inline message, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().edit_message_media(
inline_message_id=self.inline_message_id,
media=media,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return await self.message.edit_media(
media=media,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def edit_message_live_location(
self,
latitude: float = None,
longitude: float = None,
reply_markup: "InlineKeyboardMarkup" = None,
horizontal_accuracy: float = None,
heading: int = None,
proximity_alert_radius: int = None,
*,
location: Location = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.edit_live_location(*args, **kwargs)
or::
await bot.edit_message_live_location(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_live_location` and
:meth:`telegram.Message.edit_live_location`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().edit_message_live_location(
inline_message_id=self.inline_message_id,
latitude=latitude,
longitude=longitude,
location=location,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
chat_id=None,
message_id=None,
)
return await self.message.edit_live_location(
latitude=latitude,
longitude=longitude,
location=location,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
)
async def stop_message_live_location(
self,
reply_markup: "InlineKeyboardMarkup" = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.stop_live_location(*args, **kwargs)
or::
await bot.stop_message_live_location(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.stop_message_live_location` and
:meth:`telegram.Message.stop_live_location`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().stop_message_live_location(
inline_message_id=self.inline_message_id,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return await self.message.stop_live_location(
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def set_game_score(
self,
user_id: Union[int, str],
score: int,
force: bool = None,
disable_edit_message: bool = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
await update.callback_query.message.set_game_score(*args, **kwargs)
or::
await bot.set_game_score(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.set_game_score` and :meth:`telegram.Message.set_game_score`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
"""
if self.inline_message_id:
return await self.get_bot().set_game_score(
inline_message_id=self.inline_message_id,
user_id=user_id,
score=score,
force=force,
disable_edit_message=disable_edit_message,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return await self.message.set_game_score(
user_id=user_id,
score=score,
force=force,
disable_edit_message=disable_edit_message,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def get_game_high_scores(
self,
user_id: Union[int, str],
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Tuple["GameHighScore", ...]:
"""Shortcut for either::
await update.callback_query.message.get_game_high_score(*args, **kwargs)
or::
await bot.get_game_high_scores(
inline_message_id=update.callback_query.inline_message_id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.get_game_high_scores` and
:meth:`telegram.Message.get_game_high_scores`.
Returns:
Tuple[:class:`telegram.GameHighScore`]
"""
if self.inline_message_id:
return await self.get_bot().get_game_high_scores(
inline_message_id=self.inline_message_id,
user_id=user_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return await self.message.get_game_high_scores(
user_id=user_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def delete_message(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
await update.callback_query.message.delete(*args, **kwargs)
For the documentation of the arguments, please see :meth:`telegram.Message.delete`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.message.delete(
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def pin_message(
self,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
await update.callback_query.message.pin(*args, **kwargs)
For the documentation of the arguments, please see :meth:`telegram.Message.pin`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.message.pin(
disable_notification=disable_notification,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def unpin_message(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
await update.callback_query.message.unpin(*args, **kwargs)
For the documentation of the arguments, please see :meth:`telegram.Message.unpin`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.message.unpin(
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def copy_message(
self,
chat_id: Union[int, str],
caption: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence["MessageEntity"] = None,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: int = None,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: ReplyMarkup = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: int = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> "MessageId":
"""Shortcut for::
await update.callback_query.message.copy(
from_chat_id=update.message.chat_id,
message_id=update.message.message_id,
*args,
**kwargs
)
For the documentation of the arguments, please see :meth:`telegram.Message.copy`.
Returns:
:class:`telegram.MessageId`: On success, returns the MessageId of the sent message.
"""
return await self.message.copy(
chat_id=chat_id,
caption=caption,
parse_mode=parse_mode,
caption_entities=caption_entities,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
allow_sending_without_reply=allow_sending_without_reply,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
protect_content=protect_content,
message_thread_id=message_thread_id,
)
MAX_ANSWER_TEXT_LENGTH: ClassVar[
int
] = constants.CallbackQueryLimit.ANSWER_CALLBACK_QUERY_TEXT_LENGTH
"""
:const:`telegram.constants.CallbackQueryLimit.ANSWER_CALLBACK_QUERY_TEXT_LENGTH`
.. versionadded:: 13.2
"""

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,191 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 class which represents a Telegram ChatAdministratorRights."""
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class ChatAdministratorRights(TelegramObject):
"""Represents the rights of an administrator in a chat.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`is_anonymous`, :attr:`can_manage_chat`,
:attr:`can_delete_messages`, :attr:`can_manage_video_chats`, :attr:`can_restrict_members`,
:attr:`can_promote_members`, :attr:`can_change_info`, :attr:`can_invite_users`,
:attr:`can_post_messages`, :attr:`can_edit_messages`, :attr:`can_pin_messages`,
:attr:`can_manage_topics` are equal.
.. versionchanged:: 20.0
:attr:`can_manage_topics` is considered as well when comparing objects of
this type in terms of equality.
.. versionadded:: 20.0
Args:
is_anonymous (:obj:`bool`): :obj:`True`, if the user's presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :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_delete_messages (:obj:`bool`): :obj:`True`, if the administrator can delete messages of
other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the administrator can manage video
chats.
can_restrict_members (:obj:`bool`): :obj:`True`, if the administrator can restrict, ban or
unban chat members.
can_promote_members (:obj:`bool`): :obj:`True`, if the administrator can add new
administrators with a subset of their own privileges or demote administrators
that they have promoted, directly or indirectly (promoted by administrators that
were appointed by the user).
can_change_info (:obj:`bool`): :obj:`True`, if the user is allowed to change the chat title
,photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user is allowed to invite new users to
the chat.
can_post_messages (:obj:`bool`, optional): :obj:`True`, if the administrator can post
messages in the channel; channels only.
can_edit_messages (:obj:`bool`, optional): :obj:`True`, if the administrator can edit
messages of other users.
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to pin
messages; groups and supergroups only.
can_manage_topics (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only.
.. versionadded:: 20.0
Attributes:
is_anonymous (:obj:`bool`): :obj:`True`, if the user's presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :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_delete_messages (:obj:`bool`): :obj:`True`, if the administrator can delete messages of
other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the administrator can manage video
chats.
can_restrict_members (:obj:`bool`): :obj:`True`, if the administrator can restrict, ban or
unban chat members.
can_promote_members (:obj:`bool`): :obj:`True`, if the administrator can add new
administrators with a subset of their 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`): :obj:`True`, if the user is allowed to change the chat title
,photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user is allowed to invite new users to
the chat.
can_post_messages (:obj:`bool`): Optional. :obj:`True`, if the administrator can post
messages in the channel; channels only.
can_edit_messages (:obj:`bool`): Optional. :obj:`True`, if the administrator can edit
messages of other users.
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to pin
messages; groups and supergroups only.
can_manage_topics (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only.
.. versionadded:: 20.0
"""
__slots__ = (
"is_anonymous",
"can_manage_chat",
"can_delete_messages",
"can_manage_video_chats",
"can_restrict_members",
"can_promote_members",
"can_change_info",
"can_invite_users",
"can_post_messages",
"can_edit_messages",
"can_pin_messages",
"can_manage_topics",
)
def __init__(
self,
is_anonymous: bool,
can_manage_chat: bool,
can_delete_messages: bool,
can_manage_video_chats: bool,
can_restrict_members: bool,
can_promote_members: bool,
can_change_info: bool,
can_invite_users: bool,
can_post_messages: bool = None,
can_edit_messages: bool = None,
can_pin_messages: bool = None,
can_manage_topics: bool = None,
*,
api_kwargs: JSONDict = None,
) -> None:
super().__init__(api_kwargs=api_kwargs)
# Required
self.is_anonymous: bool = is_anonymous
self.can_manage_chat: bool = can_manage_chat
self.can_delete_messages: bool = can_delete_messages
self.can_manage_video_chats: bool = can_manage_video_chats
self.can_restrict_members: bool = can_restrict_members
self.can_promote_members: bool = can_promote_members
self.can_change_info: bool = can_change_info
self.can_invite_users: bool = can_invite_users
# Optionals
self.can_post_messages: Optional[bool] = can_post_messages
self.can_edit_messages: Optional[bool] = can_edit_messages
self.can_pin_messages: Optional[bool] = can_pin_messages
self.can_manage_topics: Optional[bool] = can_manage_topics
self._id_attrs = (
self.is_anonymous,
self.can_manage_chat,
self.can_delete_messages,
self.can_manage_video_chats,
self.can_restrict_members,
self.can_promote_members,
self.can_change_info,
self.can_invite_users,
self.can_post_messages,
self.can_edit_messages,
self.can_pin_messages,
self.can_manage_topics,
)
self._freeze()
@classmethod
def all_rights(cls) -> "ChatAdministratorRights":
"""
This method returns the :class:`ChatAdministratorRights` object with all attributes set to
:obj:`True`. This is e.g. useful when changing the bot's default administrator rights with
:meth:`telegram.Bot.set_my_default_administrator_rights`.
.. versionadded:: 20.0
"""
return cls(True, True, True, True, True, True, True, True, True, True, True, True)
@classmethod
def no_rights(cls) -> "ChatAdministratorRights":
"""
This method returns the :class:`ChatAdministratorRights` object with all attributes set to
:obj:`False`.
.. versionadded:: 20.0
"""
return cls(
False, False, False, False, False, False, False, False, False, False, False, False
)

View File

@@ -0,0 +1,167 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 an invite link for a chat."""
import datetime
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class ChatInviteLink(TelegramObject):
"""This object represents an invite link for a chat.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`invite_link`, :attr:`creator`, :attr:`creates_join_request`,
:attr:`is_primary` and :attr:`is_revoked` are equal.
.. versionadded:: 13.4
.. versionchanged:: 20.0
* The argument & attribute :attr:`creates_join_request` is now required to comply with the
Bot API.
* Comparing objects of this class now also takes :attr:`creates_join_request` into account.
Args:
invite_link (:obj:`str`): The invite link.
creator (:class:`telegram.User`): Creator of the link.
creates_join_request (:obj:`bool`): :obj:`True`, if users joining the chat via
the link need to be approved by chat administrators.
.. versionadded:: 13.8
is_primary (:obj:`bool`): :obj:`True`, if the link is primary.
is_revoked (:obj:`bool`): :obj:`True`, if the link is revoked.
expire_date (:class:`datetime.datetime`, optional): Date when the link will expire or
has been expired.
.. versionchanged:: 20.3
|datetime_localization|
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;
:tg-const:`telegram.constants.ChatInviteLinkLimit.MIN_MEMBER_LIMIT`-
:tg-const:`telegram.constants.ChatInviteLinkLimit.MAX_MEMBER_LIMIT`.
name (:obj:`str`, optional): Invite link name.
0-:tg-const:`telegram.constants.ChatInviteLinkLimit.NAME_LENGTH` characters.
.. versionadded:: 13.8
pending_join_request_count (:obj:`int`, optional): Number of pending join requests
created using this link.
.. versionadded:: 13.8
Attributes:
invite_link (:obj:`str`): The invite link. If the link was created by another chat
administrator, then the second part of the link will be replaced with ``''``.
creator (:class:`telegram.User`): Creator of the link.
creates_join_request (:obj:`bool`): :obj:`True`, if users joining the chat via
the link need to be approved by chat administrators.
.. versionadded:: 13.8
is_primary (:obj:`bool`): :obj:`True`, if the link is primary.
is_revoked (:obj:`bool`): :obj:`True`, if the link is revoked.
expire_date (:class:`datetime.datetime`): Optional. Date when the link will expire or
has been expired.
.. versionchanged:: 20.3
|datetime_localization|
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;
:tg-const:`telegram.constants.ChatInviteLinkLimit.MIN_MEMBER_LIMIT`-
:tg-const:`telegram.constants.ChatInviteLinkLimit.MAX_MEMBER_LIMIT`.
name (:obj:`str`): Optional. Invite link name.
0-:tg-const:`telegram.constants.ChatInviteLinkLimit.NAME_LENGTH` characters.
.. versionadded:: 13.8
pending_join_request_count (:obj:`int`): Optional. Number of pending join requests
created using this link.
.. versionadded:: 13.8
"""
__slots__ = (
"invite_link",
"creator",
"is_primary",
"is_revoked",
"expire_date",
"member_limit",
"name",
"creates_join_request",
"pending_join_request_count",
)
def __init__(
self,
invite_link: str,
creator: User,
creates_join_request: bool,
is_primary: bool,
is_revoked: bool,
expire_date: datetime.datetime = None,
member_limit: int = None,
name: str = None,
pending_join_request_count: int = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.invite_link: str = invite_link
self.creator: User = creator
self.creates_join_request: bool = creates_join_request
self.is_primary: bool = is_primary
self.is_revoked: bool = is_revoked
# Optionals
self.expire_date: Optional[datetime.datetime] = expire_date
self.member_limit: Optional[int] = member_limit
self.name: Optional[str] = name
self.pending_join_request_count: Optional[int] = (
int(pending_join_request_count) if pending_join_request_count is not None else None
)
self._id_attrs = (
self.invite_link,
self.creates_join_request,
self.creator,
self.is_primary,
self.is_revoked,
)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatInviteLink"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
# Get the local timezone from the bot if it has defaults
loc_tzinfo = extract_tzinfo_from_defaults(bot)
data["creator"] = User.de_json(data.get("creator"), bot)
data["expire_date"] = from_timestamp(data.get("expire_date", None), tzinfo=loc_tzinfo)
return super().de_json(data=data, bot=bot)

View File

@@ -0,0 +1,205 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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, Optional
from telegram._chat import Chat
from telegram._chatinvitelink import ChatInviteLink
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.defaultvalue import 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.
Note:
* Since Bot API 5.5, bots are allowed to contact users who sent a join request to a chat
where the bot is an administrator with the
:attr:`~telegram.ChatMemberAdministrator.can_invite_users` administrator right - even
if the user never interacted with the bot before.
* Telegram does not guarantee that :attr:`from_user.id <from_user>` coincides with the
``chat_id`` of the user. Please use :attr:`user_chat_id` to contact the user in
response to their join request.
.. versionadded:: 13.8
.. versionchanged:: 20.1
In Bot API 6.5 the argument :paramref:`user_chat_id` was added, which changes the position
of the optional arguments :paramref:`bio` and :paramref:`invite_link`.
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.
.. versionchanged:: 20.3
|datetime_localization|
user_chat_id (:obj:`int`): Identifier of a private chat with the user who sent the join
request. This number may have more than 32 significant bits and some programming
languages may have difficulty/silent defects in interpreting it. But it has at most 52
significant bits, so a 64-bit integer or double-precision float type are safe for
storing this identifier. The bot can use this identifier for 24 hours to send messages
until the join request is processed, assuming no other administrator contacted the
user.
.. versionadded:: 20.1
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.
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.
.. versionchanged:: 20.3
|datetime_localization|
user_chat_id (:obj:`int`): Identifier of a private chat with the user who sent the join
request. This number may have more than 32 significant bits and some programming
languages may have difficulty/silent defects in interpreting it. But it has at most 52
significant bits, so a 64-bit integer or double-precision float type are safe for
storing this identifier. The bot can use this identifier for 24 hours to send messages
until the join request is processed, assuming no other administrator contacted the
user.
.. versionadded:: 20.1
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", "user_chat_id")
def __init__(
self,
chat: Chat,
from_user: User,
date: datetime.datetime,
user_chat_id: int,
bio: str = None,
invite_link: ChatInviteLink = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.chat: Chat = chat
self.from_user: User = from_user
self.date: datetime.datetime = date
self.user_chat_id: int = user_chat_id
# Optionals
self.bio: Optional[str] = bio
self.invite_link: Optional[ChatInviteLink] = invite_link
self._id_attrs = (self.chat, self.from_user, self.date)
self._freeze()
@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
# Get the local timezone from the bot if it has defaults
loc_tzinfo = extract_tzinfo_from_defaults(bot)
data["chat"] = Chat.de_json(data.get("chat"), bot)
data["from_user"] = User.de_json(data.pop("from", None), bot)
data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo)
data["invite_link"] = ChatInviteLink.de_json(data.get("invite_link"), bot)
return super().de_json(data=data, bot=bot)
async def approve(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
await 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 await self.get_bot().approve_chat_join_request(
chat_id=self.chat.id,
user_id=self.from_user.id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def decline(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
await 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 await self.get_bot().decline_chat_join_request(
chat_id=self.chat.id,
user_id=self.from_user.id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 location to which a chat is connected."""
from typing import TYPE_CHECKING, ClassVar, Optional
from telegram import constants
from telegram._files.location import Location
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class ChatLocation(TelegramObject):
"""This object represents a location to which a chat is connected.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`location` is equal.
Args:
location (:class:`telegram.Location`): The location to which the supergroup is connected.
Can't be a live location.
address (:obj:`str`): Location address;
:tg-const:`telegram.ChatLocation.MIN_ADDRESS`-
:tg-const:`telegram.ChatLocation.MAX_ADDRESS` characters, as defined by the chat owner.
Attributes:
location (:class:`telegram.Location`): The location to which the supergroup is connected.
Can't be a live location.
address (:obj:`str`): Location address;
:tg-const:`telegram.ChatLocation.MIN_ADDRESS`-
:tg-const:`telegram.ChatLocation.MAX_ADDRESS` characters, as defined by the chat owner.
"""
__slots__ = ("location", "address")
def __init__(
self,
location: Location,
address: str,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
self.location: Location = location
self.address: str = address
self._id_attrs = (self.location,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatLocation"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["location"] = Location.de_json(data.get("location"), bot)
return super().de_json(data=data, bot=bot)
MIN_ADDRESS: ClassVar[int] = constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS
""":const:`telegram.constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS`
.. versionadded:: 20.0
"""
MAX_ADDRESS: ClassVar[int] = constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS
""":const:`telegram.constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS`
.. versionadded:: 20.0
"""

View File

@@ -0,0 +1,603 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 ChatMember."""
import datetime
from typing import TYPE_CHECKING, ClassVar, Dict, Optional, Type
from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class ChatMember(TelegramObject):
"""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
considered equal, if their :attr:`user` and :attr:`status` are equal.
Examples:
:any:`Chat Member Bot <examples.chatmemberbot>`
.. versionchanged:: 20.0
* 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 removed and you should no longer
use :class:`ChatMember` directly.
* The constant ``ChatMember.CREATOR`` was replaced by :attr:`~telegram.ChatMember.OWNER`
* The constant ``ChatMember.KICKED`` was replaced by :attr:`~telegram.ChatMember.BANNED`
Args:
user (:class:`telegram.User`): Information about the user.
status (:obj:`str`): The member's status in the chat. Can be
:attr:`~telegram.ChatMember.ADMINISTRATOR`, :attr:`~telegram.ChatMember.OWNER`,
:attr:`~telegram.ChatMember.BANNED`, :attr:`~telegram.ChatMember.LEFT`,
:attr:`~telegram.ChatMember.MEMBER` or :attr:`~telegram.ChatMember.RESTRICTED`.
Attributes:
user (:class:`telegram.User`): Information about the user.
status (:obj:`str`): The member's status in the chat. Can be
:attr:`~telegram.ChatMember.ADMINISTRATOR`, :attr:`~telegram.ChatMember.OWNER`,
:attr:`~telegram.ChatMember.BANNED`, :attr:`~telegram.ChatMember.LEFT`,
:attr:`~telegram.ChatMember.MEMBER` or :attr:`~telegram.ChatMember.RESTRICTED`.
"""
__slots__ = ("user", "status")
ADMINISTRATOR: ClassVar[str] = constants.ChatMemberStatus.ADMINISTRATOR
""":const:`telegram.constants.ChatMemberStatus.ADMINISTRATOR`"""
OWNER: ClassVar[str] = constants.ChatMemberStatus.OWNER
""":const:`telegram.constants.ChatMemberStatus.OWNER`"""
BANNED: ClassVar[str] = constants.ChatMemberStatus.BANNED
""":const:`telegram.constants.ChatMemberStatus.BANNED`"""
LEFT: ClassVar[str] = constants.ChatMemberStatus.LEFT
""":const:`telegram.constants.ChatMemberStatus.LEFT`"""
MEMBER: ClassVar[str] = constants.ChatMemberStatus.MEMBER
""":const:`telegram.constants.ChatMemberStatus.MEMBER`"""
RESTRICTED: ClassVar[str] = constants.ChatMemberStatus.RESTRICTED
""":const:`telegram.constants.ChatMemberStatus.RESTRICTED`"""
def __init__(
self,
user: User,
status: str,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required by all subclasses
self.user: User = user
self.status: str = status
self._id_attrs = (self.user, self.status)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatMember"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
_class_mapping: Dict[str, Type["ChatMember"]] = {
cls.OWNER: ChatMemberOwner,
cls.ADMINISTRATOR: ChatMemberAdministrator,
cls.MEMBER: ChatMemberMember,
cls.RESTRICTED: ChatMemberRestricted,
cls.LEFT: ChatMemberLeft,
cls.BANNED: ChatMemberBanned,
}
if cls is ChatMember and data.get("status") in _class_mapping:
return _class_mapping[data.pop("status")].de_json(data=data, bot=bot)
data["user"] = User.de_json(data.get("user"), bot)
if "until_date" in data:
# Get the local timezone from the bot if it has defaults
loc_tzinfo = extract_tzinfo_from_defaults(bot)
data["until_date"] = from_timestamp(data["until_date"], tzinfo=loc_tzinfo)
return super().de_json(data=data, bot=bot)
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.
is_anonymous (:obj:`bool`): :obj:`True`, if the
user's presence in the chat is hidden.
custom_title (:obj:`str`, optional): Custom title for this user.
Attributes:
status (:obj:`str`): The member's status in the chat,
always :tg-const:`telegram.ChatMember.OWNER`.
user (:class:`telegram.User`): Information about the user.
is_anonymous (:obj:`bool`): :obj:`True`, if the user's
presence in the chat is hidden.
custom_title (:obj:`str`): Optional. Custom title for
this user.
"""
__slots__ = ("is_anonymous", "custom_title")
def __init__(
self,
user: User,
is_anonymous: bool,
custom_title: str = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(status=ChatMember.OWNER, user=user, api_kwargs=api_kwargs)
with self._unfrozen():
self.is_anonymous: bool = is_anonymous
self.custom_title: Optional[str] = custom_title
class ChatMemberAdministrator(ChatMember):
"""
Represents a chat member that has some additional privileges.
.. versionadded:: 13.7
.. versionchanged:: 20.0
* Argument and attribute ``can_manage_voice_chats`` were renamed to
:paramref:`can_manage_video_chats` and :attr:`can_manage_video_chats` in accordance to
Bot API 6.0.
* The argument :paramref:`can_manage_topics` was added, which changes the position of the
optional argument :paramref:`custom_title`.
Args:
user (:class:`telegram.User`): Information about the user.
can_be_edited (:obj:`bool`): :obj:`True`, if the bot
is allowed to edit administrator privileges of that user.
is_anonymous (:obj:`bool`): :obj:`True`, if the user's
presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :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_delete_messages (:obj:`bool`): :obj:`True`, if the
administrator can delete messages of other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the
administrator can manage video chats.
.. versionadded:: 20.0
can_restrict_members (:obj:`bool`): :obj:`True`, if the
administrator can restrict, ban or unban chat members.
can_promote_members (:obj:`bool`): :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`): :obj:`True`, if the user can change
the chat title, photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user can invite
new users to the chat.
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_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to pin messages; groups and supergroups only.
can_manage_topics (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only.
.. versionadded:: 20.0
custom_title (:obj:`str`, optional): Custom title for this user.
Attributes:
status (:obj:`str`): The member's status in the chat,
always :tg-const:`telegram.ChatMember.ADMINISTRATOR`.
user (:class:`telegram.User`): Information about the user.
can_be_edited (:obj:`bool`): :obj:`True`, if the bot
is allowed to edit administrator privileges of that user.
is_anonymous (:obj:`bool`): :obj:`True`, if the user's
presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :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_delete_messages (:obj:`bool`): :obj:`True`, if the
administrator can delete messages of other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the
administrator can manage video chats.
.. versionadded:: 20.0
can_restrict_members (:obj:`bool`): :obj:`True`, if the
administrator can restrict, ban or unban chat members.
can_promote_members (:obj:`bool`): :obj:`True`, if the administrator can add new
administrators with a subset of their own privileges or demote administrators
that they have promoted, directly or indirectly (promoted by administrators that
were appointed by the user).
can_change_info (:obj:`bool`): :obj:`True`, if the user can change
the chat title, photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user can invite
new users to the chat.
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_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to pin messages; groups and supergroups only.
can_manage_topics (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only
.. versionadded:: 20.0
custom_title (:obj:`str`): Optional. Custom title for this user.
"""
__slots__ = (
"can_be_edited",
"is_anonymous",
"can_manage_chat",
"can_delete_messages",
"can_manage_video_chats",
"can_restrict_members",
"can_promote_members",
"can_change_info",
"can_invite_users",
"can_post_messages",
"can_edit_messages",
"can_pin_messages",
"can_manage_topics",
"custom_title",
)
def __init__(
self,
user: User,
can_be_edited: bool,
is_anonymous: bool,
can_manage_chat: bool,
can_delete_messages: bool,
can_manage_video_chats: bool,
can_restrict_members: bool,
can_promote_members: bool,
can_change_info: bool,
can_invite_users: bool,
can_post_messages: bool = None,
can_edit_messages: bool = None,
can_pin_messages: bool = None,
can_manage_topics: bool = None,
custom_title: str = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(status=ChatMember.ADMINISTRATOR, user=user, api_kwargs=api_kwargs)
with self._unfrozen():
self.can_be_edited: bool = can_be_edited
self.is_anonymous: bool = is_anonymous
self.can_manage_chat: bool = can_manage_chat
self.can_delete_messages: bool = can_delete_messages
self.can_manage_video_chats: bool = can_manage_video_chats
self.can_restrict_members: bool = can_restrict_members
self.can_promote_members: bool = can_promote_members
self.can_change_info: bool = can_change_info
self.can_invite_users: bool = can_invite_users
self.can_post_messages: Optional[bool] = can_post_messages
self.can_edit_messages: Optional[bool] = can_edit_messages
self.can_pin_messages: Optional[bool] = can_pin_messages
self.can_manage_topics: Optional[bool] = can_manage_topics
self.custom_title: Optional[str] = custom_title
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 :tg-const:`telegram.ChatMember.MEMBER`.
user (:class:`telegram.User`): Information about the user.
"""
__slots__ = ()
def __init__(
self,
user: User,
*,
api_kwargs: JSONDict = None,
):
super().__init__(status=ChatMember.MEMBER, user=user, api_kwargs=api_kwargs)
self._freeze()
class ChatMemberRestricted(ChatMember):
"""
Represents a chat member that is under certain restrictions
in the chat. Supergroups only.
.. versionadded:: 13.7
.. versionchanged:: 20.0
All arguments were made positional and their order was changed.
The argument can_manage_topics was added.
Args:
user (:class:`telegram.User`): Information about the user.
is_member (:obj:`bool`): :obj:`True`, if the user is a
member of the chat at the moment of the request.
can_change_info (:obj:`bool`): :obj:`True`, if the user can change
the chat title, photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user can invite
new users to the chat.
can_pin_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to pin messages; groups and supergroups only.
can_send_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to send text messages, contacts, invoices, locations and venues.
can_send_media_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to send audios, documents, photos, videos, video notes and voice notes.
.. deprecated:: 20.1
Bot API 6.5 replaced this argument with granular media settings.
can_send_polls (:obj:`bool`): :obj:`True`, if the user is allowed
to send polls.
can_send_other_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to send animations, games, stickers and use inline bots.
can_add_web_page_previews (:obj:`bool`): :obj:`True`, if the user is
allowed to add web page previews to their messages.
can_manage_topics (:obj:`bool`): :obj:`True`, if the user is allowed to create
forum topics.
.. versionadded:: 20.0
until_date (:class:`datetime.datetime`): Date when restrictions
will be lifted for this user.
.. versionchanged:: 20.3
|datetime_localization|
can_send_audios (:obj:`bool`): :obj:`True`, if the user is allowed to send audios.
.. versionadded:: 20.1
can_send_documents (:obj:`bool`): :obj:`True`, if the user is allowed to send documents.
.. versionadded:: 20.1
can_send_photos (:obj:`bool`): :obj:`True`, if the user is allowed to send photos.
.. versionadded:: 20.1
can_send_videos (:obj:`bool`): :obj:`True`, if the user is allowed to send videos.
.. versionadded:: 20.1
can_send_video_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send video
notes.
.. versionadded:: 20.1
can_send_voice_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send voice
notes.
.. versionadded:: 20.1
Attributes:
status (:obj:`str`): The member's status in the chat,
always :tg-const:`telegram.ChatMember.RESTRICTED`.
user (:class:`telegram.User`): Information about the user.
is_member (:obj:`bool`): :obj:`True`, if the user is a
member of the chat at the moment of the request.
can_change_info (:obj:`bool`): :obj:`True`, if the user can change
the chat title, photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user can invite
new users to the chat.
can_pin_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to pin messages; groups and supergroups only.
can_send_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to send text messages, contacts, locations and venues.
can_send_media_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to send audios, documents, photos, videos, video notes and voice notes.
.. deprecated:: 20.1
Bot API 6.5 replaced this attribute with granular media settings.
can_send_polls (:obj:`bool`): :obj:`True`, if the user is allowed
to send polls.
can_send_other_messages (:obj:`bool`): :obj:`True`, if the user is allowed
to send animations, games, stickers and use inline bots.
can_add_web_page_previews (:obj:`bool`): :obj:`True`, if the user is
allowed to add web page previews to their messages.
can_manage_topics (:obj:`bool`): :obj:`True`, if the user is allowed to create
forum topics.
.. versionadded:: 20.0
until_date (:class:`datetime.datetime`): Date when restrictions
will be lifted for this user.
.. versionchanged:: 20.3
|datetime_localization|
can_send_audios (:obj:`bool`): :obj:`True`, if the user is allowed to send audios.
.. versionadded:: 20.1
can_send_documents (:obj:`bool`): :obj:`True`, if the user is allowed to send documents.
.. versionadded:: 20.1
can_send_photos (:obj:`bool`): :obj:`True`, if the user is allowed to send photos.
.. versionadded:: 20.1
can_send_videos (:obj:`bool`): :obj:`True`, if the user is allowed to send videos.
.. versionadded:: 20.1
can_send_video_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send video
notes.
.. versionadded:: 20.1
can_send_voice_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send voice
notes.
.. versionadded:: 20.1
"""
__slots__ = (
"is_member",
"can_change_info",
"can_invite_users",
"can_pin_messages",
"can_send_messages",
"can_send_media_messages",
"can_send_polls",
"can_send_other_messages",
"can_add_web_page_previews",
"can_manage_topics",
"until_date",
"can_send_audios",
"can_send_documents",
"can_send_photos",
"can_send_videos",
"can_send_video_notes",
"can_send_voice_notes",
)
def __init__(
self,
user: User,
is_member: bool,
can_change_info: bool,
can_invite_users: bool,
can_pin_messages: bool,
can_send_messages: bool,
can_send_media_messages: bool,
can_send_polls: bool,
can_send_other_messages: bool,
can_add_web_page_previews: bool,
can_manage_topics: bool,
until_date: datetime.datetime,
can_send_audios: bool,
can_send_documents: bool,
can_send_photos: bool,
can_send_videos: bool,
can_send_video_notes: bool,
can_send_voice_notes: bool,
*,
api_kwargs: JSONDict = None,
):
super().__init__(status=ChatMember.RESTRICTED, user=user, api_kwargs=api_kwargs)
with self._unfrozen():
self.is_member: bool = is_member
self.can_change_info: bool = can_change_info
self.can_invite_users: bool = can_invite_users
self.can_pin_messages: bool = can_pin_messages
self.can_send_messages: bool = can_send_messages
self.can_send_media_messages: bool = can_send_media_messages
self.can_send_polls: bool = can_send_polls
self.can_send_other_messages: bool = can_send_other_messages
self.can_add_web_page_previews: bool = can_add_web_page_previews
self.can_manage_topics: bool = can_manage_topics
self.until_date: datetime.datetime = until_date
self.can_send_audios: bool = can_send_audios
self.can_send_documents: bool = can_send_documents
self.can_send_photos: bool = can_send_photos
self.can_send_videos: bool = can_send_videos
self.can_send_video_notes: bool = can_send_video_notes
self.can_send_voice_notes: bool = can_send_voice_notes
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 :tg-const:`telegram.ChatMember.LEFT`.
user (:class:`telegram.User`): Information about the user.
"""
__slots__ = ()
def __init__(
self,
user: User,
*,
api_kwargs: JSONDict = None,
):
super().__init__(status=ChatMember.LEFT, user=user, api_kwargs=api_kwargs)
self._freeze()
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`): Date when restrictions
will be lifted for this user.
.. versionchanged:: 20.3
|datetime_localization|
Attributes:
status (:obj:`str`): The member's status in the chat,
always :tg-const:`telegram.ChatMember.BANNED`.
user (:class:`telegram.User`): Information about the user.
until_date (:class:`datetime.datetime`): Date when restrictions
will be lifted for this user.
.. versionchanged:: 20.3
|datetime_localization|
"""
__slots__ = ("until_date",)
def __init__(
self,
user: User,
until_date: datetime.datetime,
*,
api_kwargs: JSONDict = None,
):
super().__init__(status=ChatMember.BANNED, user=user, api_kwargs=api_kwargs)
with self._unfrozen():
self.until_date: datetime.datetime = until_date

View File

@@ -0,0 +1,204 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 ChatMemberUpdated."""
import datetime
from typing import TYPE_CHECKING, Dict, Optional, Tuple, Union
from telegram._chat import Chat
from telegram._chatinvitelink import ChatInviteLink
from telegram._chatmember import ChatMember
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class ChatMemberUpdated(TelegramObject):
"""This object represents changes in the status of a chat member.
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`, :attr:`date`,
:attr:`old_chat_member` and :attr:`new_chat_member` are equal.
.. versionadded:: 13.4
Note:
In Python :keyword:`from` is a reserved word. Use :paramref:`from_user` instead.
Examples:
:any:`Chat Member Bot <examples.chatmemberbot>`
Args:
chat (:class:`telegram.Chat`): Chat the user belongs to.
from_user (:class:`telegram.User`): Performer of the action, which resulted in the change.
date (:class:`datetime.datetime`): Date the change was done in Unix time. Converted to
:class:`datetime.datetime`.
.. versionchanged:: 20.3
|datetime_localization|
old_chat_member (:class:`telegram.ChatMember`): Previous information about the chat member.
new_chat_member (:class:`telegram.ChatMember`): New information about the chat member.
invite_link (:class:`telegram.ChatInviteLink`, optional): Chat invite link, which was used
by the user to join the chat. For joining by invite link events only.
via_chat_folder_invite_link (:obj:`bool`, optional): :obj:`True`, if the user joined the
chat via a chat folder invite link
.. versionadded:: 20.3
Attributes:
chat (:class:`telegram.Chat`): Chat the user belongs to.
from_user (:class:`telegram.User`): Performer of the action, which resulted in the change.
date (:class:`datetime.datetime`): Date the change was done in Unix time. Converted to
:class:`datetime.datetime`.
.. versionchanged:: 20.3
|datetime_localization|
old_chat_member (:class:`telegram.ChatMember`): Previous information about the chat member.
new_chat_member (:class:`telegram.ChatMember`): New information about the chat member.
invite_link (:class:`telegram.ChatInviteLink`): Optional. Chat invite link, which was used
by the user to join the chat. For joining by invite link events only.
via_chat_folder_invite_link (:obj:`bool`): Optional. :obj:`True`, if the user joined the
chat via a chat folder invite link
.. versionadded:: 20.3
"""
__slots__ = (
"chat",
"from_user",
"date",
"old_chat_member",
"new_chat_member",
"invite_link",
"via_chat_folder_invite_link",
)
def __init__(
self,
chat: Chat,
from_user: User,
date: datetime.datetime,
old_chat_member: ChatMember,
new_chat_member: ChatMember,
invite_link: ChatInviteLink = None,
via_chat_folder_invite_link: bool = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.chat: Chat = chat
self.from_user: User = from_user
self.date: datetime.datetime = date
self.old_chat_member: ChatMember = old_chat_member
self.new_chat_member: ChatMember = new_chat_member
self.via_chat_folder_invite_link: Optional[bool] = via_chat_folder_invite_link
# Optionals
self.invite_link: Optional[ChatInviteLink] = invite_link
self._id_attrs = (
self.chat,
self.from_user,
self.date,
self.old_chat_member,
self.new_chat_member,
)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatMemberUpdated"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
# Get the local timezone from the bot if it has defaults
loc_tzinfo = extract_tzinfo_from_defaults(bot)
data["chat"] = Chat.de_json(data.get("chat"), bot)
data["from_user"] = User.de_json(data.pop("from", None), bot)
data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo)
data["old_chat_member"] = ChatMember.de_json(data.get("old_chat_member"), bot)
data["new_chat_member"] = ChatMember.de_json(data.get("new_chat_member"), bot)
data["invite_link"] = ChatInviteLink.de_json(data.get("invite_link"), bot)
return super().de_json(data=data, bot=bot)
def _get_attribute_difference(self, attribute: str) -> Tuple[object, object]:
try:
old = self.old_chat_member[attribute]
except KeyError:
old = None
try:
new = self.new_chat_member[attribute]
except KeyError:
new = None
return old, new
def difference(
self,
) -> Dict[
str,
Tuple[
Union[str, bool, datetime.datetime, User], Union[str, bool, datetime.datetime, User]
],
]:
"""Computes the difference between :attr:`old_chat_member` and :attr:`new_chat_member`.
Example:
.. code:: pycon
>>> chat_member_updated.difference()
{'custom_title': ('old title', 'new title')}
Note:
To determine, if the :attr:`telegram.ChatMember.user` attribute has changed, *every*
attribute of the user will be checked.
.. versionadded:: 13.5
Returns:
Dict[:obj:`str`, Tuple[:class:`object`, :class:`object`]]: A dictionary mapping
attribute names to tuples of the form ``(old_value, new_value)``
"""
# we first get the names of the attributes that have changed
# user.to_dict() is unhashable, so that needs some special casing further down
old_dict = self.old_chat_member.to_dict()
old_user_dict = old_dict.pop("user")
new_dict = self.new_chat_member.to_dict()
new_user_dict = new_dict.pop("user")
# Generator for speed: we only need to iterate over it once
# we can't directly use the values from old_dict ^ new_dict b/c that set is unordered
attributes = (entry[0] for entry in set(old_dict.items()) ^ set(new_dict.items()))
result = {attribute: self._get_attribute_difference(attribute) for attribute in attributes}
if old_user_dict != new_user_dict:
result["user"] = (self.old_chat_member.user, self.new_chat_member.user)
return result # type: ignore[return-value]

View File

@@ -0,0 +1,252 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 ChatPermission."""
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
from telegram._utils.warnings import warn
from telegram.warnings import PTBDeprecationWarning
class ChatPermissions(TelegramObject):
"""Describes actions that a non-administrator user is allowed to take in a chat.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`can_send_messages`, :attr:`can_send_media_messages`,
:attr:`can_send_polls`, :attr:`can_send_other_messages`, :attr:`can_add_web_page_previews`,
:attr:`can_change_info`, :attr:`can_invite_users`, :attr:`can_pin_messages`, and
:attr:`can_manage_topics` are equal.
.. versionchanged:: 20.0
:attr:`can_manage_topics` is considered as well when comparing objects of
this type in terms of equality.
.. deprecated:: 20.1
:attr:`can_send_audios`, :attr:`can_send_documents`, :attr:`can_send_photos`,
:attr:`can_send_videos`, :attr:`can_send_video_notes` and :attr:`can_send_voice_notes`
will be considered as well when comparing objects of this type in terms of equality in
V21.
Note:
Though not stated explicitly in the official docs, Telegram changes not only the
permissions that are set, but also sets all the others to :obj:`False`. However, since not
documented, this behavior may change unbeknown to PTB.
Args:
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, implies
:attr:`can_send_messages`.
.. deprecated:: 20.1
Bot API 6.5 replaced this argument with granular media settings.
can_send_polls (:obj:`bool`, optional): :obj:`True`, if the user is allowed to send polls,
implies :attr:`can_send_messages`.
can_send_other_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to
send animations, games, stickers and use inline bots, implies
:attr:`can_send_media_messages`.
can_add_web_page_previews (:obj:`bool`, optional): :obj:`True`, if the user is allowed to
add web page previews to their messages, implies :attr:`can_send_media_messages`.
can_change_info (:obj:`bool`, optional): :obj:`True`, if the user is allowed to change the
chat title, photo and other settings. Ignored in public supergroups.
can_invite_users (:obj:`bool`, optional): :obj:`True`, if the user is allowed to invite new
users to the chat.
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to pin
messages. Ignored in public supergroups.
can_manage_topics (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to create forum topics. If omitted defaults to the value of
:attr:`can_pin_messages`.
.. versionadded:: 20.0
can_send_audios (:obj:`bool`): :obj:`True`, if the user is allowed to send audios.
.. versionadded:: 20.1
can_send_documents (:obj:`bool`): :obj:`True`, if the user is allowed to send documents.
.. versionadded:: 20.1
can_send_photos (:obj:`bool`): :obj:`True`, if the user is allowed to send photos.
.. versionadded:: 20.1
can_send_videos (:obj:`bool`): :obj:`True`, if the user is allowed to send videos.
.. versionadded:: 20.1
can_send_video_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send video
notes.
.. versionadded:: 20.1
can_send_voice_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send voice
notes.
.. versionadded:: 20.1
Attributes:
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, implies
:attr:`can_send_messages`.
.. deprecated:: 20.1
Bot API 6.5 replaced this attribute with granular media settings.
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send polls,
implies :attr:`can_send_messages`.
can_send_other_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send animations, games, stickers and use inline bots, implies
:attr:`can_send_media_messages`.
can_add_web_page_previews (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
add web page previews to their messages, implies :attr:`can_send_media_messages`.
can_change_info (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to change the
chat title, photo and other settings. Ignored in public supergroups.
can_invite_users (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to invite
new users to the chat.
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to pin
messages. Ignored in public supergroups.
can_manage_topics (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to create forum topics. If omitted defaults to the value of
:attr:`can_pin_messages`.
.. versionadded:: 20.0
can_send_audios (:obj:`bool`): :obj:`True`, if the user is allowed to send audios.
.. versionadded:: 20.1
can_send_documents (:obj:`bool`): :obj:`True`, if the user is allowed to send documents.
.. versionadded:: 20.1
can_send_photos (:obj:`bool`): :obj:`True`, if the user is allowed to send photos.
.. versionadded:: 20.1
can_send_videos (:obj:`bool`): :obj:`True`, if the user is allowed to send videos.
.. versionadded:: 20.1
can_send_video_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send video
notes.
.. versionadded:: 20.1
can_send_voice_notes (:obj:`bool`): :obj:`True`, if the user is allowed to send voice
notes.
.. versionadded:: 20.1
"""
__slots__ = (
"can_send_other_messages",
"can_invite_users",
"can_send_polls",
"can_send_messages",
"can_send_media_messages",
"can_change_info",
"can_pin_messages",
"can_add_web_page_previews",
"can_manage_topics",
"can_send_audios",
"can_send_documents",
"can_send_photos",
"can_send_videos",
"can_send_video_notes",
"can_send_voice_notes",
)
def __init__(
self,
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,
can_change_info: bool = None,
can_invite_users: bool = None,
can_pin_messages: bool = None,
can_manage_topics: bool = None,
can_send_audios: bool = None,
can_send_documents: bool = None,
can_send_photos: bool = None,
can_send_videos: bool = None,
can_send_video_notes: bool = None,
can_send_voice_notes: bool = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.can_send_messages: Optional[bool] = can_send_messages
self.can_send_media_messages: Optional[bool] = can_send_media_messages
self.can_send_polls: Optional[bool] = can_send_polls
self.can_send_other_messages: Optional[bool] = can_send_other_messages
self.can_add_web_page_previews: Optional[bool] = can_add_web_page_previews
self.can_change_info: Optional[bool] = can_change_info
self.can_invite_users: Optional[bool] = can_invite_users
self.can_pin_messages: Optional[bool] = can_pin_messages
self.can_manage_topics: Optional[bool] = can_manage_topics
self.can_send_audios: Optional[bool] = can_send_audios
self.can_send_documents: Optional[bool] = can_send_documents
self.can_send_photos: Optional[bool] = can_send_photos
self.can_send_videos: Optional[bool] = can_send_videos
self.can_send_video_notes: Optional[bool] = can_send_video_notes
self.can_send_voice_notes: Optional[bool] = can_send_voice_notes
self._id_attrs = (
self.can_send_messages,
self.can_send_media_messages,
self.can_send_polls,
self.can_send_other_messages,
self.can_add_web_page_previews,
self.can_change_info,
self.can_invite_users,
self.can_pin_messages,
self.can_manage_topics,
)
self._freeze()
def __eq__(self, other: object) -> bool:
warn(
"In v21, granular media settings will be considered as well when comparing"
" ChatPermissions instances.",
PTBDeprecationWarning,
stacklevel=2,
)
return super().__eq__(other)
def __hash__(self) -> int:
# Intend: Added so support the own __eq__ function (which otherwise breaks hashing)
return super().__hash__()
@classmethod
def all_permissions(cls) -> "ChatPermissions":
"""
This method returns an :class:`ChatPermissions` instance with all attributes
set to :obj:`True`. This is e.g. useful when unrestricting a chat member with
:meth:`telegram.Bot.restrict_chat_member`.
.. versionadded:: 20.0
"""
return cls(*(15 * (True,)))
@classmethod
def no_permissions(cls) -> "ChatPermissions":
"""
This method returns an :class:`ChatPermissions` instance
with all attributes set to :obj:`False`.
.. versionadded:: 20.0
"""
return cls(*(15 * (False,)))

View File

@@ -0,0 +1,107 @@
#!/usr/bin/env python
# pylint: disable=too-many-arguments
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 ChosenInlineResult."""
from typing import TYPE_CHECKING, Optional
from telegram._files.location import Location
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class ChosenInlineResult(TelegramObject):
"""
Represents a result of an inline query that was chosen by the user and sent to their chat
partner.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`result_id` is equal.
Note:
* In Python :keyword:`from` is a reserved word. Use :paramref:`from_user` instead.
* It is necessary to enable inline feedback via `@Botfather <https://t.me/BotFather>`_ in
order to receive these objects in updates.
Args:
result_id (:obj:`str`): The unique identifier for the result that was chosen.
from_user (:class:`telegram.User`): The user that chose the result.
location (:class:`telegram.Location`, optional): Sender location, only for bots that
require user location.
inline_message_id (:obj:`str`, optional): Identifier of the sent inline message. Available
only if there is an inline keyboard attached to the message. Will be also received in
callback queries and can be used to edit the message.
query (:obj:`str`): The query that was used to obtain the result.
Attributes:
result_id (:obj:`str`): The unique identifier for the result that was chosen.
from_user (:class:`telegram.User`): The user that chose the result.
location (:class:`telegram.Location`): Optional. Sender location, only for bots that
require user location.
inline_message_id (:obj:`str`): Optional. Identifier of the sent inline message. Available
only if there is an inline keyboard attached to the message. Will be also received in
callback queries and can be used to edit the message.
query (:obj:`str`): The query that was used to obtain the result.
"""
__slots__ = ("location", "result_id", "from_user", "inline_message_id", "query")
def __init__(
self,
result_id: str,
from_user: User,
query: str,
location: Location = None,
inline_message_id: str = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.result_id: str = result_id
self.from_user: User = from_user
self.query: str = query
# Optionals
self.location: Optional[Location] = location
self.inline_message_id: Optional[str] = inline_message_id
self._id_attrs = (self.result_id,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChosenInlineResult"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
# Required
data["from_user"] = User.de_json(data.pop("from", None), bot)
# Optionals
data["location"] = Location.de_json(data.get("location"), bot)
return super().de_json(data=data, bot=bot)

View File

@@ -0,0 +1,160 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Dice."""
from typing import ClassVar, List
from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class Dice(TelegramObject):
"""
This object represents an animated emoji with a random value for currently supported base
emoji. (The singular form of "dice" is "die". However, PTB mimics the Telegram API, which uses
the term "dice".)
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`value` and :attr:`emoji` are equal.
Note:
If :attr:`emoji` is :tg-const:`telegram.Dice.DARTS`, a value of 6 currently
represents a bullseye, while a value of 1 indicates that the dartboard was missed.
However, this behaviour is undocumented and might be changed by Telegram.
If :attr:`emoji` is :tg-const:`telegram.Dice.BASKETBALL`, a value of 4 or 5
currently score a basket, while a value of 1 to 3 indicates that the basket was missed.
However, this behaviour is undocumented and might be changed by Telegram.
If :attr:`emoji` is :tg-const:`telegram.Dice.FOOTBALL`, a value of 4 to 5
currently scores a goal, while a value of 1 to 3 indicates that the goal was missed.
However, this behaviour is undocumented and might be changed by Telegram.
If :attr:`emoji` is :tg-const:`telegram.Dice.BOWLING`, a value of 6 knocks
all the pins, while a value of 1 means all the pins were missed.
However, this behaviour is undocumented and might be changed by Telegram.
If :attr:`emoji` is :tg-const:`telegram.Dice.SLOT_MACHINE`, each value
corresponds to a unique combination of symbols, which
can be found in our
:wiki:`wiki <Code-snippets#map-a-slot-machine-dice-value-to-the-corresponding-symbols>`.
However, this behaviour is undocumented and might be changed by Telegram.
..
In args, some links for limits of `value` intentionally point to constants for only
one emoji of a group to avoid duplication. For example, maximum value for Dice, Darts and
Bowling is linked to a constant for Bowling.
Args:
value (:obj:`int`): Value of the dice.
:tg-const:`telegram.Dice.MIN_VALUE`-:tg-const:`telegram.Dice.MAX_VALUE_BOWLING`
for :tg-const:`telegram.Dice.DICE`, :tg-const:`telegram.Dice.DARTS` and
:tg-const:`telegram.Dice.BOWLING` base emoji,
:tg-const:`telegram.Dice.MIN_VALUE`-:tg-const:`telegram.Dice.MAX_VALUE_BASKETBALL`
for :tg-const:`telegram.Dice.BASKETBALL` and :tg-const:`telegram.Dice.FOOTBALL`
base emoji,
:tg-const:`telegram.Dice.MIN_VALUE`-:tg-const:`telegram.Dice.MAX_VALUE_SLOT_MACHINE`
for :tg-const:`telegram.Dice.SLOT_MACHINE` base emoji.
emoji (:obj:`str`): Emoji on which the dice throw animation is based.
Attributes:
value (:obj:`int`): Value of the dice.
:tg-const:`telegram.Dice.MIN_VALUE`-:tg-const:`telegram.Dice.MAX_VALUE_BOWLING`
for :tg-const:`telegram.Dice.DICE`, :tg-const:`telegram.Dice.DARTS` and
:tg-const:`telegram.Dice.BOWLING` base emoji,
:tg-const:`telegram.Dice.MIN_VALUE`-:tg-const:`telegram.Dice.MAX_VALUE_BASKETBALL`
for :tg-const:`telegram.Dice.BASKETBALL` and :tg-const:`telegram.Dice.FOOTBALL`
base emoji,
:tg-const:`telegram.Dice.MIN_VALUE`-:tg-const:`telegram.Dice.MAX_VALUE_SLOT_MACHINE`
for :tg-const:`telegram.Dice.SLOT_MACHINE` base emoji.
emoji (:obj:`str`): Emoji on which the dice throw animation is based.
"""
__slots__ = ("emoji", "value")
def __init__(self, value: int, emoji: str, *, api_kwargs: JSONDict = None):
super().__init__(api_kwargs=api_kwargs)
self.value: int = value
self.emoji: str = emoji
self._id_attrs = (self.value, self.emoji)
self._freeze()
DICE: ClassVar[str] = constants.DiceEmoji.DICE # skipcq: PTC-W0052
""":const:`telegram.constants.DiceEmoji.DICE`"""
DARTS: ClassVar[str] = constants.DiceEmoji.DARTS
""":const:`telegram.constants.DiceEmoji.DARTS`"""
BASKETBALL: ClassVar[str] = constants.DiceEmoji.BASKETBALL
""":const:`telegram.constants.DiceEmoji.BASKETBALL`"""
FOOTBALL: ClassVar[str] = constants.DiceEmoji.FOOTBALL
""":const:`telegram.constants.DiceEmoji.FOOTBALL`"""
SLOT_MACHINE: ClassVar[str] = constants.DiceEmoji.SLOT_MACHINE
""":const:`telegram.constants.DiceEmoji.SLOT_MACHINE`"""
BOWLING: ClassVar[str] = constants.DiceEmoji.BOWLING
"""
:const:`telegram.constants.DiceEmoji.BOWLING`
.. versionadded:: 13.4
"""
ALL_EMOJI: ClassVar[List[str]] = list(constants.DiceEmoji)
"""List[:obj:`str`]: A list of all available dice emoji."""
MIN_VALUE: ClassVar[int] = constants.DiceLimit.MIN_VALUE
""":const:`telegram.constants.DiceLimit.MIN_VALUE`
.. versionadded:: 20.0
"""
MAX_VALUE_BOWLING: ClassVar[int] = constants.DiceLimit.MAX_VALUE_BOWLING
""":const:`telegram.constants.DiceLimit.MAX_VALUE_BOWLING`
.. versionadded:: 20.0
"""
MAX_VALUE_DARTS: ClassVar[int] = constants.DiceLimit.MAX_VALUE_DARTS
""":const:`telegram.constants.DiceLimit.MAX_VALUE_DARTS`
.. versionadded:: 20.0
"""
MAX_VALUE_DICE: ClassVar[int] = constants.DiceLimit.MAX_VALUE_DICE
""":const:`telegram.constants.DiceLimit.MAX_VALUE_DICE`
.. versionadded:: 20.0
"""
MAX_VALUE_BASKETBALL: ClassVar[int] = constants.DiceLimit.MAX_VALUE_BASKETBALL
""":const:`telegram.constants.DiceLimit.MAX_VALUE_BASKETBALL`
.. versionadded:: 20.0
"""
MAX_VALUE_FOOTBALL: ClassVar[int] = constants.DiceLimit.MAX_VALUE_FOOTBALL
""":const:`telegram.constants.DiceLimit.MAX_VALUE_FOOTBALL`
.. versionadded:: 20.0
"""
MAX_VALUE_SLOT_MACHINE: ClassVar[int] = constants.DiceLimit.MAX_VALUE_SLOT_MACHINE
""":const:`telegram.constants.DiceLimit.MAX_VALUE_SLOT_MACHINE`
.. versionadded:: 20.0
"""

View File

@@ -0,0 +1,100 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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/].
"""Common base class for media objects"""
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import File
class _BaseMedium(TelegramObject):
"""Base class for objects representing the various media file types.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`, optional): File size.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`): Optional. File size.
"""
__slots__ = ("file_id", "file_size", "file_unique_id")
def __init__(
self,
file_id: str,
file_unique_id: str,
file_size: int = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.file_id: str = str(file_id)
self.file_unique_id: str = str(file_unique_id)
# Optionals
self.file_size: Optional[int] = file_size
self._id_attrs = (self.file_unique_id,)
async def get_file(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> "File":
"""Convenience wrapper over :meth:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return await self.get_bot().get_file(
file_id=self.file_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

View File

@@ -0,0 +1,131 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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/].
"""Common base class for media objects with thumbnails"""
from typing import TYPE_CHECKING, Optional, Type, TypeVar
from telegram._files._basemedium import _BaseMedium
from telegram._files.photosize import PhotoSize
from telegram._utils.types import JSONDict
from telegram._utils.warnings_transition import (
warn_about_deprecated_arg_return_new_arg,
warn_about_deprecated_attr_in_property,
)
if TYPE_CHECKING:
from telegram import Bot
# pylint: disable=invalid-name
ThumbedMT_co = TypeVar("ThumbedMT_co", bound="_BaseThumbedMedium", covariant=True)
class _BaseThumbedMedium(_BaseMedium):
"""
Base class for objects representing the various media file types that may include a thumbnail.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`, optional): File size.
thumb (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by sender.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by sender.
.. versionadded:: 20.2
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`): Optional. File size.
thumbnail (:class:`telegram.PhotoSize`): Optional. Thumbnail as defined by sender.
.. versionadded:: 20.2
"""
__slots__ = ("thumbnail",)
def __init__(
self,
file_id: str,
file_unique_id: str,
file_size: int = None,
thumb: PhotoSize = None,
thumbnail: PhotoSize = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
api_kwargs=api_kwargs,
)
self.thumbnail: Optional[PhotoSize] = warn_about_deprecated_arg_return_new_arg(
deprecated_arg=thumb,
new_arg=thumbnail,
deprecated_arg_name="thumb",
new_arg_name="thumbnail",
bot_api_version="6.6",
stacklevel=3,
)
@property
def thumb(self) -> Optional[PhotoSize]:
""":class:`telegram.PhotoSize`: Optional. Thumbnail as defined by sender.
.. deprecated:: 20.2
|thumbattributedeprecation| :attr:`thumbnail`.
"""
warn_about_deprecated_attr_in_property(
deprecated_attr_name="thumb", new_attr_name="thumbnail", bot_api_version="6.6"
)
return self.thumbnail
@classmethod
def de_json(
cls: Type[ThumbedMT_co], data: Optional[JSONDict], bot: "Bot"
) -> Optional[ThumbedMT_co]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
# In case this wasn't already done by the subclass
if not isinstance(data.get("thumbnail"), PhotoSize):
data["thumbnail"] = PhotoSize.de_json(data.get("thumbnail"), bot)
api_kwargs = {}
# This is a deprecated field that TG still returns for backwards compatibility
# Let's filter it out to speed up the de-json process
if data.get("thumb") is not None:
api_kwargs["thumb"] = data.pop("thumb")
return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs)

View File

@@ -0,0 +1,105 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Animation."""
from typing import Optional
from telegram._files._basethumbedmedium import _BaseThumbedMedium
from telegram._files.photosize import PhotoSize
from telegram._utils.types import JSONDict
class Animation(_BaseThumbedMedium):
"""This object represents an animation file (GIF or H.264/MPEG-4 AVC video without sound).
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`, optional): Animation thumbnail as defined by sender.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
file_name (:obj:`str`, optional): Original animation filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Animation thumbnail as defined by
sender.
.. versionadded:: 20.2
Attributes:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
file_name (:obj:`str`): Optional. Original animation filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Animation thumbnail as defined by
sender.
.. versionadded:: 20.2
"""
__slots__ = ("duration", "height", "file_name", "mime_type", "width")
def __init__(
self,
file_id: str,
file_unique_id: str,
width: int,
height: int,
duration: int,
thumb: PhotoSize = None,
file_name: str = None,
mime_type: str = None,
file_size: int = None,
thumbnail: PhotoSize = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
api_kwargs=api_kwargs,
thumbnail=thumbnail,
)
with self._unfrozen():
# Required
self.width: int = width
self.height: int = height
self.duration: int = duration
# Optional
self.mime_type: Optional[str] = mime_type
self.file_name: Optional[str] = file_name

View File

@@ -0,0 +1,108 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Audio."""
from typing import Optional
from telegram._files._basethumbedmedium import _BaseThumbedMedium
from telegram._files.photosize import PhotoSize
from telegram._utils.types import JSONDict
class Audio(_BaseThumbedMedium):
"""This object represents an audio file to be treated as music by the Telegram clients.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`, optional): Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`, optional): Title of the audio as defined by sender or by audio tags.
file_name (:obj:`str`, optional): Original filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
file_size (:obj:`int`, optional): File size in bytes.
thumb (:class:`telegram.PhotoSize`, optional): Thumbnail of the album cover to
which the music file belongs.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail of the album cover to
which the music file belongs.
.. versionadded:: 20.2
Attributes:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`): Optional. Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Thumbnail of the album cover to
which the music file belongs.
.. versionadded:: 20.2
"""
__slots__ = ("duration", "file_name", "mime_type", "performer", "title")
def __init__(
self,
file_id: str,
file_unique_id: str,
duration: int,
performer: str = None,
title: str = None,
mime_type: str = None,
file_size: int = None,
thumb: PhotoSize = None,
file_name: str = None,
thumbnail: PhotoSize = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
thumbnail=thumbnail,
api_kwargs=api_kwargs,
)
with self._unfrozen():
# Required
self.duration: int = duration
# Optional
self.performer: Optional[str] = performer
self.title: Optional[str] = title
self.mime_type: Optional[str] = mime_type
self.file_name: Optional[str] = file_name

View File

@@ -0,0 +1,176 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 ChatPhoto."""
from typing import TYPE_CHECKING, ClassVar
from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import File
class ChatPhoto(TelegramObject):
"""This object represents a chat photo.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`small_file_unique_id` and :attr:`big_file_unique_id` are
equal.
Args:
small_file_id (:obj:`str`): File identifier of small
(:tg-const:`telegram.ChatPhoto.SIZE_SMALL` x :tg-const:`telegram.ChatPhoto.SIZE_SMALL`)
chat photo. This file_id can be used only for photo download and only for as long
as the photo is not changed.
small_file_unique_id (:obj:`str`): Unique file identifier of small
(:tg-const:`telegram.ChatPhoto.SIZE_SMALL` x :tg-const:`telegram.ChatPhoto.SIZE_SMALL`)
chat photo, which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
big_file_id (:obj:`str`): File identifier of big
(:tg-const:`telegram.ChatPhoto.SIZE_BIG` x :tg-const:`telegram.ChatPhoto.SIZE_BIG`)
chat photo. This file_id can be used only for photo download and only for as long as
the photo is not changed.
big_file_unique_id (:obj:`str`): Unique file identifier of big
(:tg-const:`telegram.ChatPhoto.SIZE_BIG` x :tg-const:`telegram.ChatPhoto.SIZE_BIG`)
chat photo, which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
Attributes:
small_file_id (:obj:`str`): File identifier of small
(:tg-const:`telegram.ChatPhoto.SIZE_SMALL` x :tg-const:`telegram.ChatPhoto.SIZE_SMALL`)
chat photo. This file_id can be used only for photo download and only for as long
as the photo is not changed.
small_file_unique_id (:obj:`str`): Unique file identifier of small
(:tg-const:`telegram.ChatPhoto.SIZE_SMALL` x :tg-const:`telegram.ChatPhoto.SIZE_SMALL`)
chat photo, which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
big_file_id (:obj:`str`): File identifier of big
(:tg-const:`telegram.ChatPhoto.SIZE_BIG` x :tg-const:`telegram.ChatPhoto.SIZE_BIG`)
chat photo. This file_id can be used only for photo download and only for as long as
the photo is not changed.
big_file_unique_id (:obj:`str`): Unique file identifier of big
(:tg-const:`telegram.ChatPhoto.SIZE_BIG` x :tg-const:`telegram.ChatPhoto.SIZE_BIG`)
chat photo, which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
"""
__slots__ = (
"big_file_unique_id",
"small_file_id",
"small_file_unique_id",
"big_file_id",
)
def __init__(
self,
small_file_id: str,
small_file_unique_id: str,
big_file_id: str,
big_file_unique_id: str,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
self.small_file_id: str = small_file_id
self.small_file_unique_id: str = small_file_unique_id
self.big_file_id: str = big_file_id
self.big_file_unique_id: str = big_file_unique_id
self._id_attrs = (
self.small_file_unique_id,
self.big_file_unique_id,
)
self._freeze()
async def get_small_file(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> "File":
"""Convenience wrapper over :meth:`telegram.Bot.get_file` for getting the small
(:tg-const:`telegram.ChatPhoto.SIZE_SMALL` x :tg-const:`telegram.ChatPhoto.SIZE_SMALL`)
chat photo
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return await self.get_bot().get_file(
file_id=self.small_file_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def get_big_file(
self,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> "File":
"""Convenience wrapper over :meth:`telegram.Bot.get_file` for getting the
big (:tg-const:`telegram.ChatPhoto.SIZE_BIG` x :tg-const:`telegram.ChatPhoto.SIZE_BIG`)
chat photo
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return await self.get_bot().get_file(
file_id=self.big_file_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
SIZE_SMALL: ClassVar[int] = constants.ChatPhotoSize.SMALL
""":const:`telegram.constants.ChatPhotoSize.SMALL`
.. versionadded:: 20.0
"""
SIZE_BIG: ClassVar[int] = constants.ChatPhotoSize.BIG
""":const:`telegram.constants.ChatPhotoSize.BIG`
.. versionadded:: 20.0
"""

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Contact."""
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class Contact(TelegramObject):
"""This object represents a phone contact.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`phone_number` is equal.
Args:
phone_number (:obj:`str`): Contact's phone number.
first_name (:obj:`str`): Contact's first name.
last_name (:obj:`str`, optional): Contact's last name.
user_id (:obj:`int`, optional): Contact's user identifier in Telegram.
vcard (:obj:`str`, optional): Additional data about the contact in the form of a vCard.
Attributes:
phone_number (:obj:`str`): Contact's phone number.
first_name (:obj:`str`): Contact's first name.
last_name (:obj:`str`): Optional. Contact's last name.
user_id (:obj:`int`): Optional. Contact's user identifier in Telegram.
vcard (:obj:`str`): Optional. Additional data about the contact in the form of a vCard.
"""
__slots__ = ("vcard", "user_id", "first_name", "last_name", "phone_number")
def __init__(
self,
phone_number: str,
first_name: str,
last_name: str = None,
user_id: int = None,
vcard: str = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.phone_number: str = str(phone_number)
self.first_name: str = first_name
# Optionals
self.last_name: Optional[str] = last_name
self.user_id: Optional[int] = user_id
self.vcard: Optional[str] = vcard
self._id_attrs = (self.phone_number,)
self._freeze()

View File

@@ -0,0 +1,89 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Document."""
from typing import Optional
from telegram._files._basethumbedmedium import _BaseThumbedMedium
from telegram._files.photosize import PhotoSize
from telegram._utils.types import JSONDict
class Document(_BaseThumbedMedium):
"""This object represents a general file
(as opposed to photos, voice messages and audio files).
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
thumb (:class:`telegram.PhotoSize`, optional): Document thumbnail as defined by sender.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
file_name (:obj:`str`, optional): Original filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Document thumbnail as defined by sender.
.. versionadded:: 20.2
Attributes:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Document thumbnail as defined by sender.
.. versionadded:: 20.2
"""
__slots__ = ("file_name", "mime_type")
def __init__(
self,
file_id: str,
file_unique_id: str,
thumb: PhotoSize = None,
file_name: str = None,
mime_type: str = None,
file_size: int = None,
thumbnail: PhotoSize = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
thumbnail=thumbnail,
api_kwargs=api_kwargs,
)
with self._unfrozen():
# Optional
self.mime_type: Optional[str] = mime_type
self.file_name: Optional[str] = file_name

View File

@@ -0,0 +1,337 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 File."""
import shutil
import urllib.parse as urllib_parse
from base64 import b64decode
from pathlib import Path
from typing import TYPE_CHECKING, BinaryIO, Optional
from telegram._passport.credentials import decrypt
from telegram._telegramobject import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.files import is_local_file
from telegram._utils.types import FilePathInput, JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import FileCredentials
class File(TelegramObject):
"""
This object represents a file ready to be downloaded. The file can be e.g. downloaded with
:attr:`download_to_drive`. It is guaranteed that the link will be valid for at least 1 hour.
When the link expires, a new one can be requested by calling :meth:`telegram.Bot.get_file`.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
.. versionchanged:: 20.0
``download`` was split into :meth:`download_to_drive` and :meth:`download_to_memory`.
Note:
* Maximum file size to download is
:tg-const:`telegram.constants.FileSizeLimit.FILESIZE_DOWNLOAD`.
* If you obtain an instance of this class from :attr:`telegram.PassportFile.get_file`,
then it will automatically be decrypted as it downloads when you call e.g.
:meth:`download_to_drive`.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`, optional): File size in bytes, if known.
file_path (:obj:`str`, optional): File path. Use e.g. :meth:`download_to_drive` to get the
file.
Attributes:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`): Optional. File size in bytes, if known.
file_path (:obj:`str`): Optional. File path. Use e.g. :meth:`download_to_drive` to get the
file.
"""
__slots__ = (
"file_id",
"file_size",
"file_unique_id",
"file_path",
"_credentials",
)
def __init__(
self,
file_id: str,
file_unique_id: str,
file_size: int = None,
file_path: str = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.file_id: str = str(file_id)
self.file_unique_id: str = str(file_unique_id)
# Optionals
self.file_size: Optional[int] = file_size
self.file_path: Optional[str] = file_path
self._credentials: Optional["FileCredentials"] = None
self._id_attrs = (self.file_unique_id,)
self._freeze()
def _get_encoded_url(self) -> str:
"""Convert any UTF-8 char in :obj:`File.file_path` into a url encoded ASCII string."""
sres = urllib_parse.urlsplit(str(self.file_path))
return urllib_parse.urlunsplit(
urllib_parse.SplitResult(
sres.scheme, sres.netloc, urllib_parse.quote(sres.path), sres.query, sres.fragment
)
)
def _prepare_decrypt(self, buf: bytes) -> bytes:
return decrypt(b64decode(self._credentials.secret), b64decode(self._credentials.hash), buf)
async def download_to_drive(
self,
custom_path: FilePathInput = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
) -> Path:
"""
Download this file. By default, the file is saved in the current working directory with
:attr:`file_path` as file name. If the file has no filename, the file ID will be used as
filename. If :paramref:`custom_path` is supplied as a :obj:`str` or :obj:`pathlib.Path`,
it will be saved to that path.
Note:
If :paramref:`custom_path` isn't provided and :attr:`file_path` is the path of a
local file (which is the case when a Bot API Server is running in local mode), this
method will just return the path.
The only exception to this are encrypted files (e.g. a passport file). For these, a
file with the prefix `decrypted_` will be created in the same directory as the
original file in order to decrypt the file without changing the existing one
in-place.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionchanged:: 20.0
* :paramref:`custom_path` parameter now also accepts :class:`pathlib.Path` as argument.
* Returns :class:`pathlib.Path` object in cases where previously a :obj:`str` was
returned.
* This method was previously called ``download``. It was split into
:meth:`download_to_drive` and :meth:`download_to_memory`.
Args:
custom_path (:class:`pathlib.Path` | :obj:`str` , optional): The path where the file
will be saved to. If not specified, will be saved in the current working directory
with :attr:`file_path` as file name or the :attr:`file_id` if :attr:`file_path`
is not set.
Keyword Args:
read_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.read_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.connect_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
Returns:
:class:`pathlib.Path`: Returns the Path object the file was downloaded to.
"""
local_file = is_local_file(self.file_path)
url = None if local_file else self._get_encoded_url()
# if _credentials exists we want to decrypt the file
if local_file and self._credentials:
file_to_decrypt = Path(self.file_path)
buf = self._prepare_decrypt(file_to_decrypt.read_bytes())
if custom_path is not None:
path = Path(custom_path)
else:
path = Path(str(file_to_decrypt.parent) + "/decrypted_" + file_to_decrypt.name)
path.write_bytes(buf)
return path
if custom_path is not None and local_file:
shutil.copyfile(self.file_path, str(custom_path))
return Path(custom_path)
if custom_path:
filename = Path(custom_path)
elif local_file:
return Path(self.file_path)
elif self.file_path:
filename = Path(Path(self.file_path).name)
else:
filename = Path.cwd() / self.file_id
buf = await self.get_bot().request.retrieve(
url,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
)
if self._credentials:
buf = self._prepare_decrypt(buf)
filename.write_bytes(buf)
return filename
async def download_to_memory(
self,
out: BinaryIO,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
) -> None:
"""
Download this file into memory. :paramref:`out` needs to be supplied with a
:obj:`io.BufferedIOBase`, the file contents will be saved to that object using the
:obj:`out.write<io.BufferedIOBase.write>` method.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 20.0
Args:
out (:obj:`io.BufferedIOBase`): A file-like object. Must be opened for writing in
binary mode.
Keyword Args:
read_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.read_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.connect_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
"""
local_file = is_local_file(self.file_path)
url = None if local_file else self._get_encoded_url()
path = Path(self.file_path) if local_file else None
if local_file:
buf = path.read_bytes()
else:
buf = await self.get_bot().request.retrieve(
url,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
)
if self._credentials:
buf = self._prepare_decrypt(buf)
out.write(buf)
async def download_as_bytearray(
self,
buf: bytearray = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
) -> bytearray:
"""Download this file and return it as a bytearray.
Args:
buf (:obj:`bytearray`, optional): Extend the given bytearray with the downloaded data.
Keyword Args:
read_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.read_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
.. versionadded:: 20.0
write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
.. versionadded:: 20.0
connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.connect_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
.. versionadded:: 20.0
pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
.. versionadded:: 20.0
Returns:
:obj:`bytearray`: The same object as :paramref:`buf` if it was specified. Otherwise a
newly allocated :obj:`bytearray`.
"""
if buf is None:
buf = bytearray()
if is_local_file(self.file_path):
bytes_data = Path(self.file_path).read_bytes()
else:
bytes_data = await self.get_bot().request.retrieve(
self._get_encoded_url(),
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
)
if self._credentials:
buf.extend(self._prepare_decrypt(bytes_data))
else:
buf.extend(bytes_data)
return buf
def set_credentials(self, credentials: "FileCredentials") -> None:
"""Sets the passport credentials for the file.
Args:
credentials (:class:`telegram.FileCredentials`): The credentials.
"""
self._credentials = credentials

View File

@@ -0,0 +1,104 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 InputFile."""
import mimetypes
from typing import IO, Optional, Union
from uuid import uuid4
from telegram._utils.files import load_file
from telegram._utils.types import FieldTuple
_DEFAULT_MIME_TYPE = "application/octet-stream"
class InputFile:
"""This object represents a Telegram InputFile.
.. versionchanged:: 20.0
* The former attribute ``attach`` was renamed to :attr:`attach_name`.
* Method ``is_image`` was removed. If you pass :obj:`bytes` to :paramref:`obj` and would
like to have the mime type automatically guessed, please pass :paramref:`filename`
in addition.
Args:
obj (:term:`file object` | :obj:`bytes` | :obj:`str`): An open file descriptor or the files
content as bytes or string.
Note:
If :paramref:`obj` is a string, it will be encoded as bytes via
:external:obj:`obj.encode('utf-8') <str.encode>`.
.. versionchanged:: 20.0
Accept string input.
filename (:obj:`str`, optional): Filename for this InputFile.
attach (:obj:`bool`, optional): Pass :obj:`True` if the parameter this file belongs to in
the request to Telegram should point to the multipart data via an ``attach://`` URI.
Defaults to `False`.
Attributes:
input_file_content (:obj:`bytes`): The binary content of the file to send.
attach_name (:obj:`str`): Optional. If present, the parameter this file belongs to in
the request to Telegram should point to the multipart data via a an URI of the form
``attach://<attach_name>`` URI.
filename (:obj:`str`): Filename for the file to be sent.
mimetype (:obj:`str`): The mimetype inferred from the file to be sent.
"""
__slots__ = ("filename", "attach_name", "input_file_content", "mimetype")
def __init__(
self, obj: Union[IO[bytes], bytes, str], filename: str = None, attach: bool = False
):
if isinstance(obj, bytes):
self.input_file_content: bytes = obj
elif isinstance(obj, str):
self.input_file_content = obj.encode("utf-8")
else:
reported_filename, self.input_file_content = load_file(obj)
filename = filename or reported_filename
self.attach_name: Optional[str] = "attached" + uuid4().hex if attach else None
if filename:
self.mimetype: str = (
mimetypes.guess_type(filename, strict=False)[0] or _DEFAULT_MIME_TYPE
)
else:
self.mimetype = _DEFAULT_MIME_TYPE
self.filename: str = filename or self.mimetype.replace("/", ".")
@property
def field_tuple(self) -> FieldTuple:
"""Field tuple representing the contents of the file for upload to the Telegram servers.
Returns:
Tuple[:obj:`str`, :obj:`bytes`, :obj:`str`]:
"""
return self.filename, self.input_file_content, self.mimetype
@property
def attach_uri(self) -> Optional[str]:
"""URI to insert into the JSON data for uploading the file. Returns :obj:`None`, if
:attr:`attach_name` is :obj:`None`.
"""
return f"attach://{self.attach_name}" if self.attach_name else None

View File

@@ -0,0 +1,717 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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/].
"""Base class for Telegram InputMedia Objects."""
from typing import Optional, Sequence, Tuple, Union
from telegram._files.animation import Animation
from telegram._files.audio import Audio
from telegram._files.document import Document
from telegram._files.inputfile import InputFile
from telegram._files.photosize import PhotoSize
from telegram._files.video import Video
from telegram._messageentity import MessageEntity
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.files import parse_file_input
from telegram._utils.types import FileInput, JSONDict, ODVInput
from telegram._utils.warnings_transition import (
warn_about_deprecated_attr_in_property,
warn_about_thumb_return_thumbnail,
)
from telegram.constants import InputMediaType
MediaType = Union[Animation, Audio, Document, PhotoSize, Video]
class InputMedia(TelegramObject):
"""
Base class for Telegram InputMedia Objects.
.. versionchanged:: 20.0
Added arguments and attributes :attr:`type`, :attr:`media`, :attr:`caption`,
:attr:`caption_entities`, :paramref:`parse_mode`.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Args:
media_type (:obj:`str`): Type of media that the instance represents.
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation` | :class:`telegram.Audio` | \
:class:`telegram.Document` | :class:`telegram.PhotoSize` | \
:class:`telegram.Video`): File to send.
|fileinputnopath|
Lastly you can pass an existing telegram media object of the corresponding type
to send.
caption (:obj:`str`, optional): Caption of the media to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
.. versionchanged:: 20.0
|sequenceclassargs|
parse_mode (:obj:`str`, optional): |parse_mode|
Attributes:
type (:obj:`str`): Type of the input media.
media (:obj:`str` | :class:`telegram.InputFile`): Media to send.
caption (:obj:`str`): Optional. Caption of the media to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
* |tupleclassattrs|
* |alwaystuple|
"""
__slots__ = ("caption", "caption_entities", "media", "parse_mode", "type")
def __init__(
self,
media_type: str,
media: Union[str, InputFile, MediaType],
caption: str = None,
caption_entities: Sequence[MessageEntity] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
self.type: str = media_type
self.media: Union[str, InputFile, Animation, Audio, Document, PhotoSize, Video] = media
self.caption: Optional[str] = caption
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.parse_mode: ODVInput[str] = parse_mode
self._freeze()
@staticmethod
def _parse_thumb_input(thumb: Optional[FileInput]) -> Optional[Union[str, InputFile]]:
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
return (
parse_file_input(thumb, attach=True, local_mode=True) if thumb is not None else thumb
)
class InputMediaAnimation(InputMedia):
"""Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
Note:
When using a :class:`telegram.Animation` for the :attr:`media` attribute, it will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Animation` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the animation, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
caption (:obj:`str`, optional): Caption of the animation to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`, optional): |parse_mode|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
.. versionchanged:: 20.0
|sequenceclassargs|
width (:obj:`int`, optional): Animation width.
height (:obj:`int`, optional): Animation height.
duration (:obj:`int`, optional): Animation duration in seconds.
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the animation needs to be covered
with a spoiler animation.
.. versionadded:: 20.0
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionadded:: 20.2
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.ANIMATION`.
media (:obj:`str` | :class:`telegram.InputFile`): Animation to send.
caption (:obj:`str`): Optional. Caption of the animation to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
* |tupleclassattrs|
* |alwaystuple|
width (:obj:`int`): Optional. Animation width.
height (:obj:`int`): Optional. Animation height.
duration (:obj:`int`): Optional. Animation duration in seconds.
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the animation is covered with a
spoiler animation.
.. versionadded:: 20.0
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
"""
__slots__ = ("duration", "height", "width", "has_spoiler", "thumbnail")
def __init__(
self,
media: Union[FileInput, Animation],
thumb: FileInput = None,
caption: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
width: int = None,
height: int = None,
duration: int = None,
caption_entities: Sequence[MessageEntity] = None,
filename: str = None,
has_spoiler: bool = None,
thumbnail: FileInput = None,
*,
api_kwargs: JSONDict = None,
):
if isinstance(media, Animation):
width = media.width if width is None else width
height = media.height if height is None else height
duration = media.duration if duration is None else duration
media = media.file_id
else:
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
media = parse_file_input(media, filename=filename, attach=True, local_mode=True)
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
super().__init__(
InputMediaType.ANIMATION,
media,
caption,
caption_entities,
parse_mode,
api_kwargs=api_kwargs,
)
with self._unfrozen():
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
self.width: Optional[int] = width
self.height: Optional[int] = height
self.duration: Optional[int] = duration
self.has_spoiler: Optional[bool] = has_spoiler
@property
def thumb(self) -> Optional[Union[str, InputFile]]:
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
.. deprecated:: 20.2
|thumbattributedeprecation| :attr:`thumbnail`.
"""
warn_about_deprecated_attr_in_property(
deprecated_attr_name="thumb",
new_attr_name="thumbnail",
bot_api_version="6.6",
)
return self.thumbnail
class InputMediaPhoto(InputMedia):
"""Represents a photo to be sent.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.PhotoSize`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the photo, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional ): Caption of the photo to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`, optional): |parse_mode|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
.. versionchanged:: 20.0
|sequenceclassargs|
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the photo needs to be covered
with a spoiler animation.
.. versionadded:: 20.0
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.PHOTO`.
media (:obj:`str` | :class:`telegram.InputFile`): Photo to send.
caption (:obj:`str`): Optional. Caption of the photo to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
* |tupleclassattrs|
* |alwaystuple|
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the photo is covered with a
spoiler animation.
.. versionadded:: 20.0
"""
__slots__ = ("has_spoiler",)
def __init__(
self,
media: Union[FileInput, PhotoSize],
caption: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence[MessageEntity] = None,
filename: str = None,
has_spoiler: bool = None,
*,
api_kwargs: JSONDict = None,
):
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
media = parse_file_input(media, PhotoSize, filename=filename, attach=True, local_mode=True)
super().__init__(
InputMediaType.PHOTO,
media,
caption,
caption_entities,
parse_mode,
api_kwargs=api_kwargs,
)
with self._unfrozen():
self.has_spoiler: Optional[bool] = has_spoiler
class InputMediaVideo(InputMedia):
"""Represents a video to be sent.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Note:
* When using a :class:`telegram.Video` for the :attr:`media` attribute, it will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
* :paramref:`thumb` will be ignored for small video files, for which Telegram can easily
generate thumbnails. However, this behaviour is undocumented and might be changed
by Telegram.
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Video`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Video` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the video, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional): Caption of the video to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`, optional): |parse_mode|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
.. versionchanged:: 20.0
|sequenceclassargs|
width (:obj:`int`, optional): Video width.
height (:obj:`int`, optional): Video height.
duration (:obj:`int`, optional): Video duration in seconds.
supports_streaming (:obj:`bool`, optional): Pass :obj:`True`, if the uploaded video is
suitable for streaming.
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the video needs to be covered
with a spoiler animation.
.. versionadded:: 20.0
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionadded:: 20.2
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.VIDEO`.
media (:obj:`str` | :class:`telegram.InputFile`): Video file to send.
caption (:obj:`str`): Optional. Caption of the video to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
* |tupleclassattrs|
* |alwaystuple|
width (:obj:`int`): Optional. Video width.
height (:obj:`int`): Optional. Video height.
duration (:obj:`int`): Optional. Video duration in seconds.
supports_streaming (:obj:`bool`): Optional. :obj:`True`, if the uploaded video is
suitable for streaming.
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the video is covered with a
spoiler animation.
.. versionadded:: 20.0
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
"""
__slots__ = (
"duration",
"height",
"supports_streaming",
"width",
"has_spoiler",
"thumbnail",
)
def __init__(
self,
media: Union[FileInput, Video],
caption: str = None,
width: int = None,
height: int = None,
duration: int = None,
supports_streaming: bool = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
caption_entities: Sequence[MessageEntity] = None,
filename: str = None,
has_spoiler: bool = None,
thumbnail: FileInput = None,
*,
api_kwargs: JSONDict = None,
):
if isinstance(media, Video):
width = width if width is not None else media.width
height = height if height is not None else media.height
duration = duration if duration is not None else media.duration
media = media.file_id
else:
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
media = parse_file_input(media, filename=filename, attach=True, local_mode=True)
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
super().__init__(
InputMediaType.VIDEO,
media,
caption,
caption_entities,
parse_mode,
api_kwargs=api_kwargs,
)
with self._unfrozen():
self.width: Optional[int] = width
self.height: Optional[int] = height
self.duration: Optional[int] = duration
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
self.supports_streaming: Optional[bool] = supports_streaming
self.has_spoiler: Optional[bool] = has_spoiler
@property
def thumb(self) -> Optional[Union[str, InputFile]]:
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
.. deprecated:: 20.2
|thumbattributedeprecation| :attr:`thumbnail`.
"""
warn_about_deprecated_attr_in_property(
deprecated_attr_name="thumb",
new_attr_name="thumbnail",
bot_api_version="6.6",
)
return self.thumbnail
class InputMediaAudio(InputMedia):
"""Represents an audio file to be treated as music to be sent.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Note:
When using a :class:`telegram.Audio` for the :attr:`media` attribute, it will take the
duration, performer and title from that video, unless otherwise specified with the
optional arguments.
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Audio`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Audio` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the audio, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional): Caption of the audio to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`, optional): |parse_mode|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
.. versionchanged:: 20.0
|sequenceclassargs|
duration (:obj:`int`, optional): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`, optional): Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`, optional): Title of the audio as defined by sender or by audio tags.
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionadded:: 20.2
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.AUDIO`.
media (:obj:`str` | :class:`telegram.InputFile`): Audio file to send.
caption (:obj:`str`): Optional. Caption of the audio to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
* |tupleclassattrs|
* |alwaystuple|
duration (:obj:`int`): Optional. Duration of the audio in seconds.
performer (:obj:`str`): Optional. Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
"""
__slots__ = ("duration", "performer", "title", "thumbnail")
def __init__(
self,
media: Union[FileInput, Audio],
thumb: FileInput = None,
caption: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
duration: int = None,
performer: str = None,
title: str = None,
caption_entities: Sequence[MessageEntity] = None,
filename: str = None,
thumbnail: FileInput = None,
*,
api_kwargs: JSONDict = None,
):
if isinstance(media, Audio):
duration = media.duration if duration is None else duration
performer = media.performer if performer is None else performer
title = media.title if title is None else title
media = media.file_id
else:
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
media = parse_file_input(media, filename=filename, attach=True, local_mode=True)
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
super().__init__(
InputMediaType.AUDIO,
media,
caption,
caption_entities,
parse_mode,
api_kwargs=api_kwargs,
)
with self._unfrozen():
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
self.duration: Optional[int] = duration
self.title: Optional[str] = title
self.performer: Optional[str] = performer
@property
def thumb(self) -> Optional[Union[str, InputFile]]:
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
.. deprecated:: 20.2
|thumbattributedeprecation| :attr:`thumbnail`.
"""
warn_about_deprecated_attr_in_property(
deprecated_attr_name="thumb",
new_attr_name="thumbnail",
bot_api_version="6.6",
)
return self.thumbnail
class InputMediaDocument(InputMedia):
"""Represents a general file to be sent.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Document`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Document` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the document, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional): Caption of the document to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`, optional): |parse_mode|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
.. versionchanged:: 20.0
|sequenceclassargs|
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
.. deprecated:: 20.2
|thumbargumentdeprecation| :paramref:`thumbnail`.
disable_content_type_detection (:obj:`bool`, optional): Disables automatic server-side
content type detection for files uploaded using multipart/form-data. Always
:obj:`True`, if the document is sent as part of an album.
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
.. versionadded:: 20.2
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.DOCUMENT`.
media (:obj:`str` | :class:`telegram.InputFile`): File to send.
caption (:obj:`str`): Optional. Caption of the document to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
* |tupleclassattrs|
* |alwaystuple|
disable_content_type_detection (:obj:`bool`): Optional. Disables automatic server-side
content type detection for files uploaded using multipart/form-data. Always
:obj:`True`, if the document is sent as part of an album.
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
"""
__slots__ = ("disable_content_type_detection", "thumbnail")
def __init__(
self,
media: Union[FileInput, Document],
thumb: FileInput = None,
caption: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_content_type_detection: bool = None,
caption_entities: Sequence[MessageEntity] = None,
filename: str = None,
thumbnail: FileInput = None,
*,
api_kwargs: JSONDict = None,
):
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
media = parse_file_input(media, Document, filename=filename, attach=True, local_mode=True)
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
super().__init__(
InputMediaType.DOCUMENT,
media,
caption,
caption_entities,
parse_mode,
api_kwargs=api_kwargs,
)
with self._unfrozen():
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
self.disable_content_type_detection: Optional[bool] = disable_content_type_detection
@property
def thumb(self) -> Optional[Union[str, InputFile]]:
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
.. deprecated:: 20.2
|thumbattributedeprecation| :attr:`thumbnail`.
"""
warn_about_deprecated_attr_in_property(
deprecated_attr_name="thumb",
new_attr_name="thumbnail",
bot_api_version="6.6",
)
return self.thumbnail

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 InputSticker."""
from typing import Optional, Sequence, Tuple, Union
from telegram._files.inputfile import InputFile
from telegram._files.sticker import MaskPosition
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.files import parse_file_input
from telegram._utils.types import FileInput, JSONDict
class InputSticker(TelegramObject):
"""
This object describes a sticker to be added to a sticker set.
.. versionadded:: 20.2
Args:
sticker (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path`): The
added sticker. |uploadinputnopath| Animated and video stickers can't be uploaded via
HTTP URL.
emoji_list (Sequence[:obj:`str`]): Sequence of
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
sticker.
mask_position (:obj:`telegram.MaskPosition`, optional): Position where the mask should be
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
keywords (Sequence[:obj:`str`], optional): Sequence of
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
for the sticker with the total length of up to
:tg-const:`telegram.constants.StickerLimit.MAX_KEYWORD_LENGTH` characters. For
":tg-const:`telegram.constants.StickerType.REGULAR`" and
":tg-const:`telegram.constants.StickerType.CUSTOM_EMOJI`" stickers only.
Attributes:
sticker (:obj:`str` | :class:`telegram.InputFile`): The added sticker.
emoji_list (Tuple[:obj:`str`]): Tuple of
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
sticker.
mask_position (:obj:`telegram.MaskPosition`): Optional. Position where the mask should be
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
keywords (Tuple[:obj:`str`]): Optional. Tuple of
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
for the sticker with the total length of up to
:tg-const:`telegram.constants.StickerLimit.MAX_KEYWORD_LENGTH` characters. For
":tg-const:`telegram.constants.StickerType.REGULAR`" and
":tg-const:`telegram.constants.StickerType.CUSTOM_EMOJI`" stickers only.
"""
__slots__ = ("sticker", "emoji_list", "mask_position", "keywords")
def __init__(
self,
sticker: FileInput,
emoji_list: Sequence[str],
mask_position: MaskPosition = None,
keywords: Sequence[str] = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
self.sticker: Union[str, InputFile] = parse_file_input(
sticker,
local_mode=True,
attach=True,
)
self.emoji_list: Tuple[str, ...] = parse_sequence_arg(emoji_list)
self.mask_position: Optional[MaskPosition] = mask_position
self.keywords: Tuple[str, ...] = parse_sequence_arg(keywords)
self._freeze()

View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# 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 Location."""
from typing import ClassVar, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class Location(TelegramObject):
"""This object represents a point on the map.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`longitude` and :attr:`latitude` are equal.
Args:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
horizontal_accuracy (:obj:`float`, optional): The radius of uncertainty for the location,
measured in meters; 0-:tg-const:`telegram.Location.HORIZONTAL_ACCURACY`.
live_period (:obj:`int`, optional): Time relative to the message sending date, during which
the location can be updated, in seconds. For active live locations only.
heading (:obj:`int`, optional): The direction in which user is moving, in degrees;
:tg-const:`telegram.Location.MIN_HEADING`-:tg-const:`telegram.Location.MAX_HEADING`.
For active live locations only.
proximity_alert_radius (:obj:`int`, optional): Maximum distance for proximity alerts about
approaching another chat member, in meters. For sent live locations only.
Attributes:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
horizontal_accuracy (:obj:`float`): Optional. The radius of uncertainty for the location,
measured in meters; 0-:tg-const:`telegram.Location.HORIZONTAL_ACCURACY`.
live_period (:obj:`int`): Optional. Time relative to the message sending date, during which
the location can be updated, in seconds. For active live locations only.
heading (:obj:`int`): Optional. The direction in which user is moving, in degrees;
:tg-const:`telegram.Location.MIN_HEADING`-:tg-const:`telegram.Location.MAX_HEADING`.
For active live locations only.
proximity_alert_radius (:obj:`int`): Optional. Maximum distance for proximity alerts about
approaching another chat member, in meters. For sent live locations only.
"""
__slots__ = (
"longitude",
"horizontal_accuracy",
"proximity_alert_radius",
"live_period",
"latitude",
"heading",
)
def __init__(
self,
longitude: float,
latitude: float,
horizontal_accuracy: float = None,
live_period: int = None,
heading: int = None,
proximity_alert_radius: int = None,
*,
api_kwargs: JSONDict = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.longitude: float = longitude
self.latitude: float = latitude
# Optionals
self.horizontal_accuracy: Optional[float] = horizontal_accuracy
self.live_period: Optional[int] = live_period
self.heading: Optional[int] = heading
self.proximity_alert_radius: Optional[int] = (
int(proximity_alert_radius) if proximity_alert_radius else None
)
self._id_attrs = (self.longitude, self.latitude)
self._freeze()
HORIZONTAL_ACCURACY: ClassVar[int] = constants.LocationLimit.HORIZONTAL_ACCURACY
""":const:`telegram.constants.LocationLimit.HORIZONTAL_ACCURACY`
.. versionadded:: 20.0
"""
MIN_HEADING: ClassVar[int] = constants.LocationLimit.MIN_HEADING
""":const:`telegram.constants.LocationLimit.MIN_HEADING`
.. versionadded:: 20.0
"""
MAX_HEADING: ClassVar[int] = constants.LocationLimit.MAX_HEADING
""":const:`telegram.constants.LocationLimit.MAX_HEADING`
.. versionadded:: 20.0
"""

Some files were not shown because too many files have changed in this diff Show More