Merge remote-tracking branch 'origin/dev-3.x' into dev-3.x-require-sugar

# Conflicts:
#	poetry.lock
This commit is contained in:
mpa 2020-07-21 04:49:37 +04:00
commit ca44f9c01a
No known key found for this signature in database
GPG key ID: BCCFBFCCC9B754A8
122 changed files with 1347 additions and 605 deletions

View file

@ -1 +1 @@
4.8
4.9

View file

@ -49,6 +49,5 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
file: coverage.xml
flags: unittests
yml: codecov.yml
name: py-${{ matrix.python-version }}-${{ matrix.os }}
fail_ci_if_error: true

View file

@ -28,5 +28,5 @@ __all__ = (
"handler",
)
__version__ = "3.0.0a4"
__api_version__ = "4.8"
__version__ = "3.0.0a5"
__api_version__ = "4.9"

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
from __future__ import annotations
from typing import (
TYPE_CHECKING,
Any,
AsyncGenerator,
Dict,
@ -20,6 +21,9 @@ from aiogram.api.methods import Request, TelegramMethod
from .base import BaseSession
if TYPE_CHECKING: # pragma: no cover
from ..bot import Bot
T = TypeVar("T")
_ProxyBasic = Union[str, Tuple[str, BasicAuth]]
_ProxyChain = Iterable[_ProxyBasic]
@ -125,15 +129,17 @@ class AiohttpSession(BaseSession):
form.add_field(key, value, filename=value.filename or key)
return form
async def make_request(self, token: str, call: TelegramMethod[T]) -> T:
async def make_request(
self, bot: Bot, call: TelegramMethod[T], timeout: Optional[int] = None
) -> T:
session = await self.create_session()
request = call.build_request()
url = self.api.api_url(token=token, method=request.method)
request = call.build_request(bot)
url = self.api.api_url(token=bot.token, method=request.method)
form = self.build_form_data(request)
async with session.post(
url, data=form, timeout=call.request_timeout or self.timeout
url, data=form, timeout=self.timeout if timeout is None else timeout
) as resp:
raw_result = await resp.json(loads=self.json_loads)

View file

@ -4,63 +4,39 @@ import abc
import datetime
import json
from types import TracebackType
from typing import Any, AsyncGenerator, Callable, ClassVar, Optional, Type, TypeVar, Union
from typing import (
TYPE_CHECKING,
Any,
AsyncGenerator,
Callable,
ClassVar,
Optional,
Type,
TypeVar,
Union,
)
from aiogram.utils.exceptions import TelegramAPIError
from ....utils.helper import Default
from ...methods import Response, TelegramMethod
from ...types import UNSET
from ..telegram import PRODUCTION, TelegramAPIServer
if TYPE_CHECKING: # pragma: no cover
from ..bot import Bot
T = TypeVar("T")
_JsonLoads = Callable[..., Any]
_JsonDumps = Callable[..., str]
class BaseSession(abc.ABC):
# global session timeout
default_timeout: ClassVar[float] = 60.0
_api: TelegramAPIServer
_json_loads: _JsonLoads
_json_dumps: _JsonDumps
_timeout: float
@property
def api(self) -> TelegramAPIServer:
return getattr(self, "_api", PRODUCTION) # type: ignore
@api.setter
def api(self, value: TelegramAPIServer) -> None:
self._api = value
@property
def json_loads(self) -> _JsonLoads:
return getattr(self, "_json_loads", json.loads) # type: ignore
@json_loads.setter
def json_loads(self, value: _JsonLoads) -> None:
self._json_loads = value # type: ignore
@property
def json_dumps(self) -> _JsonDumps:
return getattr(self, "_json_dumps", json.dumps) # type: ignore
@json_dumps.setter
def json_dumps(self, value: _JsonDumps) -> None:
self._json_dumps = value # type: ignore
@property
def timeout(self) -> float:
return getattr(self, "_timeout", self.__class__.default_timeout) # type: ignore
@timeout.setter
def timeout(self, value: float) -> None:
self._timeout = value
@timeout.deleter
def timeout(self) -> None:
if hasattr(self, "_timeout"):
del self._timeout
api: Default[TelegramAPIServer] = Default(PRODUCTION)
json_loads: Default[_JsonLoads] = Default(json.loads)
json_dumps: Default[_JsonDumps] = Default(json.dumps)
timeout: Default[float] = Default(fget=lambda self: float(self.__class__.default_timeout))
@classmethod
def raise_for_status(cls, response: Response[T]) -> None:
@ -73,7 +49,9 @@ class BaseSession(abc.ABC):
pass
@abc.abstractmethod
async def make_request(self, token: str, method: TelegramMethod[T]) -> T: # pragma: no cover
async def make_request(
self, bot: Bot, method: TelegramMethod[T], timeout: Optional[int] = UNSET
) -> T: # pragma: no cover
pass
@abc.abstractmethod

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InputFile, MaskPosition
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class AddStickerToSet(TelegramMethod[bool]):
"""
@ -34,7 +39,7 @@ class AddStickerToSet(TelegramMethod[bool]):
mask_position: Optional[MaskPosition] = None
"""A JSON-serialized object for position where the mask should be placed on faces"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker"})
files: Dict[str, InputFile] = {}

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class AnswerCallbackQuery(TelegramMethod[bool]):
"""
@ -33,7 +38,7 @@ class AnswerCallbackQuery(TelegramMethod[bool]):
"""The maximum amount of time in seconds that the result of the callback query may be cached
client-side. Telegram apps will support caching starting in version 3.14. Defaults to 0."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="answerCallbackQuery", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import InlineQueryResult
from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class AnswerInlineQuery(TelegramMethod[bool]):
"""
@ -26,8 +31,8 @@ class AnswerInlineQuery(TelegramMethod[bool]):
query. By default, results may be returned to any user who sends the same query"""
next_offset: Optional[str] = None
"""Pass the offset that a client should send in the next query with the same text to receive
more results. Pass an empty string if there are no more results or if you dont support
pagination. Offset length cant exceed 64 bytes."""
more results. Pass an empty string if there are no more results or if you don't support
pagination. Offset length can't exceed 64 bytes."""
switch_pm_text: Optional[str] = None
"""If passed, clients will display a button with specified text that switches the user to a
private chat with the bot and sends the bot a start message with the parameter
@ -36,8 +41,8 @@ class AnswerInlineQuery(TelegramMethod[bool]):
"""Deep-linking parameter for the /start message sent to the bot when user presses the switch
button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
prepare_parse_mode(data["results"])
prepare_parse_mode(bot, data["results"])
return Request(method="answerInlineQuery", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class AnswerPreCheckoutQuery(TelegramMethod[bool]):
"""
@ -26,7 +31,7 @@ class AnswerPreCheckoutQuery(TelegramMethod[bool]):
amazing black T-shirts while you were busy filling out your payment details. Please choose
a different color or garment!"). Telegram will display this message to the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="answerPreCheckoutQuery", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import ShippingOption
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class AnswerShippingQuery(TelegramMethod[bool]):
"""
@ -27,7 +32,7 @@ class AnswerShippingQuery(TelegramMethod[bool]):
impossible to complete the order (e.g. "Sorry, delivery to your desired address is
unavailable'). Telegram will display this message to the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="answerShippingQuery", data=data)

View file

@ -4,10 +4,10 @@ import abc
import secrets
from typing import TYPE_CHECKING, Any, Dict, Generator, Generic, Optional, TypeVar, Union
from pydantic import BaseConfig, BaseModel, Extra
from pydantic import BaseConfig, BaseModel, Extra, root_validator
from pydantic.generics import GenericModel
from ..types import InputFile, ResponseParameters
from ..types import UNSET, InputFile, ResponseParameters
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
@ -46,22 +46,33 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]):
arbitrary_types_allowed = True
orm_mode = True
@root_validator(pre=True)
def remove_unset(cls, values: Dict[str, Any]) -> Dict[str, Any]:
"""
Remove UNSET from `parse_mode` before fields validation.
We use UNSET as a sentinel value for `parse_mode` and replace it to real value later.
It isn't a problem when it's just default value for a model field, but UNSET might be passing to
a model initialization from `Bot.method_name`, so we must take care of it and
remove it before fields validation.
"""
for parse_mode_attribute in {"parse_mode", "explanation_parse_mode"}:
if parse_mode_attribute in values and values[parse_mode_attribute] is UNSET:
values.pop(parse_mode_attribute)
return values
@property
@abc.abstractmethod
def __returning__(self) -> type: # pragma: no cover
pass
@abc.abstractmethod
def build_request(self) -> Request: # pragma: no cover
def build_request(self, bot: Bot) -> Request: # pragma: no cover
pass
request_timeout: Optional[float] = None
def dict(self, **kwargs: Any) -> Any:
# override dict of pydantic.BaseModel to overcome exporting request_timeout field
exclude = kwargs.pop("exclude", set())
if isinstance(exclude, set):
exclude.add("request_timeout")
return super().dict(exclude=exclude, **kwargs)
@ -115,19 +126,20 @@ def prepare_media_file(data: Dict[str, Any], files: Dict[str, InputFile]) -> Non
data["media"]["media"] = f"attach://{tag}"
def prepare_parse_mode(root: Any, parse_mode_property: str = "parse_mode") -> None:
def prepare_parse_mode(bot: Bot, root: Any, parse_mode_property: str = "parse_mode") -> None:
"""
Find and set parse_mode with highest priority.
Developer can manually set parse_mode for each message (or message-like) object,
but if parse_mode was unset we should use value from Bot object.
We can't use None for "unset state", because None itself is the parse_mode option.
"""
if isinstance(root, list):
for item in root:
prepare_parse_mode(item, parse_mode_property=parse_mode_property)
return
if root.get(parse_mode_property):
return
from ..client.bot import Bot
bot = Bot.get_current(no_error=True)
if bot and bot.parse_mode:
root[parse_mode_property] = bot.parse_mode
return
return
prepare_parse_mode(bot=bot, root=item, parse_mode_property=parse_mode_property)
elif root.get(parse_mode_property, UNSET) is UNSET:
if bot.parse_mode:
root[parse_mode_property] = bot.parse_mode
else:
root[parse_mode_property] = None

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InputFile, MaskPosition
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class CreateNewStickerSet(TelegramMethod[bool]):
"""
@ -40,7 +45,7 @@ class CreateNewStickerSet(TelegramMethod[bool]):
mask_position: Optional[MaskPosition] = None
"""A JSON-serialized object for position where the mask should be placed on faces"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker"})
files: Dict[str, InputFile] = {}

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class DeleteChatPhoto(TelegramMethod[bool]):
"""
@ -18,7 +23,7 @@ class DeleteChatPhoto(TelegramMethod[bool]):
"""Unique identifier for the target chat or username of the target channel (in the format
@channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="deleteChatPhoto", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class DeleteChatStickerSet(TelegramMethod[bool]):
"""
@ -19,7 +24,7 @@ class DeleteChatStickerSet(TelegramMethod[bool]):
"""Unique identifier for the target chat or username of the target supergroup (in the format
@supergroupusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="deleteChatStickerSet", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class DeleteMessage(TelegramMethod[bool]):
"""
@ -28,7 +33,7 @@ class DeleteMessage(TelegramMethod[bool]):
message_id: int
"""Identifier of the message to delete"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="deleteMessage", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class DeleteStickerFromSet(TelegramMethod[bool]):
"""
@ -15,7 +20,7 @@ class DeleteStickerFromSet(TelegramMethod[bool]):
sticker: str
"""File identifier of the sticker"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="deleteStickerFromSet", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class DeleteWebhook(TelegramMethod[bool]):
"""
@ -13,7 +18,7 @@ class DeleteWebhook(TelegramMethod[bool]):
__returning__ = bool
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="deleteWebhook", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from ..types import InlineKeyboardMarkup, Message
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import UNSET, InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class EditMessageCaption(TelegramMethod[Union[Message, bool]]):
"""
@ -23,13 +28,13 @@ class EditMessageCaption(TelegramMethod[Union[Message, bool]]):
"""Required if chat_id and message_id are not specified. Identifier of the inline message"""
caption: Optional[str] = None
"""New caption of the message, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the message caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for an inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
prepare_parse_mode(data)
prepare_parse_mode(bot, data)
return Request(method="editMessageCaption", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class EditMessageLiveLocation(TelegramMethod[Union[Message, bool]]):
"""
@ -30,7 +35,7 @@ class EditMessageLiveLocation(TelegramMethod[Union[Message, bool]]):
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for a new inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="editMessageLiveLocation", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, InputFile, InputMedia, Message
from .base import Request, TelegramMethod, prepare_media_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class EditMessageMedia(TelegramMethod[Union[Message, bool]]):
"""
@ -30,9 +35,9 @@ class EditMessageMedia(TelegramMethod[Union[Message, bool]]):
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for a new inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
prepare_parse_mode(data["media"])
prepare_parse_mode(bot, data["media"])
files: Dict[str, InputFile] = {}
prepare_media_file(data=data, files=files)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class EditMessageReplyMarkup(TelegramMethod[Union[Message, bool]]):
"""
@ -24,7 +29,7 @@ class EditMessageReplyMarkup(TelegramMethod[Union[Message, bool]]):
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for an inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="editMessageReplyMarkup", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from ..types import InlineKeyboardMarkup, Message
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import UNSET, InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class EditMessageText(TelegramMethod[Union[Message, bool]]):
"""
@ -23,14 +28,14 @@ class EditMessageText(TelegramMethod[Union[Message, bool]]):
"""Required if inline_message_id is not specified. Identifier of the message to edit"""
inline_message_id: Optional[str] = None
"""Required if chat_id and message_id are not specified. Identifier of the inline message"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the message text. See formatting options for more details."""
disable_web_page_preview: Optional[bool] = None
"""Disables link previews for links in this message"""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for an inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="editMessageText", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class ExportChatInviteLink(TelegramMethod[str]):
"""
@ -23,7 +28,7 @@ class ExportChatInviteLink(TelegramMethod[str]):
"""Unique identifier for the target chat or username of the target channel (in the format
@channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="exportChatInviteLink", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class ForwardMessage(TelegramMethod[Message]):
"""
@ -24,7 +29,7 @@ class ForwardMessage(TelegramMethod[Message]):
disable_notification: Optional[bool] = None
"""Sends the message silently. Users will receive a notification with no sound."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="forwardMessage", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import Chat
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetChat(TelegramMethod[Chat]):
"""
@ -19,7 +24,7 @@ class GetChat(TelegramMethod[Chat]):
"""Unique identifier for the target chat or username of the target supergroup or channel (in
the format @channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getChat", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Union
from ..types import ChatMember
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetChatAdministrators(TelegramMethod[List[ChatMember]]):
"""
@ -20,7 +25,7 @@ class GetChatAdministrators(TelegramMethod[List[ChatMember]]):
"""Unique identifier for the target chat or username of the target supergroup or channel (in
the format @channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getChatAdministrators", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import ChatMember
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetChatMember(TelegramMethod[ChatMember]):
"""
@ -20,7 +25,7 @@ class GetChatMember(TelegramMethod[ChatMember]):
user_id: int
"""Unique identifier of the target user"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getChatMember", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetChatMembersCount(TelegramMethod[int]):
"""
@ -16,7 +21,7 @@ class GetChatMembersCount(TelegramMethod[int]):
"""Unique identifier for the target chat or username of the target supergroup or channel (in
the format @channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getChatMembersCount", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from ..types import File
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetFile(TelegramMethod[File]):
"""
@ -22,7 +27,7 @@ class GetFile(TelegramMethod[File]):
file_id: str
"""File identifier to get info about"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getFile", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import GameHighScore
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetGameHighScores(TelegramMethod[List[GameHighScore]]):
"""
@ -27,7 +32,7 @@ class GetGameHighScores(TelegramMethod[List[GameHighScore]]):
inline_message_id: Optional[str] = None
"""Required if chat_id and message_id are not specified. Identifier of the inline message"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getGameHighScores", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from ..types import User
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetMe(TelegramMethod[User]):
"""
@ -14,7 +19,7 @@ class GetMe(TelegramMethod[User]):
__returning__ = User
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getMe", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List
from ..types import BotCommand
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetMyCommands(TelegramMethod[List[BotCommand]]):
"""
@ -14,7 +19,7 @@ class GetMyCommands(TelegramMethod[List[BotCommand]]):
__returning__ = List[BotCommand]
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getMyCommands", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from ..types import StickerSet
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetStickerSet(TelegramMethod[StickerSet]):
"""
@ -16,7 +21,7 @@ class GetStickerSet(TelegramMethod[StickerSet]):
name: str
"""Name of the sticker set"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getStickerSet", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import Update
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetUpdates(TelegramMethod[List[Update]]):
"""
@ -37,7 +42,7 @@ class GetUpdates(TelegramMethod[List[Update]]):
list to receive all updates regardless of type (default). If not specified, the previous
setting will be used."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getUpdates", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional
from ..types import UserProfilePhotos
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetUserProfilePhotos(TelegramMethod[UserProfilePhotos]):
"""
@ -22,7 +27,7 @@ class GetUserProfilePhotos(TelegramMethod[UserProfilePhotos]):
"""Limits the number of photos to be retrieved. Values between 1-100 are accepted. Defaults to
100."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getUserProfilePhotos", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from ..types import WebhookInfo
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class GetWebhookInfo(TelegramMethod[WebhookInfo]):
"""
@ -15,7 +20,7 @@ class GetWebhookInfo(TelegramMethod[WebhookInfo]):
__returning__ = WebhookInfo
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="getWebhookInfo", data=data)

View file

@ -1,8 +1,13 @@
from __future__ import annotations
import datetime
from typing import Any, Dict, Optional, Union
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class KickChatMember(TelegramMethod[bool]):
"""
@ -25,7 +30,7 @@ class KickChatMember(TelegramMethod[bool]):
"""Date when the user will be unbanned, unix time. If user is banned for more than 366 days or
less than 30 seconds from the current time they are considered to be banned forever"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="kickChatMember", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class LeaveChat(TelegramMethod[bool]):
"""
@ -16,7 +21,7 @@ class LeaveChat(TelegramMethod[bool]):
"""Unique identifier for the target chat or username of the target supergroup or channel (in
the format @channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="leaveChat", data=data)

View file

@ -1,13 +1,18 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class PinChatMessage(TelegramMethod[bool]):
"""
Use this method to pin a message in a group, a supergroup, or a channel. The bot must be an
administrator in the chat for this to work and must have the can_pin_messages admin right in
the supergroup or can_edit_messages admin right in the channel. Returns True on success.
administrator in the chat for this to work and must have the 'can_pin_messages' admin right in
the supergroup or 'can_edit_messages' admin right in the channel. Returns True on success.
Source: https://core.telegram.org/bots/api#pinchatmessage
"""
@ -23,7 +28,7 @@ class PinChatMessage(TelegramMethod[bool]):
"""Pass True, if it is not necessary to send a notification to all chat members about the new
pinned message. Notifications are always disabled in channels."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="pinChatMessage", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class PromoteChatMember(TelegramMethod[bool]):
"""
@ -39,7 +44,7 @@ class PromoteChatMember(TelegramMethod[bool]):
privileges or demote administrators that he has promoted, directly or indirectly (promoted
by administrators that were appointed by him)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="promoteChatMember", data=data)

View file

@ -1,9 +1,14 @@
from __future__ import annotations
import datetime
from typing import Any, Dict, Optional, Union
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import ChatPermissions
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class RestrictChatMember(TelegramMethod[bool]):
"""
@ -28,7 +33,7 @@ class RestrictChatMember(TelegramMethod[bool]):
more than 366 days or less than 30 seconds from the current time, they are considered to be
restricted forever"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="restrictChatMember", data=data)

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
InputFile,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendAnimation(TelegramMethod[Message]):
"""
@ -38,14 +44,14 @@ class SendAnimation(TelegramMethod[Message]):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
caption: Optional[str] = None
"""Animation caption (may also be used when resending animation by file_id), 0-1024 characters
after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the animation caption. See formatting options for more
details."""
disable_notification: Optional[bool] = None
@ -58,7 +64,7 @@ class SendAnimation(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"animation", "thumb"})
files: Dict[str, InputFile] = {}

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
InputFile,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendAudio(TelegramMethod[Message]):
"""
@ -33,7 +39,7 @@ class SendAudio(TelegramMethod[Message]):
file from the Internet, or upload a new one using multipart/form-data."""
caption: Optional[str] = None
"""Audio caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the audio caption. See formatting options for more details."""
duration: Optional[int] = None
"""Duration of the audio in seconds"""
@ -44,8 +50,8 @@ class SendAudio(TelegramMethod[Message]):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
disable_notification: Optional[bool] = None
@ -58,7 +64,7 @@ class SendAudio(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"audio", "thumb"})
files: Dict[str, InputFile] = {}

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendChatAction(TelegramMethod[bool]):
"""
@ -29,7 +34,7 @@ class SendChatAction(TelegramMethod[bool]):
record_audio or upload_audio for audio files, upload_document for general files,
find_location for location data, record_video_note or upload_video_note for video notes."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendChatAction", data=data)

View file

@ -1,4 +1,6 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
ForceReply,
@ -9,6 +11,9 @@ from ..types import (
)
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendContact(TelegramMethod[Message]):
"""
@ -40,7 +45,7 @@ class SendContact(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendContact", data=data)

View file

@ -1,4 +1,6 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
ForceReply,
@ -9,12 +11,14 @@ from ..types import (
)
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendDice(TelegramMethod[Message]):
"""
Use this method to send a dice, which will have a random value from 1 to 6. On success, the
sent Message is returned. (Yes, we're aware of the 'proper' singular of die. But it's awkward,
and we decided to help it change. One dice at a time!)
Use this method to send an animated emoji that will display a random value. On success, the
sent Message is returned.
Source: https://core.telegram.org/bots/api#senddice
"""
@ -25,8 +29,8 @@ class SendDice(TelegramMethod[Message]):
"""Unique identifier for the target chat or username of the target channel (in the format
@channelusername)"""
emoji: Optional[str] = None
"""Emoji on which the dice throw animation is based. Currently, must be one of '' or ''.
Defauts to ''"""
"""Emoji on which the dice throw animation is based. Currently, must be one of '', '', or ''.
Dice can have values 1-6 for '' and '', and values 1-5 for ''. Defaults to ''"""
disable_notification: Optional[bool] = None
"""Sends the message silently. Users will receive a notification with no sound."""
reply_to_message_id: Optional[int] = None
@ -37,7 +41,7 @@ class SendDice(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendDice", data=data)

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
InputFile,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendDocument(TelegramMethod[Message]):
"""
@ -32,14 +38,14 @@ class SendDocument(TelegramMethod[Message]):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
caption: Optional[str] = None
"""Document caption (may also be used when resending documents by file_id), 0-1024 characters
after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the document caption. See formatting options for more details."""
disable_notification: Optional[bool] = None
"""Sends the message silently. Users will receive a notification with no sound."""
@ -51,7 +57,7 @@ class SendDocument(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"document", "thumb"})
files: Dict[str, InputFile] = {}

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional
from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendGame(TelegramMethod[Message]):
"""
@ -23,10 +28,10 @@ class SendGame(TelegramMethod[Message]):
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for an inline keyboard. If empty, one Play game_title button
"""A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button
will be shown. If not empty, the first button must launch the game."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendGame", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import InlineKeyboardMarkup, LabeledPrice, Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendInvoice(TelegramMethod[Message]):
"""
@ -66,7 +71,7 @@ class SendInvoice(TelegramMethod[Message]):
"""A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button
will be shown. If not empty, the first button must be a Pay button."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendInvoice", data=data)

View file

@ -1,4 +1,6 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
ForceReply,
@ -9,6 +11,9 @@ from ..types import (
)
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendLocation(TelegramMethod[Message]):
"""
@ -39,7 +44,7 @@ class SendLocation(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendLocation", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from ..types import InputFile, InputMediaPhoto, InputMediaVideo, Message
from .base import Request, TelegramMethod, prepare_input_media, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendMediaGroup(TelegramMethod[List[Message]]):
"""
@ -24,9 +29,9 @@ class SendMediaGroup(TelegramMethod[List[Message]]):
reply_to_message_id: Optional[int] = None
"""If the messages are a reply, ID of the original message"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
prepare_parse_mode(data["media"])
prepare_parse_mode(bot, data["media"])
files: Dict[str, InputFile] = {}
prepare_input_media(data, files)

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
Message,
@ -9,6 +12,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendMessage(TelegramMethod[Message]):
"""
@ -24,7 +30,7 @@ class SendMessage(TelegramMethod[Message]):
@channelusername)"""
text: str
"""Text of the message to be sent, 1-4096 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the message text. See formatting options for more details."""
disable_web_page_preview: Optional[bool] = None
"""Disables link previews for links in this message"""
@ -38,8 +44,8 @@ class SendMessage(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
prepare_parse_mode(data)
prepare_parse_mode(bot, data)
return Request(method="sendMessage", data=data)

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
InputFile,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendPhoto(TelegramMethod[Message]):
"""
@ -30,7 +36,7 @@ class SendPhoto(TelegramMethod[Message]):
caption: Optional[str] = None
"""Photo caption (may also be used when resending photos by file_id), 0-1024 characters after
entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the photo caption. See formatting options for more details."""
disable_notification: Optional[bool] = None
"""Sends the message silently. Users will receive a notification with no sound."""
@ -42,7 +48,7 @@ class SendPhoto(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"photo"})
files: Dict[str, InputFile] = {}

View file

@ -1,7 +1,10 @@
from __future__ import annotations
import datetime
from typing import Any, Dict, List, Optional, Union
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
Message,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendPoll(TelegramMethod[Message]):
"""
@ -39,7 +45,7 @@ class SendPoll(TelegramMethod[Message]):
explanation: Optional[str] = None
"""Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a
quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing"""
explanation_parse_mode: Optional[str] = None
explanation_parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the explanation. See formatting options for more details."""
open_period: Optional[int] = None
"""Amount of time in seconds the poll will be active after creation, 5-600. Can't be used
@ -59,8 +65,8 @@ class SendPoll(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
prepare_parse_mode(data, parse_mode_property="explanation_parse_mode")
prepare_parse_mode(bot, data, parse_mode_property="explanation_parse_mode")
return Request(method="sendPoll", data=data)

View file

@ -1,4 +1,6 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
ForceReply,
@ -10,6 +12,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendSticker(TelegramMethod[Message]):
"""
@ -38,7 +43,7 @@ class SendSticker(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"sticker"})
files: Dict[str, InputFile] = {}

View file

@ -1,4 +1,6 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
ForceReply,
@ -9,6 +11,9 @@ from ..types import (
)
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendVenue(TelegramMethod[Message]):
"""
@ -45,7 +50,7 @@ class SendVenue(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="sendVenue", data=data)

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
InputFile,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendVideo(TelegramMethod[Message]):
"""
@ -38,14 +44,14 @@ class SendVideo(TelegramMethod[Message]):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
caption: Optional[str] = None
"""Video caption (may also be used when resending videos by file_id), 0-1024 characters after
entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the video caption. See formatting options for more details."""
supports_streaming: Optional[bool] = None
"""Pass True, if the uploaded video is suitable for streaming"""
@ -59,7 +65,7 @@ class SendVideo(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"video", "thumb"})
files: Dict[str, InputFile] = {}

View file

@ -1,4 +1,6 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
ForceReply,
@ -10,6 +12,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendVideoNote(TelegramMethod[Message]):
"""
@ -35,8 +40,8 @@ class SendVideoNote(TelegramMethod[Message]):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
disable_notification: Optional[bool] = None
@ -49,7 +54,7 @@ class SendVideoNote(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"video_note", "thumb"})
files: Dict[str, InputFile] = {}

View file

@ -1,6 +1,9 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import (
UNSET,
ForceReply,
InlineKeyboardMarkup,
InputFile,
@ -10,6 +13,9 @@ from ..types import (
)
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SendVoice(TelegramMethod[Message]):
"""
@ -33,7 +39,7 @@ class SendVoice(TelegramMethod[Message]):
Internet, or upload a new one using multipart/form-data."""
caption: Optional[str] = None
"""Voice message caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the voice message caption. See formatting options for more
details."""
duration: Optional[int] = None
@ -48,7 +54,7 @@ class SendVoice(TelegramMethod[Message]):
"""Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"voice"})
files: Dict[str, InputFile] = {}

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetChatAdministratorCustomTitle(TelegramMethod[bool]):
"""
@ -21,7 +26,7 @@ class SetChatAdministratorCustomTitle(TelegramMethod[bool]):
custom_title: str
"""New custom title for the administrator; 0-16 characters, emoji are not allowed"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setChatAdministratorCustomTitle", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetChatDescription(TelegramMethod[bool]):
"""
@ -20,7 +25,7 @@ class SetChatDescription(TelegramMethod[bool]):
description: Optional[str] = None
"""New chat description, 0-255 characters"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setChatDescription", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import ChatPermissions
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetChatPermissions(TelegramMethod[bool]):
"""
@ -21,7 +26,7 @@ class SetChatPermissions(TelegramMethod[bool]):
permissions: ChatPermissions
"""New default chat permissions"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setChatPermissions", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import InputFile
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetChatPhoto(TelegramMethod[bool]):
"""
@ -21,7 +26,7 @@ class SetChatPhoto(TelegramMethod[bool]):
photo: InputFile
"""New chat photo, uploaded using multipart/form-data"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"photo"})
files: Dict[str, InputFile] = {}

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetChatStickerSet(TelegramMethod[bool]):
"""
@ -21,7 +26,7 @@ class SetChatStickerSet(TelegramMethod[bool]):
sticker_set_name: str
"""Name of the sticker set to be set as the group sticker set"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setChatStickerSet", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetChatTitle(TelegramMethod[bool]):
"""
@ -20,7 +25,7 @@ class SetChatTitle(TelegramMethod[bool]):
title: str
"""New chat title, 1-255 characters"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setChatTitle", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetGameScore(TelegramMethod[Union[Message, bool]]):
"""
@ -32,7 +37,7 @@ class SetGameScore(TelegramMethod[Union[Message, bool]]):
inline_message_id: Optional[str] = None
"""Required if chat_id and message_id are not specified. Identifier of the inline message"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setGameScore", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List
from ..types import BotCommand
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetMyCommands(TelegramMethod[bool]):
"""
@ -17,7 +22,7 @@ class SetMyCommands(TelegramMethod[bool]):
"""A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most
100 commands can be specified."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setMyCommands", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List
from ..types import PassportElementError
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetPassportDataErrors(TelegramMethod[bool]):
"""
@ -24,7 +29,7 @@ class SetPassportDataErrors(TelegramMethod[bool]):
errors: List[PassportElementError]
"""A JSON-serialized array describing the errors"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setPassportDataErrors", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetStickerPositionInSet(TelegramMethod[bool]):
"""
@ -18,7 +23,7 @@ class SetStickerPositionInSet(TelegramMethod[bool]):
position: int
"""New sticker position in the set, zero-based"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="setStickerPositionInSet", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InputFile
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetStickerSetThumb(TelegramMethod[bool]):
"""
@ -27,7 +32,7 @@ class SetStickerSetThumb(TelegramMethod[bool]):
Internet, or upload a new one using multipart/form-data.. Animated sticker set thumbnail
can't be uploaded via HTTP URL."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"thumb"})
files: Dict[str, InputFile] = {}

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, List, Optional
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import InputFile
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class SetWebhook(TelegramMethod[bool]):
"""
@ -12,7 +17,7 @@ class SetWebhook(TelegramMethod[bool]):
after a reasonable amount of attempts. Returns True on success.
If you'd like to make sure that the Webhook request comes from Telegram, we recommend using a
secret path in the URL, e.g. https://www.example.com/<token>. Since nobody else knows your
bots token, you can be pretty sure its us.
bot's token, you can be pretty sure it's us.
Notes
1. You will not be able to receive updates using getUpdates for as long as an outgoing webhook
is set up.
@ -34,8 +39,8 @@ class SetWebhook(TelegramMethod[bool]):
our self-signed guide for details."""
max_connections: Optional[int] = None
"""Maximum allowed number of simultaneous HTTPS connections to the webhook for update
delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bots server,
and higher values to increase your bots throughput."""
delivery, 1-100. Defaults to 40. Use lower values to limit the load on your bot's server,
and higher values to increase your bot's throughput."""
allowed_updates: Optional[List[str]] = None
"""A JSON-serialized list of the update types you want your bot to receive. For example,
specify ['message', 'edited_channel_post', 'callback_query'] to only receive updates of
@ -43,7 +48,7 @@ class SetWebhook(TelegramMethod[bool]):
list to receive all updates regardless of type (default). If not specified, the previous
setting will be used."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"certificate"})
files: Dict[str, InputFile] = {}

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class StopMessageLiveLocation(TelegramMethod[Union[Message, bool]]):
"""
@ -26,7 +31,7 @@ class StopMessageLiveLocation(TelegramMethod[Union[Message, bool]]):
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for a new inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="stopMessageLiveLocation", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict, Optional, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, Poll
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class StopPoll(TelegramMethod[Poll]):
"""
@ -22,7 +27,7 @@ class StopPoll(TelegramMethod[Poll]):
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for a new message inline keyboard."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="stopPoll", data=data)

View file

@ -1,7 +1,12 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class UnbanChatMember(TelegramMethod[bool]):
"""
@ -20,7 +25,7 @@ class UnbanChatMember(TelegramMethod[bool]):
user_id: int
"""Unique identifier of the target user"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="unbanChatMember", data=data)

View file

@ -1,13 +1,18 @@
from typing import Any, Dict, Union
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class UnpinChatMessage(TelegramMethod[bool]):
"""
Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be an
administrator in the chat for this to work and must have the can_pin_messages admin right in
the supergroup or can_edit_messages admin right in the channel. Returns True on success.
administrator in the chat for this to work and must have the 'can_pin_messages' admin right in
the supergroup or 'can_edit_messages' admin right in the channel. Returns True on success.
Source: https://core.telegram.org/bots/api#unpinchatmessage
"""
@ -18,7 +23,7 @@ class UnpinChatMessage(TelegramMethod[bool]):
"""Unique identifier for the target chat or username of the target channel (in the format
@channelusername)"""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict()
return Request(method="unpinChatMessage", data=data)

View file

@ -1,8 +1,13 @@
from typing import Any, Dict
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict
from ..types import File, InputFile
from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover
from ..client.bot import Bot
class UploadStickerFile(TelegramMethod[File]):
"""
@ -20,7 +25,7 @@ class UploadStickerFile(TelegramMethod[File]):
"""PNG image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed
512px, and either width or height must be exactly 512px."""
def build_request(self) -> Request:
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"png_sticker"})
files: Dict[str, InputFile] = {}

View file

@ -1,6 +1,6 @@
from .animation import Animation
from .audio import Audio
from .base import TelegramObject
from .base import UNSET, TelegramObject
from .bot_command import BotCommand
from .callback_game import CallbackGame
from .callback_query import CallbackQuery
@ -103,6 +103,7 @@ from .webhook_info import WebhookInfo
__all__ = (
"TelegramObject",
"Downloadable",
"UNSET",
"BufferedInputFile",
"FSInputFile",
"URLInputFile",

View file

@ -1,4 +1,6 @@
import datetime
from typing import Any
from unittest.mock import sentinel
from pydantic import BaseModel, Extra
@ -19,3 +21,6 @@ class TelegramObject(ContextInstanceMixin["TelegramObject"], BaseModel):
class MutableTelegramObject(TelegramObject):
class Config:
allow_mutation = True
UNSET: Any = sentinel.UNSET # special sentinel object which used in sutuation when None might be a useful value

View file

@ -3,6 +3,7 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, Optional, Union
from ...utils import helper
from .base import TelegramObject
if TYPE_CHECKING: # pragma: no cover
@ -65,3 +66,26 @@ class ChatMember(TelegramObject):
inline bots"""
can_add_web_page_previews: Optional[bool] = None
"""Restricted only. True, if the user is allowed to add web page previews to their messages"""
@property
def is_chat_admin(self) -> bool:
return self.status in {ChatMemberStatus.CREATOR, ChatMemberStatus.ADMINISTRATOR}
@property
def is_chat_member(self) -> bool:
return self.status not in {ChatMemberStatus.LEFT, ChatMemberStatus.KICKED}
class ChatMemberStatus(helper.Helper):
"""
Chat member status
"""
mode = helper.HelperMode.lowercase
CREATOR = helper.Item() # creator
ADMINISTRATOR = helper.Item() # administrator
MEMBER = helper.Item() # member
RESTRICTED = helper.Item() # restricted
LEFT = helper.Item() # left
KICKED = helper.Item() # kicked

View file

@ -5,9 +5,7 @@ from .base import TelegramObject
class Dice(TelegramObject):
"""
This object represents a dice with a random value from 1 to 6 for currently supported base
emoji. (Yes, we're aware of the 'proper' singular of die. But it's awkward, and we decided to
help it change. One dice at a time!)
This object represents an animated emoji that displays a random value.
Source: https://core.telegram.org/bots/api#dice
"""
@ -15,7 +13,7 @@ class Dice(TelegramObject):
emoji: str
"""Emoji on which the dice throw animation is based"""
value: int
"""Value of the dice, 1-6 for currently supported base emoji"""
"""Value of the dice, 1-6 for '' and '' base emoji, 1-5 for '' base emoji"""
class DiceEmoji:

View file

@ -8,7 +8,7 @@ from .base import MutableTelegramObject
class ForceReply(MutableTelegramObject):
"""
Upon receiving a message with this object, Telegram clients will display a reply interface to
the user (act as if the user has selected the bots message and tapped Reply'). This can be
the user (act as if the user has selected the bot's message and tapped 'Reply'). This can be
extremely useful if you want to create user-friendly step-by-step interfaces without having to
sacrifice privacy mode.
Example: A poll bot for groups runs in privacy mode (only receives commands, replies to its
@ -16,19 +16,19 @@ class ForceReply(MutableTelegramObject):
Explain the user how to send a command with parameters (e.g. /newpoll question answer1
answer2). May be appealing for hardcore users but lacks modern day polish.
Guide the user through a step-by-step process. Please send me your question, Cool, now
lets add the first answer option, Great. Keep adding answer options, then send /done when
youre ready.
The last option is definitely more attractive. And if you use ForceReply in your bots
questions, it will receive the users answers even if it only receives replies, commands and
Guide the user through a step-by-step process. 'Please send me your question', 'Cool, now
let's add the first answer option', 'Great. Keep adding answer options, then send /done when
you're ready'.
The last option is definitely more attractive. And if you use ForceReply in your bot's
questions, it will receive the user's answers even if it only receives replies, commands and
mentions without any extra work for the user.
Source: https://core.telegram.org/bots/api#forcereply
"""
force_reply: bool
"""Shows reply interface to the user, as if they manually selected the bots message and
tapped Reply'"""
"""Shows reply interface to the user, as if they manually selected the bot's message and
tapped 'Reply'"""
selective: Optional[bool] = None
"""Use this parameter if you want to force reply from specific users only. Targets: 1) users
that are @mentioned in the text of the Message object; 2) if the bot's message is a reply

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING: # pragma: no cover
class GameHighScore(TelegramObject):
"""
This object represents one row of the high scores table for a game.
And thats about all weve got for now.
And that's about all we've got for now.
If you've got any questions, please check out our Bot FAQ
Source: https://core.telegram.org/bots/api#gamehighscore

View file

@ -28,11 +28,11 @@ class InlineKeyboardButton(MutableTelegramObject):
"""Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes"""
switch_inline_query: Optional[str] = None
"""If set, pressing the button will prompt the user to select one of their chats, open that
chat and insert the bots username and the specified inline query in the input field. Can
be empty, in which case just the bots username will be inserted."""
chat and insert the bot's username and the specified inline query in the input field. Can
be empty, in which case just the bot's username will be inserted."""
switch_inline_query_current_chat: Optional[str] = None
"""If set, pressing the button will insert the bots username and the specified inline query
in the current chats input field. Can be empty, in which case only the bot's username will
"""If set, pressing the button will insert the bot's username and the specified inline query
in the current chat's input field. Can be empty, in which case only the bot's username will
be inserted."""
callback_game: Optional[CallbackGame] = None
"""Description of the game that will be launched when the user presses the button."""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -32,7 +33,7 @@ class InlineQueryResultAudio(InlineQueryResult):
"""Title"""
caption: Optional[str] = None
"""Caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the audio caption. See formatting options for more details."""
performer: Optional[str] = None
"""Performer"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -30,7 +31,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
"""A valid file identifier for the audio file"""
caption: Optional[str] = None
"""Caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the audio caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -34,7 +35,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
"""Short description of the result"""
caption: Optional[str] = None
"""Caption of the document to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the document caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -30,7 +31,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
"""Title for the result"""
caption: Optional[str] = None
"""Caption of the GIF file to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -31,7 +32,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
"""Title for the result"""
caption: Optional[str] = None
"""Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -32,7 +33,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
"""Short description of the result"""
caption: Optional[str] = None
"""Caption of the photo to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the photo caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -32,7 +33,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
"""Short description of the result"""
caption: Optional[str] = None
"""Caption of the video to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the video caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -32,7 +33,7 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
"""Voice message title"""
caption: Optional[str] = None
"""Caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the voice message caption. See formatting options for more
details."""
reply_markup: Optional[InlineKeyboardMarkup] = None

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -35,7 +36,7 @@ class InlineQueryResultDocument(InlineQueryResult):
"""Mime type of the content of the file, either 'application/pdf' or 'application/zip'"""
caption: Optional[str] = None
"""Caption of the document to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the document caption. See formatting options for more details."""
description: Optional[str] = None
"""Short description of the result"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -27,18 +28,21 @@ class InlineQueryResultGif(InlineQueryResult):
gif_url: str
"""A valid URL for the GIF file. File size must not exceed 1MB"""
thumb_url: str
"""URL of the static thumbnail for the result (jpeg or gif)"""
"""URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result"""
gif_width: Optional[int] = None
"""Width of the GIF"""
gif_height: Optional[int] = None
"""Height of the GIF"""
gif_duration: Optional[int] = None
"""Duration of the GIF"""
thumb_mime_type: Optional[str] = None
"""MIME type of the thumbnail, must be one of 'image/jpeg', 'image/gif', or 'video/mp4'.
Defaults to 'image/jpeg'"""
title: Optional[str] = None
"""Title for the result"""
caption: Optional[str] = None
"""Caption of the GIF file to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -28,18 +29,21 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
mpeg4_url: str
"""A valid URL for the MP4 file. File size must not exceed 1MB"""
thumb_url: str
"""URL of the static thumbnail (jpeg or gif) for the result"""
"""URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result"""
mpeg4_width: Optional[int] = None
"""Video width"""
mpeg4_height: Optional[int] = None
"""Video height"""
mpeg4_duration: Optional[int] = None
"""Video duration"""
thumb_mime_type: Optional[str] = None
"""MIME type of the thumbnail, must be one of 'image/jpeg', 'image/gif', or 'video/mp4'.
Defaults to 'image/jpeg'"""
title: Optional[str] = None
"""Title for the result"""
caption: Optional[str] = None
"""Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -38,7 +39,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
"""Short description of the result"""
caption: Optional[str] = None
"""Caption of the photo to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the photo caption. See formatting options for more details."""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""Inline keyboard attached to the message"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -36,7 +37,7 @@ class InlineQueryResultVideo(InlineQueryResult):
"""Title for the result"""
caption: Optional[str] = None
"""Caption of the video to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the video caption. See formatting options for more details."""
video_width: Optional[int] = None
"""Video width"""

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
from pydantic import Field
from .base import UNSET
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING: # pragma: no cover
@ -33,7 +34,7 @@ class InlineQueryResultVoice(InlineQueryResult):
"""Recording title"""
caption: Optional[str] = None
"""Caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the voice message caption. See formatting options for more
details."""
voice_duration: Optional[int] = None

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union
from pydantic import Field
from .base import UNSET
from .input_media import InputMedia
if TYPE_CHECKING: # pragma: no cover
@ -27,13 +28,13 @@ class InputMediaAnimation(InputMedia):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
caption: Optional[str] = None
"""Caption of the animation to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the animation caption. See formatting options for more
details."""
width: Optional[int] = None

View file

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Union
from pydantic import Field
from .base import UNSET
from .input_media import InputMedia
if TYPE_CHECKING: # pragma: no cover
@ -27,13 +28,13 @@ class InputMediaAudio(InputMedia):
thumb: Optional[Union[InputFile, str]] = None
"""Thumbnail of the file sent; can be ignored if thumbnail generation for the file is
supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size.
A thumbnails width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails cant be reused and can be only uploaded as a new
A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded
using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new
file, so you can pass 'attach://<file_attach_name>' if the thumbnail was uploaded using
multipart/form-data under <file_attach_name>."""
caption: Optional[str] = None
"""Caption of the audio to be sent, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = None
parse_mode: Optional[str] = UNSET
"""Mode for parsing entities in the audio caption. See formatting options for more details."""
duration: Optional[int] = None
"""Duration of the audio in seconds"""

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