mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-12-22 14:35:00 +01:00
Add __slots__ (#2345)
Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> Co-authored-by: Hinrich Mahler <hinrich.mahler@freenet.de>
This commit is contained in:
parent
cc43aef64b
commit
92ff6a8e2b
251 changed files with 2908 additions and 99 deletions
|
@ -26,6 +26,7 @@ import warnings
|
|||
from typing import TYPE_CHECKING, List, Optional, Tuple, Type, TypeVar
|
||||
|
||||
from telegram.utils.types import JSONDict
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
|
@ -38,11 +39,19 @@ class TelegramObject:
|
|||
|
||||
_id_attrs: Tuple[object, ...] = ()
|
||||
|
||||
# Adding slots reduces memory usage & allows for faster attribute access.
|
||||
# Only instance variables should be added to __slots__.
|
||||
# We add __dict__ here for backward compatibility & also to avoid repetition for subclasses.
|
||||
__slots__ = ('__dict__',)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.to_dict())
|
||||
|
||||
def __getitem__(self, item: str) -> object:
|
||||
return self.__dict__[item]
|
||||
return getattr(self, item, None)
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
@staticmethod
|
||||
def _parse_data(data: Optional[JSONDict]) -> Optional[JSONDict]:
|
||||
|
@ -102,11 +111,16 @@ class TelegramObject:
|
|||
"""
|
||||
data = {}
|
||||
|
||||
for key in iter(self.__dict__):
|
||||
# We want to get all attributes for the class, using self.__slots__ only includes the
|
||||
# attributes used by that class itself, and not its superclass(es). Hence we get its MRO
|
||||
# and then get their attributes. The `[:-2]` slice excludes the `object` class & the
|
||||
# TelegramObject class itself.
|
||||
attrs = {attr for cls in self.__class__.__mro__[:-2] for attr in cls.__slots__}
|
||||
for key in attrs:
|
||||
if key == 'bot' or key.startswith('_'):
|
||||
continue
|
||||
|
||||
value = self.__dict__[key]
|
||||
value = getattr(self, key, None)
|
||||
if value is not None:
|
||||
if hasattr(value, 'to_dict'):
|
||||
data[key] = value.to_dict()
|
||||
|
|
|
@ -158,6 +158,18 @@ class Bot(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'token',
|
||||
'base_url',
|
||||
'base_file_url',
|
||||
'private_key',
|
||||
'defaults',
|
||||
'_bot',
|
||||
'_commands',
|
||||
'_request',
|
||||
'logger',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
token: str,
|
||||
|
@ -184,6 +196,7 @@ class Bot(TelegramObject):
|
|||
self._bot: Optional[User] = None
|
||||
self._commands: Optional[List[BotCommand]] = None
|
||||
self._request = request or Request()
|
||||
self.private_key = None
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
if private_key:
|
||||
|
@ -196,6 +209,12 @@ class Bot(TelegramObject):
|
|||
private_key, password=private_key_password, backend=default_backend()
|
||||
)
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
if issubclass(self.__class__, Bot) and self.__class__ is not Bot:
|
||||
object.__setattr__(self, key, value)
|
||||
return
|
||||
super().__setattr__(key, value)
|
||||
|
||||
def _insert_defaults(
|
||||
self, data: Dict[str, object], timeout: ODVInput[float]
|
||||
) -> Optional[float]:
|
||||
|
|
|
@ -41,6 +41,8 @@ class BotCommand(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('description', '_id_attrs', 'command')
|
||||
|
||||
def __init__(self, command: str, description: str, **_kwargs: Any):
|
||||
self.command = command
|
||||
self.description = description
|
||||
|
|
|
@ -85,6 +85,18 @@ class CallbackQuery(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'game_short_name',
|
||||
'message',
|
||||
'chat_instance',
|
||||
'id',
|
||||
'from_user',
|
||||
'inline_message_id',
|
||||
'data',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -143,6 +143,30 @@ class Chat(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bio',
|
||||
'id',
|
||||
'type',
|
||||
'last_name',
|
||||
'bot',
|
||||
'sticker_set_name',
|
||||
'slow_mode_delay',
|
||||
'location',
|
||||
'first_name',
|
||||
'permissions',
|
||||
'invite_link',
|
||||
'pinned_message',
|
||||
'description',
|
||||
'can_set_sticker_set',
|
||||
'username',
|
||||
'title',
|
||||
'photo',
|
||||
'linked_chat_id',
|
||||
'all_members_are_administrators',
|
||||
'message_auto_delete_time',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
SENDER: ClassVar[str] = constants.CHAT_SENDER
|
||||
""":const:`telegram.constants.CHAT_SENDER`
|
||||
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
"""This module contains an object that represents a Telegram ChatAction."""
|
||||
from typing import ClassVar
|
||||
from telegram import constants
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
|
||||
class ChatAction:
|
||||
"""Helper class to provide constants for different chat actions."""
|
||||
|
||||
__slots__ = ('__dict__',) # Adding __dict__ here since it doesn't subclass TGObject
|
||||
FIND_LOCATION: ClassVar[str] = constants.CHATACTION_FIND_LOCATION
|
||||
""":const:`telegram.constants.CHATACTION_FIND_LOCATION`"""
|
||||
RECORD_AUDIO: ClassVar[str] = constants.CHATACTION_RECORD_AUDIO
|
||||
|
@ -65,3 +67,6 @@ class ChatAction:
|
|||
""":const:`telegram.constants.CHATACTION_UPLOAD_VIDEO`"""
|
||||
UPLOAD_VIDEO_NOTE: ClassVar[str] = constants.CHATACTION_UPLOAD_VIDEO_NOTE
|
||||
""":const:`telegram.constants.CHATACTION_UPLOAD_VIDEO_NOTE`"""
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
|
|
@ -60,6 +60,16 @@ class ChatInviteLink(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'invite_link',
|
||||
'creator',
|
||||
'is_primary',
|
||||
'is_revoked',
|
||||
'expire_date',
|
||||
'member_limit',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
invite_link: str,
|
||||
|
|
|
@ -47,6 +47,8 @@ class ChatLocation(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('location', '_id_attrs', 'address')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
location: Location,
|
||||
|
|
|
@ -138,6 +138,32 @@ class ChatMember(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'is_member',
|
||||
'can_restrict_members',
|
||||
'can_delete_messages',
|
||||
'custom_title',
|
||||
'can_be_edited',
|
||||
'can_post_messages',
|
||||
'can_send_messages',
|
||||
'can_edit_messages',
|
||||
'can_send_media_messages',
|
||||
'is_anonymous',
|
||||
'can_add_web_page_previews',
|
||||
'can_send_other_messages',
|
||||
'can_invite_users',
|
||||
'can_send_polls',
|
||||
'user',
|
||||
'can_promote_members',
|
||||
'status',
|
||||
'can_change_info',
|
||||
'can_pin_messages',
|
||||
'can_manage_chat',
|
||||
'can_manage_voice_chats',
|
||||
'until_date',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
ADMINISTRATOR: ClassVar[str] = constants.CHATMEMBER_ADMINISTRATOR
|
||||
""":const:`telegram.constants.CHATMEMBER_ADMINISTRATOR`"""
|
||||
CREATOR: ClassVar[str] = constants.CHATMEMBER_CREATOR
|
||||
|
|
|
@ -62,6 +62,16 @@ class ChatMemberUpdated(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'chat',
|
||||
'from_user',
|
||||
'date',
|
||||
'old_chat_member',
|
||||
'new_chat_member',
|
||||
'invite_link',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
chat: Chat,
|
||||
|
|
|
@ -78,6 +78,18 @@ class ChatPermissions(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'can_send_other_messages',
|
||||
'can_invite_users',
|
||||
'can_send_polls',
|
||||
'_id_attrs',
|
||||
'can_send_messages',
|
||||
'can_send_media_messages',
|
||||
'can_change_info',
|
||||
'can_pin_messages',
|
||||
'can_add_web_page_previews',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
can_send_messages: bool = None,
|
||||
|
|
|
@ -61,6 +61,8 @@ class ChosenInlineResult(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('location', 'result_id', 'from_user', 'inline_message_id', '_id_attrs', 'query')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
result_id: str,
|
||||
|
|
|
@ -64,6 +64,8 @@ class Dice(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('emoji', 'value', '_id_attrs')
|
||||
|
||||
def __init__(self, value: int, emoji: str, **_kwargs: Any):
|
||||
self.value = value
|
||||
self.emoji = emoji
|
||||
|
|
|
@ -41,6 +41,9 @@ def _lstrip_str(in_s: str, lstr: str) -> str:
|
|||
class TelegramError(Exception):
|
||||
"""Base class for Telegram errors."""
|
||||
|
||||
# Apparently the base class Exception already has __dict__ in it, so its not included here
|
||||
__slots__ = ('message',)
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__()
|
||||
|
||||
|
@ -62,10 +65,14 @@ class TelegramError(Exception):
|
|||
class Unauthorized(TelegramError):
|
||||
"""Raised when the bot has not enough rights to perform the requested action."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class InvalidToken(TelegramError):
|
||||
"""Raised when the token is invalid."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__('Invalid token')
|
||||
|
||||
|
@ -76,14 +83,20 @@ class InvalidToken(TelegramError):
|
|||
class NetworkError(TelegramError):
|
||||
"""Base class for exceptions due to networking errors."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class BadRequest(NetworkError):
|
||||
"""Raised when Telegram could not process the request correctly."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class TimedOut(NetworkError):
|
||||
"""Raised when a request took too long to finish."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__('Timed out')
|
||||
|
||||
|
@ -100,6 +113,8 @@ class ChatMigrated(TelegramError):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('new_chat_id',)
|
||||
|
||||
def __init__(self, new_chat_id: int):
|
||||
super().__init__(f'Group migrated to supergroup. New chat id: {new_chat_id}')
|
||||
self.new_chat_id = new_chat_id
|
||||
|
@ -117,6 +132,8 @@ class RetryAfter(TelegramError):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('retry_after',)
|
||||
|
||||
def __init__(self, retry_after: int):
|
||||
super().__init__(f'Flood control exceeded. Retry in {float(retry_after)} seconds')
|
||||
self.retry_after = float(retry_after)
|
||||
|
@ -128,5 +145,7 @@ class RetryAfter(TelegramError):
|
|||
class Conflict(TelegramError):
|
||||
"""Raised when a long poll or webhook conflicts with another one."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __reduce__(self) -> Tuple[type, Tuple[str]]:
|
||||
return self.__class__, (self.message,)
|
||||
|
|
|
@ -18,10 +18,13 @@
|
|||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the BasePersistence class."""
|
||||
import warnings
|
||||
from sys import version_info as py_ver
|
||||
from abc import ABC, abstractmethod
|
||||
from copy import copy
|
||||
from typing import DefaultDict, Dict, Optional, Tuple, cast, ClassVar
|
||||
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
from telegram import Bot
|
||||
|
||||
from telegram.utils.types import ConversationDict
|
||||
|
@ -75,6 +78,18 @@ class BasePersistence(ABC):
|
|||
persistence class.
|
||||
"""
|
||||
|
||||
# Apparently Py 3.7 and below have '__dict__' in ABC
|
||||
if py_ver < (3, 7):
|
||||
__slots__ = ('store_user_data', 'store_chat_data', 'store_bot_data', 'bot')
|
||||
else:
|
||||
__slots__ = (
|
||||
'store_user_data', # type: ignore[assignment]
|
||||
'store_chat_data',
|
||||
'store_bot_data',
|
||||
'bot',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __new__(
|
||||
cls, *args: object, **kwargs: object # pylint: disable=W0613
|
||||
) -> 'BasePersistence':
|
||||
|
@ -104,12 +119,13 @@ class BasePersistence(ABC):
|
|||
def update_bot_data_replace_bot(data: Dict) -> None:
|
||||
return update_bot_data(instance.replace_bot(data))
|
||||
|
||||
instance.get_user_data = get_user_data_insert_bot
|
||||
instance.get_chat_data = get_chat_data_insert_bot
|
||||
instance.get_bot_data = get_bot_data_insert_bot
|
||||
instance.update_user_data = update_user_data_replace_bot
|
||||
instance.update_chat_data = update_chat_data_replace_bot
|
||||
instance.update_bot_data = update_bot_data_replace_bot
|
||||
# We want to ignore TGDeprecation warnings so we use obj.__setattr__. Adds to __dict__
|
||||
object.__setattr__(instance, 'get_user_data', get_user_data_insert_bot)
|
||||
object.__setattr__(instance, 'get_chat_data', get_chat_data_insert_bot)
|
||||
object.__setattr__(instance, 'get_bot_data', get_bot_data_insert_bot)
|
||||
object.__setattr__(instance, 'update_user_data', update_user_data_replace_bot)
|
||||
object.__setattr__(instance, 'update_chat_data', update_chat_data_replace_bot)
|
||||
object.__setattr__(instance, 'update_bot_data', update_bot_data_replace_bot)
|
||||
return instance
|
||||
|
||||
def __init__(
|
||||
|
@ -123,6 +139,16 @@ class BasePersistence(ABC):
|
|||
self.store_bot_data = store_bot_data
|
||||
self.bot: Bot = None # type: ignore[assignment]
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
# Allow user defined subclasses to have custom attributes.
|
||||
if issubclass(self.__class__, BasePersistence) and self.__class__.__name__ not in {
|
||||
'DictPersistence',
|
||||
'PicklePersistence',
|
||||
}:
|
||||
object.__setattr__(self, key, value)
|
||||
return
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
def set_bot(self, bot: Bot) -> None:
|
||||
"""Set the Bot to be used by this persistence instance.
|
||||
|
||||
|
|
|
@ -73,6 +73,20 @@ class CallbackContext:
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'_dispatcher',
|
||||
'_bot_data',
|
||||
'_chat_data',
|
||||
'_user_data',
|
||||
'args',
|
||||
'matches',
|
||||
'error',
|
||||
'job',
|
||||
'async_args',
|
||||
'async_kwargs',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __init__(self, dispatcher: 'Dispatcher'):
|
||||
"""
|
||||
Args:
|
||||
|
@ -229,12 +243,13 @@ class CallbackContext:
|
|||
return self
|
||||
|
||||
def update(self, data: Dict[str, object]) -> None:
|
||||
"""Updates ``self.__dict__`` with the passed data.
|
||||
"""Updates ``self.__slots__`` with the passed data.
|
||||
|
||||
Args:
|
||||
data (Dict[:obj:`str`, :obj:`object`]): The data.
|
||||
"""
|
||||
self.__dict__.update(data)
|
||||
for key, value in data.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
@property
|
||||
def bot(self) -> 'Bot':
|
||||
|
|
|
@ -120,6 +120,8 @@ class CallbackQueryHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('pattern', 'pass_groups', 'pass_groupdict')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
callback: Callable[[Update, 'CallbackContext'], RT],
|
||||
|
|
|
@ -96,6 +96,7 @@ class ChatMemberHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('chat_member_types',)
|
||||
MY_CHAT_MEMBER: ClassVar[int] = -1
|
||||
""":obj:`int`: Used as a constant to handle only :attr:`telegram.Update.my_chat_member`."""
|
||||
CHAT_MEMBER: ClassVar[int] = 0
|
||||
|
|
|
@ -99,6 +99,8 @@ class ChosenInlineResultHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('pattern',)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
callback: Callable[[Update, 'CallbackContext'], RT],
|
||||
|
|
|
@ -129,6 +129,8 @@ class CommandHandler(Handler[Update]):
|
|||
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
|
||||
"""
|
||||
|
||||
__slots__ = ('command', 'filters', 'pass_args')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
command: SLT[str],
|
||||
|
@ -350,6 +352,9 @@ class PrefixHandler(CommandHandler):
|
|||
|
||||
"""
|
||||
|
||||
# 'prefix' is a class property, & 'command' is included in the superclass, so they're left out.
|
||||
__slots__ = ('_prefix', '_command', '_commands')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
prefix: SLT[str],
|
||||
|
|
|
@ -45,6 +45,9 @@ CheckUpdateType = Optional[Tuple[Tuple[int, ...], Handler, object]]
|
|||
|
||||
|
||||
class _ConversationTimeoutContext:
|
||||
# '__dict__' is not included since this a private class
|
||||
__slots__ = ('conversation_key', 'update', 'dispatcher', 'callback_context')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
conversation_key: Tuple[int, ...],
|
||||
|
@ -182,6 +185,26 @@ class ConversationHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'_entry_points',
|
||||
'_states',
|
||||
'_fallbacks',
|
||||
'_allow_reentry',
|
||||
'_per_user',
|
||||
'_per_chat',
|
||||
'_per_message',
|
||||
'_conversation_timeout',
|
||||
'_name',
|
||||
'persistent',
|
||||
'_persistence',
|
||||
'_map_to_parent',
|
||||
'timeout_jobs',
|
||||
'_timeout_jobs_lock',
|
||||
'_conversations',
|
||||
'_conversations_lock',
|
||||
'logger',
|
||||
)
|
||||
|
||||
END: ClassVar[int] = -1
|
||||
""":obj:`int`: Used as a constant to return when a conversation is ended."""
|
||||
TIMEOUT: ClassVar[int] = -2
|
||||
|
|
|
@ -22,6 +22,7 @@ from typing import NoReturn, Optional, Dict, Any
|
|||
|
||||
import pytz
|
||||
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
from telegram.utils.helpers import DEFAULT_NONE
|
||||
from telegram.utils.types import ODVInput
|
||||
|
||||
|
@ -56,6 +57,19 @@ class Defaults:
|
|||
:meth:`Dispatcher.add_error_handler`. Defaults to :obj:`False`.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'_timeout',
|
||||
'_tzinfo',
|
||||
'_disable_web_page_preview',
|
||||
'_run_async',
|
||||
'_quote',
|
||||
'_disable_notification',
|
||||
'_allow_sending_without_reply',
|
||||
'_parse_mode',
|
||||
'_api_defaults',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parse_mode: str = None,
|
||||
|
@ -91,8 +105,11 @@ class Defaults:
|
|||
if value not in [None, DEFAULT_NONE]:
|
||||
self._api_defaults[kwarg] = value
|
||||
# Special casing, as None is a valid default value
|
||||
if self.timeout != DEFAULT_NONE:
|
||||
self._api_defaults['timeout'] = self.timeout
|
||||
if self._timeout != DEFAULT_NONE:
|
||||
self._api_defaults['timeout'] = self._timeout
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
@property
|
||||
def api_defaults(self) -> Dict[str, Any]: # skip-cq: PY-D0003
|
||||
|
@ -243,7 +260,7 @@ class Defaults:
|
|||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if isinstance(other, Defaults):
|
||||
return self.__dict__ == other.__dict__
|
||||
return all(getattr(self, attr) == getattr(other, attr) for attr in self.__slots__)
|
||||
return False
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
|
|
|
@ -79,6 +79,17 @@ class DictPersistence(BasePersistence):
|
|||
persistence class.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'_user_data',
|
||||
'_chat_data',
|
||||
'_bot_data',
|
||||
'_conversations',
|
||||
'_user_data_json',
|
||||
'_chat_data_json',
|
||||
'_bot_data_json',
|
||||
'_conversations_json',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
store_user_data: bool = True,
|
||||
|
|
|
@ -26,14 +26,14 @@ from functools import wraps
|
|||
from queue import Empty, Queue
|
||||
from threading import BoundedSemaphore, Event, Lock, Thread, current_thread
|
||||
from time import sleep
|
||||
from typing import TYPE_CHECKING, Callable, DefaultDict, Dict, List, Optional, Set, Union
|
||||
from typing import TYPE_CHECKING, Callable, DefaultDict, Dict, List, Optional, Union, Set
|
||||
from uuid import uuid4
|
||||
|
||||
from telegram import TelegramError, Update
|
||||
from telegram.ext import BasePersistence
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.ext.handler import Handler
|
||||
from telegram.utils.deprecate import TelegramDeprecationWarning
|
||||
from telegram.utils.deprecate import TelegramDeprecationWarning, set_new_attribute_deprecated
|
||||
from telegram.ext.utils.promise import Promise
|
||||
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
|
||||
|
||||
|
@ -98,6 +98,8 @@ class DispatcherHandlerStop(Exception):
|
|||
state (:obj:`object`, optional): The next state of the conversation.
|
||||
"""
|
||||
|
||||
__slots__ = ('state',)
|
||||
|
||||
def __init__(self, state: object = None) -> None:
|
||||
super().__init__()
|
||||
self.state = state
|
||||
|
@ -134,6 +136,30 @@ class Dispatcher:
|
|||
|
||||
"""
|
||||
|
||||
# Allowing '__weakref__' creation here since we need it for the singleton
|
||||
__slots__ = (
|
||||
'workers',
|
||||
'persistence',
|
||||
'use_context',
|
||||
'update_queue',
|
||||
'job_queue',
|
||||
'user_data',
|
||||
'chat_data',
|
||||
'bot_data',
|
||||
'_update_persistence_lock',
|
||||
'handlers',
|
||||
'groups',
|
||||
'error_handlers',
|
||||
'running',
|
||||
'__stop_event',
|
||||
'__exception_event',
|
||||
'__async_queue',
|
||||
'__async_threads',
|
||||
'bot',
|
||||
'__dict__',
|
||||
'__weakref__',
|
||||
)
|
||||
|
||||
__singleton_lock = Lock()
|
||||
__singleton_semaphore = BoundedSemaphore()
|
||||
__singleton = None
|
||||
|
@ -215,6 +241,17 @@ class Dispatcher:
|
|||
else:
|
||||
self._set_singleton(None)
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
# Mangled names don't automatically apply in __setattr__ (see
|
||||
# https://docs.python.org/3/tutorial/classes.html#private-variables), so we have to make
|
||||
# it mangled so they don't raise TelegramDeprecationWarning unnecessarily
|
||||
if key.startswith('__'):
|
||||
key = f"_{self.__class__.__name__}{key}"
|
||||
if issubclass(self.__class__, Dispatcher) and self.__class__ is not Dispatcher:
|
||||
object.__setattr__(self, key, value)
|
||||
return
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
@property
|
||||
def exception_event(self) -> Event: # skipcq: PY-D0003
|
||||
return self.__exception_event
|
||||
|
|
|
@ -23,6 +23,7 @@ import re
|
|||
import warnings
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from sys import version_info as py_ver
|
||||
from threading import Lock
|
||||
from typing import (
|
||||
Dict,
|
||||
|
@ -50,7 +51,7 @@ __all__ = [
|
|||
'XORFilter',
|
||||
]
|
||||
|
||||
from telegram.utils.deprecate import TelegramDeprecationWarning
|
||||
from telegram.utils.deprecate import TelegramDeprecationWarning, set_new_attribute_deprecated
|
||||
from telegram.utils.types import SLT
|
||||
|
||||
DataDict = Dict[str, list]
|
||||
|
@ -112,8 +113,17 @@ class BaseFilter(ABC):
|
|||
(depends on the handler).
|
||||
"""
|
||||
|
||||
_name = None
|
||||
data_filter = False
|
||||
if py_ver < (3, 7):
|
||||
__slots__ = ('_name', '_data_filter')
|
||||
else:
|
||||
__slots__ = ('_name', '_data_filter', '__dict__') # type: ignore[assignment]
|
||||
|
||||
def __new__(cls, *args: object, **kwargs: object) -> 'BaseFilter': # pylint: disable=W0613
|
||||
instance = super().__new__(cls)
|
||||
instance._name = None
|
||||
instance._data_filter = False
|
||||
|
||||
return instance
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, update: Update) -> Optional[Union[bool, DataDict]]:
|
||||
|
@ -131,13 +141,33 @@ class BaseFilter(ABC):
|
|||
def __invert__(self) -> 'BaseFilter':
|
||||
return InvertedFilter(self)
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
# Allow setting custom attributes w/o warning for user defined custom filters.
|
||||
# To differentiate between a custom and a PTB filter, we use this hacky but
|
||||
# simple way of checking the module name where the class is defined from.
|
||||
if (
|
||||
issubclass(self.__class__, (UpdateFilter, MessageFilter))
|
||||
and self.__class__.__module__ != __name__
|
||||
): # __name__ is telegram.ext.filters
|
||||
object.__setattr__(self, key, value)
|
||||
return
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
@property
|
||||
def data_filter(self) -> bool:
|
||||
return self._data_filter
|
||||
|
||||
@data_filter.setter
|
||||
def data_filter(self, value: bool) -> None:
|
||||
self._data_filter = value
|
||||
|
||||
@property
|
||||
def name(self) -> Optional[str]:
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, name: Optional[str]) -> None:
|
||||
self._name = name
|
||||
self._name = name # pylint: disable=E0237
|
||||
|
||||
def __repr__(self) -> str:
|
||||
# We do this here instead of in a __init__ so filter don't have to call __init__ or super()
|
||||
|
@ -146,7 +176,7 @@ class BaseFilter(ABC):
|
|||
return self.name
|
||||
|
||||
|
||||
class MessageFilter(BaseFilter, ABC):
|
||||
class MessageFilter(BaseFilter):
|
||||
"""Base class for all Message Filters. In contrast to :class:`UpdateFilter`, the object passed
|
||||
to :meth:`filter` is ``update.effective_message``.
|
||||
|
||||
|
@ -162,6 +192,8 @@ class MessageFilter(BaseFilter, ABC):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __call__(self, update: Update) -> Optional[Union[bool, DataDict]]:
|
||||
return self.filter(update.effective_message)
|
||||
|
||||
|
@ -178,7 +210,7 @@ class MessageFilter(BaseFilter, ABC):
|
|||
"""
|
||||
|
||||
|
||||
class UpdateFilter(BaseFilter, ABC):
|
||||
class UpdateFilter(BaseFilter):
|
||||
"""Base class for all Update Filters. In contrast to :class:`MessageFilter`, the object
|
||||
passed to :meth:`filter` is ``update``, which allows to create filters like
|
||||
:attr:`Filters.update.edited_message`.
|
||||
|
@ -195,6 +227,8 @@ class UpdateFilter(BaseFilter, ABC):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __call__(self, update: Update) -> Optional[Union[bool, DataDict]]:
|
||||
return self.filter(update)
|
||||
|
||||
|
@ -219,6 +253,8 @@ class InvertedFilter(UpdateFilter):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('f',)
|
||||
|
||||
def __init__(self, f: BaseFilter):
|
||||
self.f = f
|
||||
|
||||
|
@ -244,6 +280,8 @@ class MergedFilter(UpdateFilter):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('base_filter', 'and_filter', 'or_filter')
|
||||
|
||||
def __init__(
|
||||
self, base_filter: BaseFilter, and_filter: BaseFilter = None, or_filter: BaseFilter = None
|
||||
):
|
||||
|
@ -328,6 +366,8 @@ class XORFilter(UpdateFilter):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('base_filter', 'xor_filter', 'merged_filter')
|
||||
|
||||
def __init__(self, base_filter: BaseFilter, xor_filter: BaseFilter):
|
||||
self.base_filter = base_filter
|
||||
self.xor_filter = xor_filter
|
||||
|
@ -346,11 +386,15 @@ class XORFilter(UpdateFilter):
|
|||
|
||||
|
||||
class _DiceEmoji(MessageFilter):
|
||||
__slots__ = ('emoji',)
|
||||
|
||||
def __init__(self, emoji: str = None, name: str = None):
|
||||
self.name = f'Filters.dice.{name}' if name else 'Filters.dice'
|
||||
self.emoji = emoji
|
||||
|
||||
class _DiceValues(MessageFilter):
|
||||
__slots__ = ('values', 'emoji')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
values: SLT[int],
|
||||
|
@ -393,7 +437,13 @@ class Filters:
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('__dict__',)
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
class _All(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.all'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -403,9 +453,12 @@ class Filters:
|
|||
"""All Messages."""
|
||||
|
||||
class _Text(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.text'
|
||||
|
||||
class _TextStrings(MessageFilter):
|
||||
__slots__ = ('strings',)
|
||||
|
||||
def __init__(self, strings: Union[List[str], Tuple[str]]):
|
||||
self.strings = strings
|
||||
self.name = f'Filters.text({strings})'
|
||||
|
@ -454,9 +507,12 @@ class Filters:
|
|||
"""
|
||||
|
||||
class _Caption(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.caption'
|
||||
|
||||
class _CaptionStrings(MessageFilter):
|
||||
__slots__ = ('strings',)
|
||||
|
||||
def __init__(self, strings: Union[List[str], Tuple[str]]):
|
||||
self.strings = strings
|
||||
self.name = f'Filters.caption({strings})'
|
||||
|
@ -489,9 +545,12 @@ class Filters:
|
|||
"""
|
||||
|
||||
class _Command(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.command'
|
||||
|
||||
class _CommandOnlyStart(MessageFilter):
|
||||
__slots__ = ('only_start',)
|
||||
|
||||
def __init__(self, only_start: bool):
|
||||
self.only_start = only_start
|
||||
self.name = f'Filters.command({only_start})'
|
||||
|
@ -564,6 +623,7 @@ class Filters:
|
|||
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
|
||||
"""
|
||||
|
||||
__slots__ = ('pattern',)
|
||||
data_filter = True
|
||||
|
||||
def __init__(self, pattern: Union[str, Pattern]):
|
||||
|
@ -599,6 +659,7 @@ class Filters:
|
|||
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
|
||||
"""
|
||||
|
||||
__slots__ = ('pattern',)
|
||||
data_filter = True
|
||||
|
||||
def __init__(self, pattern: Union[str, Pattern]):
|
||||
|
@ -617,6 +678,7 @@ class Filters:
|
|||
return {}
|
||||
|
||||
class _Reply(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.reply'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -626,6 +688,7 @@ class Filters:
|
|||
"""Messages that are a reply to another message."""
|
||||
|
||||
class _Audio(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.audio'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -635,6 +698,7 @@ class Filters:
|
|||
"""Messages that contain :class:`telegram.Audio`."""
|
||||
|
||||
class _Document(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.document'
|
||||
|
||||
class category(MessageFilter):
|
||||
|
@ -651,7 +715,14 @@ class Filters:
|
|||
of audio sent as file, for example 'audio/mpeg' or 'audio/x-wav'.
|
||||
"""
|
||||
|
||||
__slots__ = ('_category',)
|
||||
|
||||
def __init__(self, category: Optional[str]):
|
||||
"""Initialize the category you want to filter
|
||||
|
||||
Args:
|
||||
category (str, optional): category of the media you want to filter
|
||||
"""
|
||||
self._category = category
|
||||
self.name = f"Filters.document.category('{self._category}')"
|
||||
|
||||
|
@ -680,6 +751,8 @@ class Filters:
|
|||
``Filters.document.mime_type('audio/mpeg')`` filters all audio in mp3 format.
|
||||
"""
|
||||
|
||||
__slots__ = ('mimetype',)
|
||||
|
||||
def __init__(self, mimetype: Optional[str]):
|
||||
self.mimetype = mimetype
|
||||
self.name = f"Filters.document.mime_type('{self.mimetype}')"
|
||||
|
@ -732,6 +805,8 @@ class Filters:
|
|||
filters files without a dot in the filename.
|
||||
"""
|
||||
|
||||
__slots__ = ('_file_extension', 'is_case_sensitive')
|
||||
|
||||
def __init__(self, file_extension: Optional[str], case_sensitive: bool = False):
|
||||
"""Initialize the extension you want to filter.
|
||||
|
||||
|
@ -850,6 +925,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""
|
||||
|
||||
class _Animation(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.animation'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -859,6 +935,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Animation`."""
|
||||
|
||||
class _Photo(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.photo'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -868,6 +945,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.PhotoSize`."""
|
||||
|
||||
class _Sticker(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.sticker'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -877,6 +955,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Sticker`."""
|
||||
|
||||
class _Video(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.video'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -886,6 +965,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Video`."""
|
||||
|
||||
class _Voice(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.voice'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -895,6 +975,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Voice`."""
|
||||
|
||||
class _VideoNote(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.video_note'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -904,6 +985,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.VideoNote`."""
|
||||
|
||||
class _Contact(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.contact'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -913,6 +995,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Contact`."""
|
||||
|
||||
class _Location(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.location'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -922,6 +1005,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Location`."""
|
||||
|
||||
class _Venue(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.venue'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -939,7 +1023,10 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
class _NewChatMembers(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.new_chat_members'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -949,6 +1036,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.new_chat_members`."""
|
||||
|
||||
class _LeftChatMember(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.left_chat_member'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -958,6 +1046,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.left_chat_member`."""
|
||||
|
||||
class _NewChatTitle(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.new_chat_title'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -967,6 +1056,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.new_chat_title`."""
|
||||
|
||||
class _NewChatPhoto(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.new_chat_photo'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -976,6 +1066,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.new_chat_photo`."""
|
||||
|
||||
class _DeleteChatPhoto(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.delete_chat_photo'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -985,6 +1076,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.delete_chat_photo`."""
|
||||
|
||||
class _ChatCreated(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.chat_created'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1000,6 +1092,7 @@ officedocument.wordprocessingml.document")``.
|
|||
:attr: `telegram.Message.channel_chat_created`."""
|
||||
|
||||
class _MessageAutoDeleteTimerChanged(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'MessageAutoDeleteTimerChanged'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1009,6 +1102,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`message_auto_delete_timer_changed`"""
|
||||
|
||||
class _Migrate(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.migrate'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1019,6 +1113,7 @@ officedocument.wordprocessingml.document")``.
|
|||
:attr:`telegram.Message.migrate_to_chat_id`."""
|
||||
|
||||
class _PinnedMessage(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.pinned_message'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1028,6 +1123,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.pinned_message`."""
|
||||
|
||||
class _ConnectedWebsite(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.connected_website'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1037,6 +1133,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.connected_website`."""
|
||||
|
||||
class _ProximityAlertTriggered(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.proximity_alert_triggered'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1046,6 +1143,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.proximity_alert_triggered`."""
|
||||
|
||||
class _VoiceChatScheduled(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.voice_chat_scheduled'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1055,6 +1153,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.voice_chat_scheduled`."""
|
||||
|
||||
class _VoiceChatStarted(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.voice_chat_started'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1064,6 +1163,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.voice_chat_started`."""
|
||||
|
||||
class _VoiceChatEnded(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.voice_chat_ended'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1073,6 +1173,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :attr:`telegram.Message.voice_chat_ended`."""
|
||||
|
||||
class _VoiceChatParticipantsInvited(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.status_update.voice_chat_participants_invited'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1157,6 +1258,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""
|
||||
|
||||
class _Forwarded(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.forwarded'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1166,6 +1268,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that are forwarded."""
|
||||
|
||||
class _Game(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.game'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1188,6 +1291,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('entity_type',)
|
||||
|
||||
def __init__(self, entity_type: str):
|
||||
self.entity_type = entity_type
|
||||
self.name = f'Filters.entity({self.entity_type})'
|
||||
|
@ -1210,6 +1315,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('entity_type',)
|
||||
|
||||
def __init__(self, entity_type: str):
|
||||
self.entity_type = entity_type
|
||||
self.name = f'Filters.caption_entity({self.entity_type})'
|
||||
|
@ -1219,6 +1326,7 @@ officedocument.wordprocessingml.document")``.
|
|||
return any(entity.type == self.entity_type for entity in message.caption_entities)
|
||||
|
||||
class _Private(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.private'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1239,6 +1347,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""
|
||||
|
||||
class _Group(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.group'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1259,9 +1368,11 @@ officedocument.wordprocessingml.document")``.
|
|||
"""
|
||||
|
||||
class _ChatType(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.chat_type'
|
||||
|
||||
class _Channel(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.chat_type.channel'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1270,6 +1381,7 @@ officedocument.wordprocessingml.document")``.
|
|||
channel = _Channel()
|
||||
|
||||
class _Group(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.chat_type.group'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1278,6 +1390,7 @@ officedocument.wordprocessingml.document")``.
|
|||
group = _Group()
|
||||
|
||||
class _SuperGroup(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.chat_type.supergroup'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1286,6 +1399,7 @@ officedocument.wordprocessingml.document")``.
|
|||
supergroup = _SuperGroup()
|
||||
|
||||
class _Groups(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.chat_type.groups'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1294,6 +1408,7 @@ officedocument.wordprocessingml.document")``.
|
|||
groups = _Groups()
|
||||
|
||||
class _Private(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.chat_type.private'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1321,6 +1436,15 @@ officedocument.wordprocessingml.document")``.
|
|||
"""
|
||||
|
||||
class _ChatUserBaseFilter(MessageFilter, ABC):
|
||||
__slots__ = (
|
||||
'chat_id_name',
|
||||
'username_name',
|
||||
'allow_empty',
|
||||
'__lock',
|
||||
'_chat_ids',
|
||||
'_usernames',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
chat_id: SLT[int] = None,
|
||||
|
@ -1497,6 +1621,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
user_id: SLT[int] = None,
|
||||
|
@ -1596,6 +1722,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
bot_id: SLT[int] = None,
|
||||
|
@ -1695,6 +1823,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def get_chat_or_user(self, message: Message) -> Optional[Chat]:
|
||||
return message.chat
|
||||
|
||||
|
@ -1786,6 +1916,8 @@ officedocument.wordprocessingml.document")``.
|
|||
is specified in :attr:`chat_ids` and :attr:`usernames`.
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def get_chat_or_user(self, message: Message) -> Union[User, Chat, None]:
|
||||
return message.forward_from or message.forward_from_chat
|
||||
|
||||
|
@ -1891,6 +2023,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def get_chat_or_user(self, message: Message) -> Optional[Chat]:
|
||||
return message.sender_chat
|
||||
|
||||
|
@ -1937,12 +2071,16 @@ officedocument.wordprocessingml.document")``.
|
|||
return super().remove_chat_ids(chat_id)
|
||||
|
||||
class _SuperGroup(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
if message.sender_chat:
|
||||
return message.sender_chat.type == Chat.SUPERGROUP
|
||||
return False
|
||||
|
||||
class _Channel(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
if message.sender_chat:
|
||||
return message.sender_chat.type == Chat.CHANNEL
|
||||
|
@ -1952,6 +2090,7 @@ officedocument.wordprocessingml.document")``.
|
|||
channel = _Channel()
|
||||
|
||||
class _Invoice(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.invoice'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1961,6 +2100,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain :class:`telegram.Invoice`."""
|
||||
|
||||
class _SuccessfulPayment(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.successful_payment'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1970,6 +2110,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that confirm a :class:`telegram.SuccessfulPayment`."""
|
||||
|
||||
class _PassportData(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.passport_data'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1979,6 +2120,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain a :class:`telegram.PassportData`"""
|
||||
|
||||
class _Poll(MessageFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.poll'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -1988,6 +2130,7 @@ officedocument.wordprocessingml.document")``.
|
|||
"""Messages that contain a :class:`telegram.Poll`."""
|
||||
|
||||
class _Dice(_DiceEmoji):
|
||||
__slots__ = ()
|
||||
dice = _DiceEmoji('🎲', 'dice')
|
||||
darts = _DiceEmoji('🎯', 'darts')
|
||||
basketball = _DiceEmoji('🏀', 'basketball')
|
||||
|
@ -2051,6 +2194,8 @@ officedocument.wordprocessingml.document")``.
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('lang',)
|
||||
|
||||
def __init__(self, lang: SLT[str]):
|
||||
if isinstance(lang, str):
|
||||
lang = cast(str, lang)
|
||||
|
@ -2068,6 +2213,8 @@ officedocument.wordprocessingml.document")``.
|
|||
)
|
||||
|
||||
class _Attachment(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
name = 'Filters.attachment'
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
|
@ -2080,9 +2227,11 @@ officedocument.wordprocessingml.document")``.
|
|||
.. versionadded:: 13.6"""
|
||||
|
||||
class _UpdateType(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update'
|
||||
|
||||
class _Message(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update.message'
|
||||
|
||||
def filter(self, update: Update) -> bool:
|
||||
|
@ -2091,6 +2240,7 @@ officedocument.wordprocessingml.document")``.
|
|||
message = _Message()
|
||||
|
||||
class _EditedMessage(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update.edited_message'
|
||||
|
||||
def filter(self, update: Update) -> bool:
|
||||
|
@ -2099,6 +2249,7 @@ officedocument.wordprocessingml.document")``.
|
|||
edited_message = _EditedMessage()
|
||||
|
||||
class _Messages(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update.messages'
|
||||
|
||||
def filter(self, update: Update) -> bool:
|
||||
|
@ -2107,6 +2258,7 @@ officedocument.wordprocessingml.document")``.
|
|||
messages = _Messages()
|
||||
|
||||
class _ChannelPost(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update.channel_post'
|
||||
|
||||
def filter(self, update: Update) -> bool:
|
||||
|
@ -2115,6 +2267,7 @@ officedocument.wordprocessingml.document")``.
|
|||
channel_post = _ChannelPost()
|
||||
|
||||
class _EditedChannelPost(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update.edited_channel_post'
|
||||
|
||||
def filter(self, update: Update) -> bool:
|
||||
|
@ -2123,6 +2276,7 @@ officedocument.wordprocessingml.document")``.
|
|||
edited_channel_post = _EditedChannelPost()
|
||||
|
||||
class _ChannelPosts(UpdateFilter):
|
||||
__slots__ = ()
|
||||
name = 'Filters.update.channel_posts'
|
||||
|
||||
def filter(self, update: Update) -> bool:
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
# 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 base class for handlers as used by the Dispatcher."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar, Union, Generic
|
||||
from sys import version_info as py_ver
|
||||
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
from telegram import Update
|
||||
from telegram.ext.utils.promise import Promise
|
||||
|
@ -90,6 +92,27 @@ class Handler(Generic[UT], ABC):
|
|||
|
||||
"""
|
||||
|
||||
# Apparently Py 3.7 and below have '__dict__' in ABC
|
||||
if py_ver < (3, 7):
|
||||
__slots__ = (
|
||||
'callback',
|
||||
'pass_update_queue',
|
||||
'pass_job_queue',
|
||||
'pass_user_data',
|
||||
'pass_chat_data',
|
||||
'run_async',
|
||||
)
|
||||
else:
|
||||
__slots__ = (
|
||||
'callback', # type: ignore[assignment]
|
||||
'pass_update_queue',
|
||||
'pass_job_queue',
|
||||
'pass_user_data',
|
||||
'pass_chat_data',
|
||||
'run_async',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
callback: Callable[[UT, 'CallbackContext'], RT],
|
||||
|
@ -106,6 +129,17 @@ class Handler(Generic[UT], ABC):
|
|||
self.pass_chat_data = pass_chat_data
|
||||
self.run_async = run_async
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
# See comment on BaseFilter to know why this was done.
|
||||
if key.startswith('__'):
|
||||
key = f"_{self.__class__.__name__}{key}"
|
||||
if issubclass(self.__class__, Handler) and not self.__class__.__module__.startswith(
|
||||
'telegram.ext.'
|
||||
):
|
||||
object.__setattr__(self, key, value)
|
||||
return
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
@abstractmethod
|
||||
def check_update(self, update: object) -> Optional[Union[bool, object]]:
|
||||
"""
|
||||
|
|
|
@ -129,6 +129,8 @@ class InlineQueryHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('pattern', 'chat_types', 'pass_groups', 'pass_groupdict')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
callback: Callable[[Update, 'CallbackContext'], RT],
|
||||
|
|
|
@ -31,6 +31,7 @@ from apscheduler.job import Job as APSJob
|
|||
|
||||
from telegram.ext.callbackcontext import CallbackContext
|
||||
from telegram.utils.types import JSONDict
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
|
@ -49,6 +50,8 @@ class JobQueue:
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('_dispatcher', 'logger', 'scheduler', '__dict__')
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._dispatcher: 'Dispatcher' = None # type: ignore[assignment]
|
||||
self.logger = logging.getLogger(self.__class__.__name__)
|
||||
|
@ -64,6 +67,9 @@ class JobQueue:
|
|||
logging.getLogger('apscheduler.executors.default').addFilter(aps_log_filter)
|
||||
self.scheduler.add_listener(self._dispatch_error, EVENT_JOB_ERROR)
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
def _build_args(self, job: 'Job') -> List[Union[CallbackContext, 'Bot', 'Job']]:
|
||||
if self._dispatcher.use_context:
|
||||
return [CallbackContext.from_job(job, self._dispatcher)]
|
||||
|
@ -542,6 +548,17 @@ class Job:
|
|||
job (:class:`apscheduler.job.Job`): Optional. The APS Job this job is a wrapper for.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'callback',
|
||||
'context',
|
||||
'name',
|
||||
'job_queue',
|
||||
'_removed',
|
||||
'_enabled',
|
||||
'job',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
callback: Callable[['CallbackContext'], None],
|
||||
|
@ -561,6 +578,9 @@ class Job:
|
|||
|
||||
self.job = cast(APSJob, job) # skipcq: PTC-W0052
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
def run(self, dispatcher: 'Dispatcher') -> None:
|
||||
"""Executes the callback function independently of the jobs schedule."""
|
||||
try:
|
||||
|
|
|
@ -120,6 +120,8 @@ class MessageHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('filters',)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
filters: BaseFilter,
|
||||
|
|
|
@ -40,6 +40,8 @@ curtime = time.perf_counter
|
|||
class DelayQueueError(RuntimeError):
|
||||
"""Indicates processing errors."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class DelayQueue(threading.Thread):
|
||||
"""
|
||||
|
|
|
@ -73,6 +73,16 @@ class PicklePersistence(BasePersistence):
|
|||
Default is :obj:`False`.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'filename',
|
||||
'single_file',
|
||||
'on_flush',
|
||||
'user_data',
|
||||
'chat_data',
|
||||
'bot_data',
|
||||
'conversations',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
filename: str,
|
||||
|
|
|
@ -82,6 +82,8 @@ class PollAnswerHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def check_update(self, update: object) -> bool:
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ class PollHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def check_update(self, update: object) -> bool:
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ class PreCheckoutQueryHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def check_update(self, update: object) -> bool:
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
|
|
|
@ -108,6 +108,8 @@ class RegexHandler(MessageHandler):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('pass_groups', 'pass_groupdict')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pattern: Union[str, Pattern],
|
||||
|
|
|
@ -81,6 +81,8 @@ class ShippingQueryHandler(Handler[Update]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def check_update(self, update: object) -> bool:
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ class StringCommandHandler(Handler[str]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('command', 'pass_args')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
command: str,
|
||||
|
|
|
@ -91,6 +91,8 @@ class StringRegexHandler(Handler[str]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('pass_groups', 'pass_groupdict', 'pattern')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pattern: Union[str, Pattern],
|
||||
|
|
|
@ -75,6 +75,8 @@ class TypeHandler(Handler[UT]):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('type', 'strict')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
type: Type[UT], # pylint: disable=W0622
|
||||
|
@ -90,8 +92,8 @@ class TypeHandler(Handler[UT]):
|
|||
pass_job_queue=pass_job_queue,
|
||||
run_async=run_async,
|
||||
)
|
||||
self.type = type
|
||||
self.strict = strict
|
||||
self.type = type # pylint: disable=E0237
|
||||
self.strict = strict # pylint: disable=E0237
|
||||
|
||||
def check_update(self, update: object) -> bool:
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
|
|
@ -30,7 +30,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Un
|
|||
from telegram import Bot, TelegramError
|
||||
from telegram.error import InvalidToken, RetryAfter, TimedOut, Unauthorized
|
||||
from telegram.ext import Dispatcher, JobQueue
|
||||
from telegram.utils.deprecate import TelegramDeprecationWarning
|
||||
from telegram.utils.deprecate import TelegramDeprecationWarning, set_new_attribute_deprecated
|
||||
from telegram.utils.helpers import get_signal_name
|
||||
from telegram.utils.request import Request
|
||||
from telegram.ext.utils.webhookhandler import WebhookAppClass, WebhookServer
|
||||
|
@ -105,7 +105,24 @@ class Updater:
|
|||
|
||||
"""
|
||||
|
||||
_request = None
|
||||
__slots__ = (
|
||||
'persistence',
|
||||
'dispatcher',
|
||||
'user_sig_handler',
|
||||
'bot',
|
||||
'logger',
|
||||
'update_queue',
|
||||
'job_queue',
|
||||
'__exception_event',
|
||||
'last_update_id',
|
||||
'running',
|
||||
'_request',
|
||||
'is_idle',
|
||||
'httpd',
|
||||
'__lock',
|
||||
'__threads',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -150,6 +167,7 @@ class Updater:
|
|||
raise ValueError('`dispatcher` and `use_context` are mutually exclusive')
|
||||
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self._request = None
|
||||
|
||||
if dispatcher is None:
|
||||
con_pool_size = workers + 4
|
||||
|
@ -219,6 +237,14 @@ class Updater:
|
|||
self.__lock = Lock()
|
||||
self.__threads: List[Thread] = []
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
if key.startswith('__'):
|
||||
key = f"_{self.__class__.__name__}{key}"
|
||||
if issubclass(self.__class__, Updater) and self.__class__ is not Updater:
|
||||
object.__setattr__(self, key, value)
|
||||
return
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
def _init_thread(self, target: Callable, name: str, *args: object, **kwargs: object) -> None:
|
||||
thr = Thread(
|
||||
target=self._thread_wrapper,
|
||||
|
|
|
@ -22,6 +22,7 @@ import logging
|
|||
from threading import Event
|
||||
from typing import Callable, List, Optional, Tuple, TypeVar, Union
|
||||
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
from telegram.utils.types import JSONDict
|
||||
|
||||
RT = TypeVar('RT')
|
||||
|
@ -54,6 +55,19 @@ class Promise:
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'pooled_function',
|
||||
'args',
|
||||
'kwargs',
|
||||
'update',
|
||||
'error_handling',
|
||||
'done',
|
||||
'_done_callback',
|
||||
'_result',
|
||||
'_exception',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
# TODO: Remove error_handling parameter once we drop the @run_async decorator
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -73,6 +87,9 @@ class Promise:
|
|||
self._result: Optional[RT] = None
|
||||
self._exception: Optional[Exception] = None
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
def run(self) -> None:
|
||||
"""Calls the :attr:`pooled_function` callable."""
|
||||
try:
|
||||
|
|
|
@ -30,6 +30,7 @@ from tornado.httpserver import HTTPServer
|
|||
from tornado.ioloop import IOLoop
|
||||
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
from telegram.utils.types import JSONDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -42,6 +43,18 @@ except ImportError:
|
|||
|
||||
|
||||
class WebhookServer:
|
||||
__slots__ = (
|
||||
'http_server',
|
||||
'listen',
|
||||
'port',
|
||||
'loop',
|
||||
'logger',
|
||||
'is_running',
|
||||
'server_lock',
|
||||
'shutdown_lock',
|
||||
'__dict__',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self, listen: str, port: int, webhook_app: 'WebhookAppClass', ssl_ctx: SSLContext
|
||||
):
|
||||
|
@ -54,6 +67,9 @@ class WebhookServer:
|
|||
self.server_lock = Lock()
|
||||
self.shutdown_lock = Lock()
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
def serve_forever(self, ready: Event = None) -> None:
|
||||
with self.server_lock:
|
||||
IOLoop().make_current()
|
||||
|
|
|
@ -65,6 +65,20 @@ class Animation(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'width',
|
||||
'file_id',
|
||||
'file_size',
|
||||
'file_name',
|
||||
'thumb',
|
||||
'duration',
|
||||
'mime_type',
|
||||
'height',
|
||||
'file_unique_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -69,6 +69,20 @@ class Audio(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'file_id',
|
||||
'bot',
|
||||
'file_size',
|
||||
'file_name',
|
||||
'thumb',
|
||||
'title',
|
||||
'duration',
|
||||
'performer',
|
||||
'mime_type',
|
||||
'file_unique_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -65,6 +65,15 @@ class ChatPhoto(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'big_file_unique_id',
|
||||
'bot',
|
||||
'small_file_id',
|
||||
'small_file_unique_id',
|
||||
'big_file_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
small_file_id: str,
|
||||
|
|
|
@ -46,6 +46,8 @@ class Contact(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('vcard', 'user_id', 'first_name', 'last_name', 'phone_number', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
phone_number: str,
|
||||
|
|
|
@ -60,6 +60,17 @@ class Document(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'file_id',
|
||||
'file_size',
|
||||
'file_name',
|
||||
'thumb',
|
||||
'mime_type',
|
||||
'file_unique_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
_id_keys = ('file_id',)
|
||||
|
||||
def __init__(
|
||||
|
|
|
@ -67,6 +67,16 @@ class File(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'file_id',
|
||||
'file_size',
|
||||
'file_unique_id',
|
||||
'file_path',
|
||||
'_credentials',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -26,6 +26,8 @@ import os
|
|||
from typing import IO, Optional, Tuple, Union
|
||||
from uuid import uuid4
|
||||
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
DEFAULT_MIME_TYPE = 'application/octet-stream'
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -50,6 +52,8 @@ class InputFile:
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('filename', 'attach', 'input_file_content', 'mimetype', '__dict__')
|
||||
|
||||
def __init__(self, obj: Union[IO, bytes], filename: str = None, attach: bool = None):
|
||||
self.filename = None
|
||||
if isinstance(obj, bytes):
|
||||
|
@ -74,6 +78,9 @@ class InputFile:
|
|||
if not self.filename:
|
||||
self.filename = self.mimetype.replace('/', '.')
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
||||
@property
|
||||
def field_tuple(self) -> Tuple[str, bytes, str]: # skipcq: PY-D0003
|
||||
return self.filename, self.input_file_content, self.mimetype
|
||||
|
|
|
@ -43,6 +43,7 @@ class InputMedia(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...], None] = None
|
||||
|
||||
def to_dict(self) -> JSONDict:
|
||||
|
@ -113,6 +114,18 @@ class InputMediaAnimation(InputMedia):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'caption_entities',
|
||||
'width',
|
||||
'media',
|
||||
'thumb',
|
||||
'caption',
|
||||
'duration',
|
||||
'parse_mode',
|
||||
'height',
|
||||
'type',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Animation],
|
||||
|
@ -185,6 +198,8 @@ class InputMediaPhoto(InputMedia):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('caption_entities', 'media', 'caption', 'parse_mode', 'type')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, PhotoSize],
|
||||
|
@ -265,6 +280,19 @@ class InputMediaVideo(InputMedia):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'caption_entities',
|
||||
'width',
|
||||
'media',
|
||||
'thumb',
|
||||
'supports_streaming',
|
||||
'caption',
|
||||
'duration',
|
||||
'parse_mode',
|
||||
'height',
|
||||
'type',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Video],
|
||||
|
@ -364,6 +392,18 @@ class InputMediaAudio(InputMedia):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'caption_entities',
|
||||
'media',
|
||||
'thumb',
|
||||
'caption',
|
||||
'title',
|
||||
'duration',
|
||||
'type',
|
||||
'parse_mode',
|
||||
'performer',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Audio],
|
||||
|
@ -452,6 +492,16 @@ class InputMediaDocument(InputMedia):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'caption_entities',
|
||||
'media',
|
||||
'thumb',
|
||||
'caption',
|
||||
'parse_mode',
|
||||
'type',
|
||||
'disable_content_type_detection',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Document],
|
||||
|
|
|
@ -56,6 +56,16 @@ class Location(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'longitude',
|
||||
'horizontal_accuracy',
|
||||
'proximity_alert_radius',
|
||||
'live_period',
|
||||
'latitude',
|
||||
'heading',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
longitude: float,
|
||||
|
|
|
@ -58,6 +58,8 @@ class PhotoSize(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('bot', 'width', 'file_id', 'file_size', 'height', 'file_unique_id', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -73,6 +73,21 @@ class Sticker(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'width',
|
||||
'file_id',
|
||||
'is_animated',
|
||||
'file_size',
|
||||
'thumb',
|
||||
'set_name',
|
||||
'mask_position',
|
||||
'height',
|
||||
'file_unique_id',
|
||||
'emoji',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
@ -160,6 +175,16 @@ class StickerSet(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'is_animated',
|
||||
'contains_masks',
|
||||
'thumb',
|
||||
'title',
|
||||
'stickers',
|
||||
'name',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
|
@ -233,6 +258,8 @@ class MaskPosition(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('point', 'scale', 'x_shift', 'y_shift', '_id_attrs')
|
||||
|
||||
FOREHEAD: ClassVar[str] = constants.STICKER_FOREHEAD
|
||||
""":const:`telegram.constants.STICKER_FOREHEAD`"""
|
||||
EYES: ClassVar[str] = constants.STICKER_EYES
|
||||
|
|
|
@ -60,6 +60,17 @@ class Venue(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'google_place_type',
|
||||
'location',
|
||||
'title',
|
||||
'address',
|
||||
'foursquare_type',
|
||||
'foursquare_id',
|
||||
'google_place_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
location: Location,
|
||||
|
|
|
@ -66,6 +66,20 @@ class Video(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'width',
|
||||
'file_id',
|
||||
'file_size',
|
||||
'file_name',
|
||||
'thumb',
|
||||
'duration',
|
||||
'mime_type',
|
||||
'height',
|
||||
'file_unique_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -61,6 +61,17 @@ class VideoNote(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'length',
|
||||
'file_id',
|
||||
'file_size',
|
||||
'thumb',
|
||||
'duration',
|
||||
'file_unique_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -58,6 +58,16 @@ class Voice(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'file_id',
|
||||
'file_size',
|
||||
'duration',
|
||||
'mime_type',
|
||||
'file_unique_id',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_id: str,
|
||||
|
|
|
@ -50,6 +50,8 @@ class ForceReply(ReplyMarkup):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('selective', 'force_reply', '_id_attrs')
|
||||
|
||||
def __init__(self, force_reply: bool = True, selective: bool = False, **_kwargs: Any):
|
||||
# Required
|
||||
self.force_reply = bool(force_reply)
|
||||
|
|
|
@ -23,3 +23,5 @@ from telegram import TelegramObject
|
|||
|
||||
class CallbackGame(TelegramObject):
|
||||
"""A placeholder, currently holds no information. Use BotFather to set up your game."""
|
||||
|
||||
__slots__ = ()
|
||||
|
|
|
@ -67,6 +67,16 @@ class Game(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'title',
|
||||
'photo',
|
||||
'description',
|
||||
'text_entities',
|
||||
'text',
|
||||
'animation',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
|
|
|
@ -45,6 +45,8 @@ class GameHighScore(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('position', 'user', 'score', '_id_attrs')
|
||||
|
||||
def __init__(self, position: int, user: User, score: int):
|
||||
self.position = position
|
||||
self.user = user
|
||||
|
|
|
@ -83,6 +83,18 @@ class InlineKeyboardButton(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'callback_game',
|
||||
'url',
|
||||
'switch_inline_query_current_chat',
|
||||
'callback_data',
|
||||
'pay',
|
||||
'switch_inline_query',
|
||||
'text',
|
||||
'_id_attrs',
|
||||
'login_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
text: str,
|
||||
|
|
|
@ -45,6 +45,8 @@ class InlineKeyboardMarkup(ReplyMarkup):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('inline_keyboard', '_id_attrs')
|
||||
|
||||
def __init__(self, inline_keyboard: List[List[InlineKeyboardButton]], **_kwargs: Any):
|
||||
# Required
|
||||
self.inline_keyboard = inline_keyboard
|
||||
|
|
|
@ -71,6 +71,8 @@ class InlineQuery(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('bot', 'location', 'chat_type', 'id', 'offset', 'from_user', 'query', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -46,6 +46,8 @@ class InlineQueryResult(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('type', 'id', '_id_attrs')
|
||||
|
||||
def __init__(self, type: str, id: str, **_kwargs: Any):
|
||||
# Required
|
||||
self.type = str(type)
|
||||
|
|
|
@ -63,6 +63,18 @@ class InlineQueryResultArticle(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'thumb_width',
|
||||
'thumb_height',
|
||||
'hide_url',
|
||||
'url',
|
||||
'title',
|
||||
'description',
|
||||
'input_message_content',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -74,6 +74,18 @@ class InlineQueryResultAudio(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'title',
|
||||
'parse_mode',
|
||||
'audio_url',
|
||||
'performer',
|
||||
'input_message_content',
|
||||
'audio_duration',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -68,6 +68,15 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'parse_mode',
|
||||
'audio_file_id',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -75,6 +75,17 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'document_file_id',
|
||||
'caption',
|
||||
'title',
|
||||
'description',
|
||||
'parse_mode',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -73,6 +73,16 @@ class InlineQueryResultCachedGif(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'title',
|
||||
'input_message_content',
|
||||
'parse_mode',
|
||||
'gif_file_id',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -73,6 +73,16 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'mpeg4_file_id',
|
||||
'caption',
|
||||
'title',
|
||||
'parse_mode',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -76,6 +76,17 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'title',
|
||||
'description',
|
||||
'parse_mode',
|
||||
'photo_file_id',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -52,6 +52,8 @@ class InlineQueryResultCachedSticker(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('reply_markup', 'input_message_content', 'sticker_file_id')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -75,6 +75,17 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'title',
|
||||
'description',
|
||||
'parse_mode',
|
||||
'input_message_content',
|
||||
'video_file_id',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -70,6 +70,16 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'title',
|
||||
'parse_mode',
|
||||
'voice_file_id',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -66,6 +66,18 @@ class InlineQueryResultContact(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'thumb_width',
|
||||
'thumb_height',
|
||||
'vcard',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'phone_number',
|
||||
'input_message_content',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -85,6 +85,21 @@ class InlineQueryResultDocument(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'document_url',
|
||||
'thumb_width',
|
||||
'thumb_height',
|
||||
'caption',
|
||||
'title',
|
||||
'description',
|
||||
'parse_mode',
|
||||
'mime_type',
|
||||
'thumb_url',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -45,6 +45,8 @@ class InlineQueryResultGame(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('reply_markup', 'game_short_name')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -86,6 +86,21 @@ class InlineQueryResultGif(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'gif_height',
|
||||
'thumb_mime_type',
|
||||
'caption_entities',
|
||||
'gif_width',
|
||||
'title',
|
||||
'caption',
|
||||
'parse_mode',
|
||||
'gif_duration',
|
||||
'input_message_content',
|
||||
'gif_url',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -79,6 +79,21 @@ class InlineQueryResultLocation(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'longitude',
|
||||
'reply_markup',
|
||||
'thumb_width',
|
||||
'thumb_height',
|
||||
'heading',
|
||||
'title',
|
||||
'live_period',
|
||||
'proximity_alert_radius',
|
||||
'input_message_content',
|
||||
'latitude',
|
||||
'horizontal_accuracy',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -85,6 +85,21 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'thumb_mime_type',
|
||||
'caption_entities',
|
||||
'mpeg4_duration',
|
||||
'mpeg4_width',
|
||||
'title',
|
||||
'caption',
|
||||
'parse_mode',
|
||||
'input_message_content',
|
||||
'mpeg4_url',
|
||||
'mpeg4_height',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -82,6 +82,20 @@ class InlineQueryResultPhoto(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'photo_url',
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'photo_width',
|
||||
'caption',
|
||||
'title',
|
||||
'description',
|
||||
'parse_mode',
|
||||
'input_message_content',
|
||||
'photo_height',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -79,6 +79,22 @@ class InlineQueryResultVenue(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'longitude',
|
||||
'reply_markup',
|
||||
'google_place_type',
|
||||
'thumb_width',
|
||||
'thumb_height',
|
||||
'title',
|
||||
'address',
|
||||
'foursquare_id',
|
||||
'foursquare_type',
|
||||
'google_place_id',
|
||||
'input_message_content',
|
||||
'latitude',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -92,6 +92,22 @@ class InlineQueryResultVideo(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'video_url',
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'caption',
|
||||
'title',
|
||||
'description',
|
||||
'video_duration',
|
||||
'parse_mode',
|
||||
'mime_type',
|
||||
'input_message_content',
|
||||
'video_height',
|
||||
'video_width',
|
||||
'thumb_url',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -73,6 +73,17 @@ class InlineQueryResultVoice(InlineQueryResult):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'caption_entities',
|
||||
'voice_duration',
|
||||
'caption',
|
||||
'title',
|
||||
'voice_url',
|
||||
'parse_mode',
|
||||
'input_message_content',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str, # pylint: disable=W0622
|
||||
|
|
|
@ -46,6 +46,8 @@ class InputContactMessageContent(InputMessageContent):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('vcard', 'first_name', 'last_name', 'phone_number', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
phone_number: str,
|
||||
|
|
|
@ -123,6 +123,30 @@ class InputInvoiceMessageContent(InputMessageContent):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'title',
|
||||
'description',
|
||||
'payload',
|
||||
'provider_token',
|
||||
'currency',
|
||||
'prices',
|
||||
'max_tip_amount',
|
||||
'suggested_tip_amounts',
|
||||
'provider_data',
|
||||
'photo_url',
|
||||
'photo_size',
|
||||
'photo_width',
|
||||
'photo_height',
|
||||
'need_name',
|
||||
'need_phone_number',
|
||||
'need_email',
|
||||
'need_shipping_address',
|
||||
'send_phone_number_to_provider',
|
||||
'send_email_to_provider',
|
||||
'is_flexible',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
|
|
|
@ -59,6 +59,8 @@ class InputLocationMessageContent(InputMessageContent):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('longitude', 'horizontal_accuracy', 'proximity_alert_radius', 'live_period',
|
||||
'latitude', 'heading', '_id_attrs')
|
||||
# fmt: on
|
||||
|
||||
def __init__(
|
||||
|
|
|
@ -30,3 +30,5 @@ class InputMessageContent(TelegramObject):
|
|||
:class:`telegram.InputVenueMessageContent` for more details.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
|
|
@ -59,6 +59,8 @@ class InputTextMessageContent(InputMessageContent):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('disable_web_page_preview', 'parse_mode', 'entities', 'message_text', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message_text: str,
|
||||
|
|
|
@ -60,6 +60,18 @@ class InputVenueMessageContent(InputMessageContent):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'longitude',
|
||||
'google_place_type',
|
||||
'title',
|
||||
'address',
|
||||
'foursquare_id',
|
||||
'foursquare_type',
|
||||
'google_place_id',
|
||||
'latitude',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
latitude: float,
|
||||
|
|
|
@ -58,6 +58,8 @@ class KeyboardButton(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('request_location', 'request_contact', 'request_poll', 'text', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
text: str,
|
||||
|
|
|
@ -37,6 +37,8 @@ class KeyboardButtonPollType(TelegramObject):
|
|||
create a poll of any type.
|
||||
"""
|
||||
|
||||
__slots__ = ('type', '_id_attrs')
|
||||
|
||||
def __init__(self, type: str = None, **_kwargs: Any): # pylint: disable=W0622
|
||||
self.type = type
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ class LoginUrl(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('bot_username', 'request_write_access', 'url', 'forward_text', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
url: str,
|
||||
|
|
|
@ -77,8 +77,6 @@ if TYPE_CHECKING:
|
|||
LabeledPrice,
|
||||
)
|
||||
|
||||
_UNDEFINED = object()
|
||||
|
||||
|
||||
class Message(TelegramObject):
|
||||
# fmt: off
|
||||
|
@ -333,8 +331,67 @@ class Message(TelegramObject):
|
|||
"""
|
||||
|
||||
# fmt: on
|
||||
|
||||
_effective_attachment = _UNDEFINED
|
||||
__slots__ = (
|
||||
'reply_markup',
|
||||
'audio',
|
||||
'contact',
|
||||
'migrate_to_chat_id',
|
||||
'forward_signature',
|
||||
'chat',
|
||||
'successful_payment',
|
||||
'game',
|
||||
'text',
|
||||
'forward_sender_name',
|
||||
'document',
|
||||
'new_chat_title',
|
||||
'forward_date',
|
||||
'group_chat_created',
|
||||
'media_group_id',
|
||||
'caption',
|
||||
'video',
|
||||
'bot',
|
||||
'entities',
|
||||
'via_bot',
|
||||
'new_chat_members',
|
||||
'connected_website',
|
||||
'animation',
|
||||
'migrate_from_chat_id',
|
||||
'forward_from',
|
||||
'sticker',
|
||||
'location',
|
||||
'venue',
|
||||
'edit_date',
|
||||
'reply_to_message',
|
||||
'passport_data',
|
||||
'pinned_message',
|
||||
'forward_from_chat',
|
||||
'new_chat_photo',
|
||||
'message_id',
|
||||
'delete_chat_photo',
|
||||
'from_user',
|
||||
'author_signature',
|
||||
'proximity_alert_triggered',
|
||||
'sender_chat',
|
||||
'dice',
|
||||
'forward_from_message_id',
|
||||
'caption_entities',
|
||||
'voice',
|
||||
'date',
|
||||
'supergroup_chat_created',
|
||||
'poll',
|
||||
'left_chat_member',
|
||||
'photo',
|
||||
'channel_chat_created',
|
||||
'invoice',
|
||||
'video_note',
|
||||
'_effective_attachment',
|
||||
'message_auto_delete_timer_changed',
|
||||
'voice_chat_ended',
|
||||
'voice_chat_participants_invited',
|
||||
'voice_chat_started',
|
||||
'voice_chat_scheduled',
|
||||
'_id_attrs',
|
||||
)
|
||||
|
||||
ATTACHMENT_TYPES: ClassVar[List[str]] = [
|
||||
'audio',
|
||||
|
@ -497,6 +554,8 @@ class Message(TelegramObject):
|
|||
self.reply_markup = reply_markup
|
||||
self.bot = bot
|
||||
|
||||
self._effective_attachment = DEFAULT_NONE
|
||||
|
||||
self._id_attrs = (self.message_id, self.chat)
|
||||
|
||||
@property
|
||||
|
@ -613,7 +672,7 @@ class Message(TelegramObject):
|
|||
:obj:`None` if no attachment was sent.
|
||||
|
||||
"""
|
||||
if self._effective_attachment is not _UNDEFINED:
|
||||
if self._effective_attachment is not DEFAULT_NONE:
|
||||
return self._effective_attachment # type: ignore
|
||||
|
||||
for i in Message.ATTACHMENT_TYPES:
|
||||
|
@ -626,10 +685,7 @@ class Message(TelegramObject):
|
|||
return self._effective_attachment # type: ignore
|
||||
|
||||
def __getitem__(self, item: str) -> Any: # pylint: disable=R1710
|
||||
if item in self.__dict__.keys():
|
||||
return self.__dict__[item]
|
||||
if item == 'chat_id':
|
||||
return self.chat.id
|
||||
return self.chat.id if item == 'chat_id' else super().__getitem__(item)
|
||||
|
||||
def to_dict(self) -> JSONDict:
|
||||
"""See :meth:`telegram.TelegramObject.to_dict`."""
|
||||
|
|
|
@ -44,6 +44,8 @@ class MessageAutoDeleteTimerChanged(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('message_auto_delete_time', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message_auto_delete_time: int,
|
||||
|
|
|
@ -59,6 +59,8 @@ class MessageEntity(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('length', 'url', 'user', 'type', 'language', 'offset', '_id_attrs')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
type: str, # pylint: disable=W0622
|
||||
|
|
|
@ -32,6 +32,8 @@ class MessageId(TelegramObject):
|
|||
message_id (:obj:`int`): Unique message identifier
|
||||
"""
|
||||
|
||||
__slots__ = ('message_id', '_id_attrs')
|
||||
|
||||
def __init__(self, message_id: int, **_kwargs: Any):
|
||||
self.message_id = int(message_id)
|
||||
|
||||
|
|
|
@ -21,11 +21,14 @@
|
|||
from typing import ClassVar
|
||||
|
||||
from telegram import constants
|
||||
from telegram.utils.deprecate import set_new_attribute_deprecated
|
||||
|
||||
|
||||
class ParseMode:
|
||||
"""This object represents a Telegram Message Parse Modes."""
|
||||
|
||||
__slots__ = ('__dict__',)
|
||||
|
||||
MARKDOWN: ClassVar[str] = constants.PARSEMODE_MARKDOWN
|
||||
""":const:`telegram.constants.PARSEMODE_MARKDOWN`\n
|
||||
|
||||
|
@ -37,3 +40,6 @@ class ParseMode:
|
|||
""":const:`telegram.constants.PARSEMODE_MARKDOWN_V2`"""
|
||||
HTML: ClassVar[str] = constants.PARSEMODE_HTML
|
||||
""":const:`telegram.constants.PARSEMODE_HTML`"""
|
||||
|
||||
def __setattr__(self, key: str, value: object) -> None:
|
||||
set_new_attribute_deprecated(self, key, value)
|
||||
|
|
|
@ -51,6 +51,8 @@ if TYPE_CHECKING:
|
|||
class TelegramDecryptionError(TelegramError):
|
||||
"""Something went wrong with decryption."""
|
||||
|
||||
__slots__ = ('_msg',)
|
||||
|
||||
def __init__(self, message: Union[str, Exception]):
|
||||
super().__init__(f"TelegramDecryptionError: {message}")
|
||||
self._msg = str(message)
|
||||
|
@ -143,6 +145,16 @@ class EncryptedCredentials(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'hash',
|
||||
'secret',
|
||||
'bot',
|
||||
'data',
|
||||
'_id_attrs',
|
||||
'_decrypted_secret',
|
||||
'_decrypted_data',
|
||||
)
|
||||
|
||||
def __init__(self, data: str, hash: str, secret: str, bot: 'Bot' = None, **_kwargs: Any):
|
||||
# Required
|
||||
self.data = data
|
||||
|
@ -212,6 +224,8 @@ class Credentials(TelegramObject):
|
|||
nonce (:obj:`str`): Bot-specified nonce
|
||||
"""
|
||||
|
||||
__slots__ = ('bot', 'nonce', 'secure_data')
|
||||
|
||||
def __init__(self, secure_data: 'SecureData', nonce: str, bot: 'Bot' = None, **_kwargs: Any):
|
||||
# Required
|
||||
self.secure_data = secure_data
|
||||
|
@ -260,6 +274,21 @@ class SecureData(TelegramObject):
|
|||
temporary registration.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'bot',
|
||||
'utility_bill',
|
||||
'personal_details',
|
||||
'temporary_registration',
|
||||
'address',
|
||||
'driver_license',
|
||||
'rental_agreement',
|
||||
'internal_passport',
|
||||
'identity_card',
|
||||
'bank_statement',
|
||||
'passport',
|
||||
'passport_registration',
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
personal_details: 'SecureValue' = None,
|
||||
|
@ -345,6 +374,8 @@ class SecureValue(TelegramObject):
|
|||
|
||||
"""
|
||||
|
||||
__slots__ = ('data', 'front_side', 'reverse_side', 'selfie', 'files', 'translation', 'bot')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data: 'DataCredentials' = None,
|
||||
|
@ -395,6 +426,8 @@ class SecureValue(TelegramObject):
|
|||
class _CredentialsBase(TelegramObject):
|
||||
"""Base class for DataCredentials and FileCredentials."""
|
||||
|
||||
__slots__ = ('hash', 'secret', 'file_hash', 'data_hash', 'bot')
|
||||
|
||||
def __init__(self, hash: str, secret: str, bot: 'Bot' = None, **_kwargs: Any):
|
||||
self.hash = hash
|
||||
self.secret = secret
|
||||
|
@ -420,6 +453,8 @@ class DataCredentials(_CredentialsBase):
|
|||
secret (:obj:`str`): Secret of encrypted data
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, data_hash: str, secret: str, **_kwargs: Any):
|
||||
super().__init__(data_hash, secret, **_kwargs)
|
||||
|
||||
|
@ -447,6 +482,8 @@ class FileCredentials(_CredentialsBase):
|
|||
secret (:obj:`str`): Secret of encrypted file
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, file_hash: str, secret: str, **_kwargs: Any):
|
||||
super().__init__(file_hash, secret, **_kwargs)
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue