Significant perfomance improve about x10 more times. Replace pydantic to msgspec.

This commit is contained in:
mor 2023-05-11 13:20:55 +03:00
parent cf269e15f4
commit b1ba862539
141 changed files with 695 additions and 617 deletions

View file

@ -17,13 +17,15 @@ from typing import (
)
import certifi
import msgspec
from aiohttp import BasicAuth, ClientError, ClientSession, FormData, TCPConnector
from aiogram.methods import TelegramMethod
from ...exceptions import TelegramNetworkError
from ...methods.base import TelegramType
from ...types import InputFile
from ...types import UNSET_PARSE_MODE, InputFile
from ...types.base import UNSET_DISABLE_WEB_PAGE_PREVIEW, UNSET_PROTECT_CONTENT
from .base import BaseSession
if TYPE_CHECKING:
@ -121,7 +123,10 @@ class AiohttpSession(BaseSession):
await self.close()
if self._session is None or self._session.closed:
self._session = ClientSession(connector=self._connector_type(**self._connector_init))
self._session = ClientSession(
connector=self._connector_type(**self._connector_init),
json_serialize=self.json_dumps,
)
self._should_reset_connector = False
return self._session
@ -133,10 +138,12 @@ class AiohttpSession(BaseSession):
def build_form_data(self, bot: Bot, method: TelegramMethod[TelegramType]) -> FormData:
form = FormData(quote_fields=False)
files: Dict[str, InputFile] = {}
for key, value in method.dict().items():
value = self.prepare_value(value, bot=bot, files=files)
for key in method.__struct_fields__:
value = self.prepare_value(getattr(method, key), bot=bot, files=files)
if not value:
continue
if isinstance(value, bytes):
value = value.decode("utf-8")
form.add_field(key, value)
for key, value in files.items():
form.add_field(key, value, filename=value.filename or key)
@ -148,13 +155,30 @@ class AiohttpSession(BaseSession):
session = await self.create_session()
url = self.api.api_url(token=bot.token, method=method.__api_method__)
form = self.build_form_data(bot=bot, method=method)
def enc_hook(obj):
if obj is UNSET_PARSE_MODE:
return bot.parse_mode
if obj is UNSET_DISABLE_WEB_PAGE_PREVIEW:
return bot.disable_web_page_preview
if obj is UNSET_PROTECT_CONTENT:
return bot.protect_content
raise ValueError(f"Unknown object: {obj}")
headers = {}
try:
form = msgspec.json.encode(method, enc_hook=enc_hook)
headers = {"content-type": "application/json"}
except ValueError:
form = self.build_form_data(bot=bot, method=method)
try:
async with session.post(
url, data=form, timeout=self.timeout if timeout is None else timeout
url,
data=form,
headers=headers,
timeout=self.timeout if timeout is None else timeout,
) as resp:
raw_result = await resp.text()
raw_result = await resp.read()
except asyncio.TimeoutError:
raise TelegramNetworkError(method=method, message="Request timeout error")
except ClientError as e:

View file

@ -19,7 +19,7 @@ from typing import (
cast,
)
from pydantic import ValidationError
import msgspec
from aiogram.exceptions import (
ClientDecodeError,
@ -56,8 +56,8 @@ class BaseSession(abc.ABC):
def __init__(
self,
api: TelegramAPIServer = PRODUCTION,
json_loads: _JsonLoads = json.loads,
json_dumps: _JsonDumps = json.dumps,
json_loads: _JsonLoads = msgspec.json.decode,
json_dumps: _JsonDumps = msgspec.json.encode,
timeout: float = DEFAULT_TIMEOUT,
) -> None:
"""
@ -81,17 +81,12 @@ class BaseSession(abc.ABC):
Check response status
"""
try:
json_data = self.json_loads(content)
except Exception as e:
response = method.build_response(content)
except (msgspec.ValidationError, msgspec.DecodeError) as e:
# Handled error type can't be classified as specific error
# in due to decoder can be customized and raise any exception
raise ClientDecodeError("Failed to decode object", e, content)
try:
response = method.build_response(json_data)
except ValidationError as e:
raise ClientDecodeError("Failed to deserialize object", e, json_data)
raise ClientDecodeError("Failed to decode object", e, str(content))
if HTTPStatus.OK <= status_code <= HTTPStatus.IM_USED and response.ok:
return response
@ -175,7 +170,7 @@ class BaseSession(abc.ABC):
"""
Prepare value before send
"""
if value is None:
if value in (None, msgspec.UNSET):
return None
if isinstance(value, str):
return value

View file

@ -8,6 +8,8 @@ from asyncio import CancelledError, Event, Future, Lock
from contextlib import suppress
from typing import Any, AsyncGenerator, Dict, List, Optional, Union
import msgspec.json
from .. import loggers
from ..client.bot import Bot
from ..exceptions import TelegramAPIError
@ -167,7 +169,9 @@ class Dispatcher(Router):
)
Bot.reset_current(token)
async def feed_raw_update(self, bot: Bot, update: Dict[str, Any], **kwargs: Any) -> Any:
async def feed_raw_update(
self, bot: Bot, update: Union[str, Dict[str, Any]], **kwargs: Any
) -> Any:
"""
Main entry point for incoming updates with automatic Dict->Update serializer
@ -175,7 +179,10 @@ class Dispatcher(Router):
:param update:
:param kwargs:
"""
parsed_update = Update(**update)
if isinstance(update, dict):
parsed_update = msgspec.from_builtins(update, type=Update)
else:
parsed_update = msgspec.json.decode(update, type=Update)
return await self.feed_update(bot=bot, update=parsed_update, **kwargs)
@classmethod
@ -202,6 +209,7 @@ class Dispatcher(Router):
while True:
try:
updates = await bot(get_updates, **kwargs)
# print('updates:', updates)
except Exception as e:
failed = True
# In cases when Telegram Bot API was inaccessible don't need to stop polling
@ -364,10 +372,13 @@ class Dispatcher(Router):
raise
async def feed_webhook_update(
self, bot: Bot, update: Union[Update, Dict[str, Any]], _timeout: float = 55, **kwargs: Any
self, bot: Bot, update: Union[bytes, str, Update], _timeout: float = 55, **kwargs: Any
) -> Optional[TelegramMethod[TelegramType]]:
if not isinstance(update, Update): # Allow to use raw updates
update = Update(**update)
if isinstance(update, dict):
update = msgspec.from_builtins(update, type=Update)
else:
update = msgspec.json.decode(update, type=Update)
ctx = contextvars.copy_context()
loop = asyncio.get_running_loop()

View file

@ -172,11 +172,17 @@ class CallbackQueryFilter(Filter):
async def __call__(self, query: CallbackQuery) -> Union[Literal[False], Dict[str, Any]]:
if not isinstance(query, CallbackQuery) or not query.data:
return False
try:
callback_data = self.callback_data.unpack(query.data)
except (TypeError, ValueError):
prefix, *parts = query.data.split(self.callback_data.__separator__)
if prefix != self.callback_data.__prefix__:
return False
if self.rule is None or self.rule.resolve(callback_data):
return {"callback_data": callback_data}
if query._callback_data is None:
try:
query._callback_data = self.callback_data.unpack(query.data)
except (TypeError, ValueError):
return False
if query._callback_data is not None:
if self.rule is None or self.rule.resolve(query._callback_data):
return {"callback_data": query._callback_data}
return False

View file

@ -27,7 +27,7 @@ class StateFilter(Filter):
)
async def __call__(
self, obj: Union[TelegramObject], raw_state: Optional[str] = None
self, obj: Union[TelegramObject], raw_state: Optional[str] = None, **kwargs
) -> Union[bool, Dict[str, Any]]:
allowed_states = cast(Sequence[StateType], self.states)
for allowed_state in allowed_states:

View file

@ -1,8 +1,6 @@
from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from typing import List, Optional
from ..types import InlineQueryResult, InlineQueryResultsButton
from .base import TelegramMethod
@ -32,12 +30,12 @@ class AnswerInlineQuery(TelegramMethod[bool]):
"""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 don't support pagination. Offset length can't exceed 64 bytes."""
button: Optional[InlineQueryResultsButton] = None
"""A JSON-serialized object describing a button to be shown above inline query results"""
switch_pm_parameter: Optional[str] = Field(None, deprecated=True)
switch_pm_parameter: Optional[str] = None
"""`Deep-linking <https://core.telegram.org/bots/features#deep-linking>`_ parameter for the /start message sent to the bot when user presses the switch button. 1-64 characters, only :code:`A-Z`, :code:`a-z`, :code:`0-9`, :code:`_` and :code:`-` are allowed.
.. deprecated:: API:6.7
https://core.telegram.org/bots/api-changelog#april-21-2023"""
switch_pm_text: Optional[str] = Field(None, deprecated=True)
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 *switch_pm_parameter*
.. deprecated:: API:6.7

View file

@ -1,13 +1,22 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Dict, Generator, Generic, Optional, TypeVar
from typing import (
TYPE_CHECKING,
Any,
Dict,
Generator,
Generic,
Optional,
TypeVar,
Union,
)
from pydantic import BaseConfig, BaseModel, Extra, root_validator
from pydantic.generics import GenericModel
import msgspec
from aiogram.types import * # noqa
from ..types import InputFile, ResponseParameters
from ..types.base import UNSET_TYPE
if TYPE_CHECKING:
from ..client.bot import Bot
@ -15,44 +24,30 @@ if TYPE_CHECKING:
TelegramType = TypeVar("TelegramType", bound=Any)
class Request(BaseModel):
class Request(msgspec.Struct, weakref=True):
method: str
data: Dict[str, Optional[Any]]
files: Optional[Dict[str, InputFile]]
class Config(BaseConfig):
arbitrary_types_allowed = True
class Response(GenericModel, Generic[TelegramType]):
class Response(msgspec.Struct, Generic[TelegramType], weakref=True, kw_only=True):
ok: bool
result: Optional[TelegramType] = None
result: Optional[Union[Any, None]] = None
description: Optional[str] = None
error_code: Optional[int] = None
parameters: Optional[ResponseParameters] = None
class TelegramMethod(ABC, BaseModel, Generic[TelegramType]):
class Config(BaseConfig):
# use_enum_values = True
extra = Extra.allow
allow_population_by_field_name = True
arbitrary_types_allowed = True
orm_mode = True
smart_union = True # https://github.com/aiogram/aiogram/issues/901
@root_validator(pre=True)
def remove_unset(cls, values: Dict[str, Any]) -> Dict[str, Any]:
"""
Remove UNSET 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.
"""
return {k: v for k, v in values.items() if not isinstance(v, UNSET_TYPE)}
class TelegramMethod(
msgspec.Struct,
Generic[TelegramType],
omit_defaults=True,
weakref=True,
kw_only=True,
forbid_unknown_fields=False,
):
method: str = msgspec.UNSET
@property
@abstractmethod
@ -64,15 +59,13 @@ class TelegramMethod(ABC, BaseModel, Generic[TelegramType]):
def __api_method__(self) -> str:
pass
def dict(self, **kwargs: Any) -> Any:
# override dict of pydantic.BaseModel to overcome exporting request_timeout field
exclude = kwargs.pop("exclude", set())
return super().dict(exclude=exclude, **kwargs)
def build_response(self, data: Dict[str, Any]) -> Response[TelegramType]:
def build_response(self, data: Union[str, bytes, Dict[str, Any]]) -> Response[TelegramType]:
# noinspection PyTypeChecker
return Response[self.__returning__](**data) # type: ignore
if isinstance(data, (bytes, str)):
data = msgspec.json.decode(data)
if "result" in data:
data["result"] = msgspec.from_builtins(data["result"], type=self.__returning__)
return msgspec.from_builtins(data, type=Response)
async def emit(self, bot: Bot) -> TelegramType:
return await bot(self)

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -35,13 +37,13 @@ class CopyMessage(TelegramMethod[MessageId]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
caption: Optional[str] = None
"""New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept"""
parse_mode: Optional[str] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the new caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the new caption, which can be specified instead of *parse_mode*"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import UNSET_PARSE_MODE, InlineKeyboardMarkup, Message, MessageEntity
from .base import TelegramMethod
@ -24,7 +26,7 @@ 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] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the message caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import UNSET_PARSE_MODE, InlineKeyboardMarkup, Message, MessageEntity
from ..types.base import UNSET_DISABLE_WEB_PAGE_PREVIEW
from .base import TelegramMethod
@ -25,11 +27,13 @@ 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] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the message text. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in message text, which can be specified instead of *parse_mode*"""
disable_web_page_preview: Optional[bool] = UNSET_DISABLE_WEB_PAGE_PREVIEW
disable_web_page_preview: Optional[bool] = msgspec.field(
default_factory=lambda: UNSET_DISABLE_WEB_PAGE_PREVIEW
)
"""Disables link previews for links in this message"""
reply_markup: Optional[InlineKeyboardMarkup] = None
"""A JSON-serialized object for an `inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_."""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
import msgspec
from ..types import Message
from ..types.base import UNSET_PROTECT_CONTENT
from .base import TelegramMethod
@ -27,5 +29,5 @@ class ForwardMessage(TelegramMethod[Message]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the forwarded message from forwarding and saving"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -42,7 +44,7 @@ class SendAnimation(TelegramMethod[Message]):
"""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 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>. :ref:`More information on Sending Files » <sending-files>`"""
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] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the animation caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
@ -50,7 +52,7 @@ class SendAnimation(TelegramMethod[Message]):
"""Pass :code:`True` if the animation needs to be covered with a spoiler animation"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -1,6 +1,8 @@
from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
from typing import List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
@ -35,7 +37,7 @@ class SendAudio(TelegramMethod[Message]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
caption: Optional[str] = None
"""Audio caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the audio caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
@ -49,7 +51,7 @@ class SendAudio(TelegramMethod[Message]):
"""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 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>. :ref:`More information on Sending Files » <sending-files>`"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -1,6 +1,8 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
from typing import Optional, Union
import msgspec
from ..types import (
ForceReply,
@ -37,7 +39,7 @@ class SendContact(TelegramMethod[Message]):
"""Additional data about the contact in the form of a `vCard <https://en.wikipedia.org/wiki/VCard>`_, 0-2048 bytes"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -1,6 +1,8 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
from typing import Optional, Union
import msgspec
from ..types import (
ForceReply,
@ -31,7 +33,7 @@ class SendDice(TelegramMethod[Message]):
"""Emoji on which the dice throw animation is based. Currently, must be one of '🎲', '🎯', '🏀', '', '🎳', or '🎰'. Dice can have values 1-6 for '🎲', '🎯' and '🎳', values 1-5 for '🏀' and '', and values 1-64 for '🎰'. Defaults to '🎲'"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -36,7 +38,7 @@ class SendDocument(TelegramMethod[Message]):
"""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 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>. :ref:`More information on Sending Files » <sending-files>`"""
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] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the document caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
@ -44,7 +46,7 @@ class SendDocument(TelegramMethod[Message]):
"""Disables automatic server-side content type detection for files uploaded using multipart/form-data"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
import msgspec
from ..types import InlineKeyboardMarkup, Message
from ..types.base import UNSET_PROTECT_CONTENT
from .base import TelegramMethod
@ -25,7 +27,7 @@ class SendGame(TelegramMethod[Message]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import InlineKeyboardMarkup, LabeledPrice, Message
from ..types.base import UNSET_PROTECT_CONTENT
from .base import TelegramMethod
@ -65,7 +67,7 @@ class SendInvoice(TelegramMethod[Message]):
"""Pass :code:`True` if the final price depends on the shipping method"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
import msgspec
from ..types import (
ForceReply,
InlineKeyboardMarkup,
@ -41,7 +43,7 @@ class SendLocation(TelegramMethod[Message]):
"""For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified."""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
InputMediaAudio,
InputMediaDocument,
@ -31,7 +33,7 @@ class SendMediaGroup(TelegramMethod[List[Message]]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
disable_notification: Optional[bool] = None
"""Sends messages `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent messages from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the messages are a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -31,15 +33,17 @@ class SendMessage(TelegramMethod[Message]):
"""Text of the message to be sent, 1-4096 characters after entities parsing"""
message_thread_id: Optional[int] = None
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
parse_mode: Optional[str] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the message text. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in message text, which can be specified instead of *parse_mode*"""
disable_web_page_preview: Optional[bool] = UNSET_DISABLE_WEB_PAGE_PREVIEW
disable_web_page_preview: Optional[bool] = msgspec.field(
default_factory=lambda: UNSET_DISABLE_WEB_PAGE_PREVIEW
)
"""Disables link previews for links in this message"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -34,7 +36,7 @@ class SendPhoto(TelegramMethod[Message]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
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] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the photo caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
@ -42,7 +44,7 @@ class SendPhoto(TelegramMethod[Message]):
"""Pass :code:`True` if the photo needs to be covered with a spoiler animation"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -3,6 +3,8 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -44,7 +46,7 @@ class SendPoll(TelegramMethod[Message]):
"""0-based identifier of the correct answer option, required for polls in quiz mode"""
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] = UNSET_PARSE_MODE
explanation_parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the explanation. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
explanation_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the poll explanation, which can be specified instead of *parse_mode*"""
@ -56,7 +58,7 @@ class SendPoll(TelegramMethod[Message]):
"""Pass :code:`True` if the poll needs to be immediately closed. This can be useful for poll preview."""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
import msgspec
from ..types import (
ForceReply,
InlineKeyboardMarkup,
@ -34,7 +36,7 @@ class SendSticker(TelegramMethod[Message]):
"""Emoji associated with the sticker; only for just uploaded stickers"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
import msgspec
from ..types import (
ForceReply,
InlineKeyboardMarkup,
@ -45,7 +47,7 @@ class SendVenue(TelegramMethod[Message]):
"""Google Places type of the venue. (See `supported types <https://developers.google.com/places/web-service/supported_types>`_.)"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -42,7 +44,7 @@ class SendVideo(TelegramMethod[Message]):
"""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 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>. :ref:`More information on Sending Files » <sending-files>`"""
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] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the video caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
@ -52,7 +54,7 @@ class SendVideo(TelegramMethod[Message]):
"""Pass :code:`True` if the uploaded video is suitable for streaming"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
import msgspec
from ..types import (
ForceReply,
InlineKeyboardMarkup,
@ -38,7 +40,7 @@ class SendVideoNote(TelegramMethod[Message]):
"""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 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>. :ref:`More information on Sending Files » <sending-files>`"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -2,6 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
import msgspec
from ..types import (
UNSET_PARSE_MODE,
ForceReply,
@ -34,7 +36,7 @@ class SendVoice(TelegramMethod[Message]):
"""Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"""
caption: Optional[str] = None
"""Voice message caption, 0-1024 characters after entities parsing"""
parse_mode: Optional[str] = UNSET_PARSE_MODE
parse_mode: Optional[str] = msgspec.field(default_factory=lambda: UNSET_PARSE_MODE)
"""Mode for parsing entities in the voice message caption. See `formatting options <https://core.telegram.org/bots/api#formatting-options>`_ for more details."""
caption_entities: Optional[List[MessageEntity]] = None
"""A JSON-serialized list of special entities that appear in the caption, which can be specified instead of *parse_mode*"""
@ -42,7 +44,7 @@ class SendVoice(TelegramMethod[Message]):
"""Duration of the voice message in seconds"""
disable_notification: Optional[bool] = None
"""Sends the message `silently <https://telegram.org/blog/channels-2-0#silent-messages>`_. Users will receive a notification with no sound."""
protect_content: Optional[bool] = UNSET_PROTECT_CONTENT
protect_content: Optional[bool] = msgspec.field(default_factory=lambda: UNSET_PROTECT_CONTENT)
"""Protects the contents of the sent message from forwarding and saving"""
reply_to_message_id: Optional[int] = None
"""If the message is a reply, ID of the original message"""

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .photo_size import PhotoSize
from .photo_size import PhotoSize
class Animation(TelegramObject):

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .photo_size import PhotoSize
from .photo_size import PhotoSize
class Audio(TelegramObject):

View file

@ -1,26 +1,19 @@
import datetime
from typing import Any
from unittest.mock import sentinel
from pydantic import BaseModel, Extra
import msgspec
from aiogram.utils.mixins import ContextInstanceMixin
class TelegramObject(ContextInstanceMixin["TelegramObject"], BaseModel):
class Config:
use_enum_values = True
orm_mode = True
extra = Extra.allow
validate_assignment = True
allow_mutation = False
allow_population_by_field_name = True
json_encoders = {datetime.datetime: lambda dt: int(dt.timestamp())}
class TelegramObject(
ContextInstanceMixin["TelegramObject"], msgspec.Struct, omit_defaults=True, weakref=True
):
...
class MutableTelegramObject(TelegramObject):
class Config:
allow_mutation = True
...
# special sentinel object which used in situation when None might be a useful value

View file

@ -1,17 +1,17 @@
from __future__ import annotations
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeAllChatAdministrators(BotCommandScope):
class BotCommandScopeAllChatAdministrators(BotCommandScope, kw_only=True):
"""
Represents the `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands, covering all group and supergroup chat administrators.
Source: https://core.telegram.org/bots/api#botcommandscopeallchatadministrators
"""
type: str = Field(BotCommandScopeType.ALL_CHAT_ADMINISTRATORS, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.ALL_CHAT_ADMINISTRATORS)
"""Scope type, must be *all_chat_administrators*"""

View file

@ -1,17 +1,17 @@
from __future__ import annotations
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeAllGroupChats(BotCommandScope):
class BotCommandScopeAllGroupChats(BotCommandScope, kw_only=True):
"""
Represents the `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands, covering all group and supergroup chats.
Source: https://core.telegram.org/bots/api#botcommandscopeallgroupchats
"""
type: str = Field(BotCommandScopeType.ALL_GROUP_CHATS, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.ALL_GROUP_CHATS)
"""Scope type, must be *all_group_chats*"""

View file

@ -1,17 +1,17 @@
from __future__ import annotations
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeAllPrivateChats(BotCommandScope):
class BotCommandScopeAllPrivateChats(BotCommandScope, kw_only=True):
"""
Represents the `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands, covering all private chats.
Source: https://core.telegram.org/bots/api#botcommandscopeallprivatechats
"""
type: str = Field(BotCommandScopeType.ALL_PRIVATE_CHATS, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.ALL_PRIVATE_CHATS)
"""Scope type, must be *all_private_chats*"""

View file

@ -2,20 +2,20 @@ from __future__ import annotations
from typing import Union
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeChat(BotCommandScope):
class BotCommandScopeChat(BotCommandScope, kw_only=True):
"""
Represents the `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands, covering a specific chat.
Source: https://core.telegram.org/bots/api#botcommandscopechat
"""
type: str = Field(BotCommandScopeType.CHAT, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.CHAT)
"""Scope type, must be *chat*"""
chat_id: Union[int, str]
"""Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)"""

View file

@ -2,20 +2,20 @@ from __future__ import annotations
from typing import Union
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeChatAdministrators(BotCommandScope):
class BotCommandScopeChatAdministrators(BotCommandScope, kw_only=True):
"""
Represents the `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands, covering all administrators of a specific group or supergroup chat.
Source: https://core.telegram.org/bots/api#botcommandscopechatadministrators
"""
type: str = Field(BotCommandScopeType.CHAT_ADMINISTRATORS, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.CHAT_ADMINISTRATORS)
"""Scope type, must be *chat_administrators*"""
chat_id: Union[int, str]
"""Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)"""

View file

@ -2,20 +2,20 @@ from __future__ import annotations
from typing import Union
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeChatMember(BotCommandScope):
class BotCommandScopeChatMember(BotCommandScope, kw_only=True):
"""
Represents the `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands, covering a specific member of a group or supergroup chat.
Source: https://core.telegram.org/bots/api#botcommandscopechatmember
"""
type: str = Field(BotCommandScopeType.CHAT_MEMBER, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.CHAT_MEMBER)
"""Scope type, must be *chat_member*"""
chat_id: Union[int, str]
"""Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)"""

View file

@ -1,17 +1,17 @@
from __future__ import annotations
from pydantic import Field
import msgspec
from ..enums import BotCommandScopeType
from .bot_command_scope import BotCommandScope
class BotCommandScopeDefault(BotCommandScope):
class BotCommandScopeDefault(BotCommandScope, kw_only=True):
"""
Represents the default `scope <https://core.telegram.org/bots/api#botcommandscope>`_ of bot commands. Default commands are used if no commands with a `narrower scope <https://core.telegram.org/bots/api#determining-list-of-commands>`_ are specified for the user.
Source: https://core.telegram.org/bots/api#botcommandscopedefault
"""
type: str = Field(BotCommandScopeType.DEFAULT, const=True)
type: str = msgspec.field(default_factory=lambda: BotCommandScopeType.DEFAULT)
"""Scope type, must be *default*"""

View file

@ -1,18 +1,18 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any, ClassVar, Optional
from pydantic import Field
import msgspec
from .base import TelegramObject
if TYPE_CHECKING:
from ..methods import AnswerCallbackQuery
from .message import Message
from .user import User
from .message import Message
from .user import User
class CallbackQuery(TelegramObject):
class CallbackQuery(TelegramObject, kw_only=True):
"""
This object represents an incoming callback query from a callback button in an `inline keyboard <https://core.telegram.org/bots/features#inline-keyboards>`_. If the button that originated the query was attached to a message sent by the bot, the field *message* will be present. If the button was attached to a message sent via the bot (in `inline mode <https://core.telegram.org/bots/api#inline-mode>`_), the field *inline_message_id* will be present. Exactly one of the fields *data* or *game_short_name* will be present.
@ -23,7 +23,7 @@ class CallbackQuery(TelegramObject):
id: str
"""Unique identifier for this query"""
from_user: User = Field(..., alias="from")
from_user: User = msgspec.field(name="from")
"""Sender"""
chat_instance: str
"""Global identifier, uniquely corresponding to the chat to which the message with the callback button was sent. Useful for high scores in :class:`aiogram.methods.games.Games`."""
@ -36,6 +36,8 @@ class CallbackQuery(TelegramObject):
game_short_name: Optional[str] = None
"""*Optional*. Short name of a `Game <https://core.telegram.org/bots/api#games>`_ to be returned, serves as the unique identifier for the game"""
_callback_data = None
def answer(
self,
text: Optional[str] = None,

View file

@ -35,12 +35,14 @@ if TYPE_CHECKING:
UnpinAllChatMessages,
UnpinChatMessage,
)
from .chat_location import ChatLocation
from .chat_permissions import ChatPermissions
from .chat_photo import ChatPhoto
from .input_file import InputFile
from .message import Message
from . import message
from .chat_location import ChatLocation
from .chat_permissions import ChatPermissions
from .chat_photo import ChatPhoto
from .input_file import InputFile
class Chat(TelegramObject):
"""
@ -83,7 +85,7 @@ class Chat(TelegramObject):
"""*Optional*. Description, for groups, supergroups and channel chats. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
invite_link: Optional[str] = None
"""*Optional*. Primary invite link, for groups, supergroups and channel chats. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
pinned_message: Optional[Message] = None
pinned_message: Optional[message.Message] = None
"""*Optional*. The most recent pinned message (by sending date). Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
permissions: Optional[ChatPermissions] = None
"""*Optional*. Default chat member permissions, for groups and supergroups. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""

View file

@ -4,9 +4,7 @@ import datetime
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatInviteLink(TelegramObject):

View file

@ -3,20 +3,19 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, Any, Optional
from pydantic import Field
import msgspec
from .base import TelegramObject
if TYPE_CHECKING:
from ..methods import ApproveChatJoinRequest, DeclineChatJoinRequest
if TYPE_CHECKING:
from .chat import Chat
from .chat_invite_link import ChatInviteLink
from .user import User
from .chat import Chat
from .chat_invite_link import ChatInviteLink
from .user import User
class ChatJoinRequest(TelegramObject):
class ChatJoinRequest(TelegramObject, kw_only=True):
"""
Represents a join request sent to a chat.
@ -25,7 +24,7 @@ class ChatJoinRequest(TelegramObject):
chat: Chat
"""Chat to which the request was sent"""
from_user: User = Field(..., alias="from")
from_user: User = msgspec.field(name="from")
"""User that sent the join request"""
user_chat_id: int
"""Identifier of a private chat with the user who sent the join request. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a 64-bit integer or double-precision float type are safe for storing this identifier. The bot can use this identifier for 24 hours to send messages until the join request is processed, assuming no other administrator contacted the user."""

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from .base import TelegramObject
if TYPE_CHECKING:
from .location import Location
from .location import Location
class ChatLocation(TelegramObject):

View file

@ -4,9 +4,7 @@ import datetime
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMember(TelegramObject):

View file

@ -2,23 +2,19 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
from ..enums import ChatMemberStatus
from .chat_member import ChatMember
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMemberAdministrator(ChatMember):
class ChatMemberAdministrator(ChatMember, kw_only=True, tag=True):
"""
Represents a `chat member <https://core.telegram.org/bots/api#chatmember>`_ that has some additional privileges.
Source: https://core.telegram.org/bots/api#chatmemberadministrator
"""
status: str = Field(ChatMemberStatus.ADMINISTRATOR, const=True)
status: str = ChatMemberStatus.ADMINISTRATOR
"""The member's status in the chat, always 'administrator'"""
user: User
"""Information about the user"""

View file

@ -3,23 +3,19 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING
from pydantic import Field
from ..enums import ChatMemberStatus
from .chat_member import ChatMember
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMemberBanned(ChatMember):
class ChatMemberBanned(ChatMember, kw_only=True, tag=True):
"""
Represents a `chat member <https://core.telegram.org/bots/api#chatmember>`_ that was banned in the chat and can't return to the chat or view chat messages.
Source: https://core.telegram.org/bots/api#chatmemberbanned
"""
status: str = Field(ChatMemberStatus.KICKED, const=True)
status: str = ChatMemberStatus.KICKED
"""The member's status in the chat, always 'kicked'"""
user: User
"""Information about the user"""

View file

@ -2,23 +2,19 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from pydantic import Field
from ..enums import ChatMemberStatus
from .chat_member import ChatMember
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMemberLeft(ChatMember):
class ChatMemberLeft(ChatMember, kw_only=True, tag=True):
"""
Represents a `chat member <https://core.telegram.org/bots/api#chatmember>`_ that isn't currently a member of the chat, but may join it themselves.
Source: https://core.telegram.org/bots/api#chatmemberleft
"""
status: str = Field(ChatMemberStatus.LEFT, const=True)
status: str = ChatMemberStatus.LEFT
"""The member's status in the chat, always 'left'"""
user: User
"""Information about the user"""

View file

@ -2,23 +2,19 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from pydantic import Field
from ..enums import ChatMemberStatus
from .chat_member import ChatMember
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMemberMember(ChatMember):
class ChatMemberMember(ChatMember, kw_only=True, tag=True):
"""
Represents a `chat member <https://core.telegram.org/bots/api#chatmember>`_ that has no additional privileges or restrictions.
Source: https://core.telegram.org/bots/api#chatmembermember
"""
status: str = Field(ChatMemberStatus.MEMBER, const=True)
status: str = ChatMemberStatus.MEMBER
"""The member's status in the chat, always 'member'"""
user: User
"""Information about the user"""

View file

@ -2,23 +2,19 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
from ..enums import ChatMemberStatus
from .chat_member import ChatMember
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMemberOwner(ChatMember):
class ChatMemberOwner(ChatMember, kw_only=True, tag=True):
"""
Represents a `chat member <https://core.telegram.org/bots/api#chatmember>`_ that owns the chat and has all administrator privileges.
Source: https://core.telegram.org/bots/api#chatmemberowner
"""
status: str = Field(ChatMemberStatus.CREATOR, const=True)
status: str = ChatMemberStatus.CREATOR
"""The member's status in the chat, always 'creator'"""
user: User
"""Information about the user"""

View file

@ -3,23 +3,19 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING
from pydantic import Field
from ..enums import ChatMemberStatus
from .chat_member import ChatMember
if TYPE_CHECKING:
from .user import User
from .user import User
class ChatMemberRestricted(ChatMember):
class ChatMemberRestricted(ChatMember, kw_only=True, tag=True):
"""
Represents a `chat member <https://core.telegram.org/bots/api#chatmember>`_ that is under certain restrictions in the chat. Supergroups only.
Source: https://core.telegram.org/bots/api#chatmemberrestricted
"""
status: str = Field(ChatMemberStatus.RESTRICTED, const=True)
status: str = ChatMemberStatus.RESTRICTED
"""The member's status in the chat, always 'restricted'"""
user: User
"""Information about the user"""

View file

@ -3,23 +3,21 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, Optional, Union
from pydantic import Field
import msgspec
from .base import TelegramObject
if TYPE_CHECKING:
from .chat import Chat
from .chat_invite_link import ChatInviteLink
from .chat_member_administrator import ChatMemberAdministrator
from .chat_member_banned import ChatMemberBanned
from .chat_member_left import ChatMemberLeft
from .chat_member_member import ChatMemberMember
from .chat_member_owner import ChatMemberOwner
from .chat_member_restricted import ChatMemberRestricted
from .user import User
from .chat import Chat
from .chat_invite_link import ChatInviteLink
from .chat_member_administrator import ChatMemberAdministrator
from .chat_member_banned import ChatMemberBanned
from .chat_member_left import ChatMemberLeft
from .chat_member_member import ChatMemberMember
from .chat_member_owner import ChatMemberOwner
from .chat_member_restricted import ChatMemberRestricted
from .user import User
class ChatMemberUpdated(TelegramObject):
class ChatMemberUpdated(TelegramObject, kw_only=True):
"""
This object represents changes in the status of a chat member.
@ -28,7 +26,7 @@ class ChatMemberUpdated(TelegramObject):
chat: Chat
"""Chat the user belongs to"""
from_user: User = Field(..., alias="from")
from_user: User = msgspec.field(name="from")
"""Performer of the action, which resulted in the change"""
date: datetime.datetime
"""Date the change was done in Unix time"""

View file

@ -2,16 +2,14 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
import msgspec
from .base import TelegramObject
if TYPE_CHECKING:
from .location import Location
from .user import User
from .location import Location
from .user import User
class ChosenInlineResult(TelegramObject):
class ChosenInlineResult(TelegramObject, kw_only=True):
"""
Represents a `result <https://core.telegram.org/bots/api#inlinequeryresult>`_ of an inline query that was chosen by the user and sent to their chat partner.
**Note:** It is necessary to enable `inline feedback <https://core.telegram.org/bots/inline#collecting-feedback>`_ via `@BotFather <https://t.me/botfather>`_ in order to receive these objects in updates.
@ -21,7 +19,7 @@ class ChosenInlineResult(TelegramObject):
result_id: str
"""The unique identifier for the result that was chosen"""
from_user: User = Field(..., alias="from")
from_user: User = msgspec.field(name="from")
"""The user that chose the result"""
query: str
"""The query that was used to obtain the result"""

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .photo_size import PhotoSize
from .photo_size import PhotoSize
class Document(TelegramObject):

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .passport_file import PassportFile
from .passport_file import PassportFile
class EncryptedPassportElement(TelegramObject):

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import Optional
from pydantic import Field
from .base import MutableTelegramObject
@ -21,7 +19,7 @@ class ForceReply(MutableTelegramObject):
Source: https://core.telegram.org/bots/api#forcereply
"""
force_reply: bool = Field(True, const=True)
force_reply: bool = True
"""Shows reply interface to the user, as if they manually selected the bot's message and tapped 'Reply'"""
input_field_placeholder: Optional[str] = None
"""*Optional*. The placeholder to be shown in the input field when the reply is active; 1-64 characters"""

View file

@ -2,12 +2,10 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from .animation import Animation
from .base import TelegramObject
if TYPE_CHECKING:
from .animation import Animation
from .message_entity import MessageEntity
from .photo_size import PhotoSize
from .message_entity import MessageEntity
from .photo_size import PhotoSize
class Game(TelegramObject):

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from .base import TelegramObject
if TYPE_CHECKING:
from .user import User
from .user import User
class GameHighScore(TelegramObject):

View file

@ -3,12 +3,10 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import MutableTelegramObject
if TYPE_CHECKING:
from .callback_game import CallbackGame
from .login_url import LoginUrl
from .switch_inline_query_chosen_chat import SwitchInlineQueryChosenChat
from .web_app_info import WebAppInfo
from .callback_game import CallbackGame
from .login_url import LoginUrl
from .switch_inline_query_chosen_chat import SwitchInlineQueryChosenChat
from .web_app_info import WebAppInfo
class InlineKeyboardButton(MutableTelegramObject):

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List
from .base import MutableTelegramObject
if TYPE_CHECKING:
from .inline_keyboard_button import InlineKeyboardButton
from .inline_keyboard_button import InlineKeyboardButton
class InlineKeyboardMarkup(MutableTelegramObject):

View file

@ -2,19 +2,19 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Any, List, Optional
from pydantic import Field
import msgspec
from .base import TelegramObject
if TYPE_CHECKING:
from ..methods import AnswerInlineQuery
from .inline_query_result import InlineQueryResult
from .inline_query_results_button import InlineQueryResultsButton
from .location import Location
from .user import User
from .inline_query_result import InlineQueryResult
from .inline_query_results_button import InlineQueryResultsButton
from .location import Location
from .user import User
class InlineQuery(TelegramObject):
class InlineQuery(TelegramObject, kw_only=True):
"""
This object represents an incoming inline query. When the user sends an empty query, your bot could return some default or trending results.
@ -23,7 +23,7 @@ class InlineQuery(TelegramObject):
id: str
"""Unique identifier for this query"""
from_user: User = Field(..., alias="from")
from_user: User = msgspec.field(name="from")
"""Sender"""
query: str
"""Text of the query (up to 256 characters)"""

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
import msgspec
from ..enums import InlineQueryResultType
from .inline_query_result import InlineQueryResult
@ -12,14 +12,14 @@ if TYPE_CHECKING:
from .input_message_content import InputMessageContent
class InlineQueryResultArticle(InlineQueryResult):
class InlineQueryResultArticle(InlineQueryResult, kw_only=True):
"""
Represents a link to an article or web page.
Source: https://core.telegram.org/bots/api#inlinequeryresultarticle
"""
type: str = Field(InlineQueryResultType.ARTICLE, const=True)
type: str = msgspec.field(default_factory=lambda: InlineQueryResultType.ARTICLE)
"""Type of the result, must be *article*"""
id: str
"""Unique identifier for this result, 1-64 Bytes"""

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
import msgspec
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
@ -14,7 +14,7 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultAudio(InlineQueryResult):
class InlineQueryResultAudio(InlineQueryResult, kw_only=True):
"""
Represents a link to an MP3 audio file. By default, this audio file will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the audio.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -22,7 +22,7 @@ class InlineQueryResultAudio(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultaudio
"""
type: str = Field(InlineQueryResultType.AUDIO, const=True)
type: str = msgspec.field(default_factory=lambda: InlineQueryResultType.AUDIO)
"""Type of the result, must be *audio*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
import msgspec
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
@ -14,7 +14,7 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedAudio(InlineQueryResult):
class InlineQueryResultCachedAudio(InlineQueryResult, kw_only=True):
"""
Represents a link to an MP3 audio file stored on the Telegram servers. By default, this audio file will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the audio.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -22,7 +22,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedaudio
"""
type: str = Field(InlineQueryResultType.AUDIO, const=True)
type: str = msgspec.field(default_factory=lambda: InlineQueryResultType.AUDIO)
"""Type of the result, must be *audio*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,7 +12,7 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedDocument(InlineQueryResult):
class InlineQueryResultCachedDocument(InlineQueryResult, kw_only=True):
"""
Represents a link to a file stored on the Telegram servers. By default, this file will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the file.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -22,7 +20,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultcacheddocument
"""
type: str = Field(InlineQueryResultType.DOCUMENT, const=True)
type: str = InlineQueryResultType.DOCUMENT
"""Type of the result, must be *document*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedGif(InlineQueryResult):
class InlineQueryResultCachedGif(InlineQueryResult, kw_only=True):
"""
Represents a link to an animated GIF file stored on the Telegram servers. By default, this animated GIF file will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with specified content instead of the animation.
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedgif
"""
type: str = Field(InlineQueryResultType.GIF, const=True)
type: str = InlineQueryResultType.GIF
"""Type of the result, must be *gif*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
class InlineQueryResultCachedMpeg4Gif(InlineQueryResult, kw_only=True):
"""
Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) stored on the Telegram servers. By default, this animated MPEG-4 file will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the animation.
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedmpeg4gif
"""
type: str = Field(InlineQueryResultType.MPEG4_GIF, const=True)
type: str = InlineQueryResultType.MPEG4_GIF
"""Type of the result, must be *mpeg4_gif*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedPhoto(InlineQueryResult):
class InlineQueryResultCachedPhoto(InlineQueryResult, kw_only=True):
"""
Represents a link to a photo stored on the Telegram servers. By default, this photo will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the photo.
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedphoto
"""
type: str = Field(InlineQueryResultType.PHOTO, const=True)
type: str = InlineQueryResultType.PHOTO
"""Type of the result, must be *photo*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .inline_query_result import InlineQueryResult
@ -12,7 +10,7 @@ if TYPE_CHECKING:
from .input_message_content import InputMessageContent
class InlineQueryResultCachedSticker(InlineQueryResult):
class InlineQueryResultCachedSticker(InlineQueryResult, kw_only=True):
"""
Represents a link to a sticker stored on the Telegram servers. By default, this sticker will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the sticker.
**Note:** This will only work in Telegram versions released after 9 April, 2016 for static stickers and after 06 July, 2019 for `animated stickers <https://telegram.org/blog/animated-stickers>`_. Older clients will ignore them.
@ -20,7 +18,7 @@ class InlineQueryResultCachedSticker(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedsticker
"""
type: str = Field(InlineQueryResultType.STICKER, const=True)
type: str = InlineQueryResultType.STICKER
"""Type of the result, must be *sticker*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedVideo(InlineQueryResult):
class InlineQueryResultCachedVideo(InlineQueryResult, kw_only=True):
"""
Represents a link to a video file stored on the Telegram servers. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the video.
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedvideo
"""
type: str = Field(InlineQueryResultType.VIDEO, const=True)
type: str = InlineQueryResultType.VIDEO
"""Type of the result, must be *video*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,7 +12,7 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultCachedVoice(InlineQueryResult):
class InlineQueryResultCachedVoice(InlineQueryResult, kw_only=True):
"""
Represents a link to a voice message stored on the Telegram servers. By default, this voice message will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the voice message.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -22,7 +20,7 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultcachedvoice
"""
type: str = Field(InlineQueryResultType.VOICE, const=True)
type: str = InlineQueryResultType.VOICE
"""Type of the result, must be *voice*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .inline_query_result import InlineQueryResult
@ -12,7 +10,7 @@ if TYPE_CHECKING:
from .input_message_content import InputMessageContent
class InlineQueryResultContact(InlineQueryResult):
class InlineQueryResultContact(InlineQueryResult, kw_only=True):
"""
Represents a contact with a phone number. By default, this contact will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the contact.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -20,7 +18,7 @@ class InlineQueryResultContact(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultcontact
"""
type: str = Field(InlineQueryResultType.CONTACT, const=True)
type: str = InlineQueryResultType.CONTACT
"""Type of the result, must be *contact*"""
id: str
"""Unique identifier for this result, 1-64 Bytes"""

View file

@ -2,19 +2,17 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
import msgspec
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_keyboard_markup import InlineKeyboardMarkup
from .inline_query_result import InlineQueryResult
if TYPE_CHECKING:
from .inline_keyboard_markup import InlineKeyboardMarkup
from .input_message_content import InputMessageContent
from .message_entity import MessageEntity
from .input_message_content import InputMessageContent
from .message_entity import MessageEntity
class InlineQueryResultDocument(InlineQueryResult):
class InlineQueryResultDocument(InlineQueryResult, kw_only=True):
"""
Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the file. Currently, only **.PDF** and **.ZIP** files can be sent using this method.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -22,7 +20,7 @@ class InlineQueryResultDocument(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultdocument
"""
type: str = Field(InlineQueryResultType.DOCUMENT, const=True)
type: str = msgspec.field(default_factory=lambda: InlineQueryResultType.DOCUMENT)
"""Type of the result, must be *document*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .inline_query_result import InlineQueryResult
@ -11,7 +9,7 @@ if TYPE_CHECKING:
from .inline_keyboard_markup import InlineKeyboardMarkup
class InlineQueryResultGame(InlineQueryResult):
class InlineQueryResultGame(InlineQueryResult, kw_only=True):
"""
Represents a `Game <https://core.telegram.org/bots/api#games>`_.
**Note:** This will only work in Telegram versions released after October 1, 2016. Older clients will not display any inline results if a game result is among them.
@ -19,7 +17,7 @@ class InlineQueryResultGame(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultgame
"""
type: str = Field(InlineQueryResultType.GAME, const=True)
type: str = InlineQueryResultType.GAME
"""Type of the result, must be *game*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultGif(InlineQueryResult):
class InlineQueryResultGif(InlineQueryResult, kw_only=True):
"""
Represents a link to an animated GIF file. By default, this animated GIF file will be sent by the user with optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the animation.
Source: https://core.telegram.org/bots/api#inlinequeryresultgif
"""
type: str = Field(InlineQueryResultType.GIF, const=True)
type: str = InlineQueryResultType.GIF
"""Type of the result, must be *gif*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
import msgspec
from ..enums import InlineQueryResultType
from .inline_query_result import InlineQueryResult
@ -12,7 +12,7 @@ if TYPE_CHECKING:
from .input_message_content import InputMessageContent
class InlineQueryResultLocation(InlineQueryResult):
class InlineQueryResultLocation(InlineQueryResult, kw_only=True):
"""
Represents a location on a map. By default, the location will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the location.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -20,7 +20,7 @@ class InlineQueryResultLocation(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultlocation
"""
type: str = Field(InlineQueryResultType.LOCATION, const=True)
type: str = msgspec.field(default_factory=lambda: InlineQueryResultType.LOCATION)
"""Type of the result, must be *location*"""
id: str
"""Unique identifier for this result, 1-64 Bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultMpeg4Gif(InlineQueryResult):
class InlineQueryResultMpeg4Gif(InlineQueryResult, kw_only=True):
"""
Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). By default, this animated MPEG-4 file will be sent by the user with optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the animation.
Source: https://core.telegram.org/bots/api#inlinequeryresultmpeg4gif
"""
type: str = Field(InlineQueryResultType.MPEG4_GIF, const=True)
type: str = InlineQueryResultType.MPEG4_GIF
"""Type of the result, must be *mpeg4_gif*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,14 +12,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultPhoto(InlineQueryResult):
class InlineQueryResultPhoto(InlineQueryResult, kw_only=True):
"""
Represents a link to a photo. By default, this photo will be sent by the user with optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the photo.
Source: https://core.telegram.org/bots/api#inlinequeryresultphoto
"""
type: str = Field(InlineQueryResultType.PHOTO, const=True)
type: str = InlineQueryResultType.PHOTO
"""Type of the result, must be *photo*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .inline_query_result import InlineQueryResult
@ -12,7 +10,7 @@ if TYPE_CHECKING:
from .input_message_content import InputMessageContent
class InlineQueryResultVenue(InlineQueryResult):
class InlineQueryResultVenue(InlineQueryResult, kw_only=True):
"""
Represents a venue. By default, the venue will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the venue.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -20,7 +18,7 @@ class InlineQueryResultVenue(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultvenue
"""
type: str = Field(InlineQueryResultType.VENUE, const=True)
type: str = InlineQueryResultType.VENUE
"""Type of the result, must be *venue*"""
id: str
"""Unique identifier for this result, 1-64 Bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,7 +12,7 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultVideo(InlineQueryResult):
class InlineQueryResultVideo(InlineQueryResult, kw_only=True):
"""
Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the video.
@ -23,7 +21,7 @@ class InlineQueryResultVideo(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultvideo
"""
type: str = Field(InlineQueryResultType.VIDEO, const=True)
type: str = InlineQueryResultType.VIDEO
"""Type of the result, must be *video*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from pydantic import Field
from ..enums import InlineQueryResultType
from .base import UNSET_PARSE_MODE
from .inline_query_result import InlineQueryResult
@ -14,7 +12,7 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InlineQueryResultVoice(InlineQueryResult):
class InlineQueryResultVoice(InlineQueryResult, kw_only=True):
"""
Represents a link to a voice recording in an .OGG container encoded with OPUS. By default, this voice recording will be sent by the user. Alternatively, you can use *input_message_content* to send a message with the specified content instead of the the voice message.
**Note:** This will only work in Telegram versions released after 9 April, 2016. Older clients will ignore them.
@ -22,7 +20,7 @@ class InlineQueryResultVoice(InlineQueryResult):
Source: https://core.telegram.org/bots/api#inlinequeryresultvoice
"""
type: str = Field(InlineQueryResultType.VOICE, const=True)
type: str = InlineQueryResultType.VOICE
"""Type of the result, must be *voice*"""
id: str
"""Unique identifier for this result, 1-64 bytes"""

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .web_app_info import WebAppInfo
from .web_app_info import WebAppInfo
class InlineQueryResultsButton(TelegramObject):

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
from pydantic import Field
from ..enums import InputMediaType
from .base import UNSET_PARSE_MODE
from .input_media import InputMedia
@ -13,14 +11,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InputMediaAnimation(InputMedia):
class InputMediaAnimation(InputMedia, kw_only=True):
"""
Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
Source: https://core.telegram.org/bots/api#inputmediaanimation
"""
type: str = Field(InputMediaType.ANIMATION, const=True)
type: str = InputMediaType.ANIMATION
"""Type of the result, must be *animation*"""
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name. :ref:`More information on Sending Files » <sending-files>`"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
from pydantic import Field
from ..enums import InputMediaType
from .base import UNSET_PARSE_MODE
from .input_media import InputMedia
@ -13,14 +11,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InputMediaAudio(InputMedia):
class InputMediaAudio(InputMedia, kw_only=True):
"""
Represents an audio file to be treated as music to be sent.
Source: https://core.telegram.org/bots/api#inputmediaaudio
"""
type: str = Field(InputMediaType.AUDIO, const=True)
type: str = InputMediaType.AUDIO
"""Type of the result, must be *audio*"""
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name. :ref:`More information on Sending Files » <sending-files>`"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
from pydantic import Field
from ..enums import InputMediaType
from .base import UNSET_PARSE_MODE
from .input_media import InputMedia
@ -13,14 +11,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InputMediaDocument(InputMedia):
class InputMediaDocument(InputMedia, kw_only=True):
"""
Represents a general file to be sent.
Source: https://core.telegram.org/bots/api#inputmediadocument
"""
type: str = Field(InputMediaType.DOCUMENT, const=True)
type: str = InputMediaType.DOCUMENT
"""Type of the result, must be *document*"""
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name. :ref:`More information on Sending Files » <sending-files>`"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
from pydantic import Field
from ..enums import InputMediaType
from .base import UNSET_PARSE_MODE
from .input_media import InputMedia
@ -13,14 +11,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InputMediaPhoto(InputMedia):
class InputMediaPhoto(InputMedia, kw_only=True):
"""
Represents a photo to be sent.
Source: https://core.telegram.org/bots/api#inputmediaphoto
"""
type: str = Field(InputMediaType.PHOTO, const=True)
type: str = InputMediaType.PHOTO
"""Type of the result, must be *photo*"""
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name. :ref:`More information on Sending Files » <sending-files>`"""

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional, Union
from pydantic import Field
from ..enums import InputMediaType
from .base import UNSET_PARSE_MODE
from .input_media import InputMedia
@ -13,14 +11,14 @@ if TYPE_CHECKING:
from .message_entity import MessageEntity
class InputMediaVideo(InputMedia):
class InputMediaVideo(InputMedia, kw_only=True):
"""
Represents a video to be sent.
Source: https://core.telegram.org/bots/api#inputmediavideo
"""
type: str = Field(InputMediaType.VIDEO, const=True)
type: str = InputMediaType.VIDEO
"""Type of the result, must be *video*"""
media: Union[str, InputFile]
"""File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass 'attach://<file_attach_name>' to upload a new one using multipart/form-data under <file_attach_name> name. :ref:`More information on Sending Files » <sending-files>`"""

View file

@ -3,12 +3,10 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import MutableTelegramObject
if TYPE_CHECKING:
from .keyboard_button_poll_type import KeyboardButtonPollType
from .keyboard_button_request_chat import KeyboardButtonRequestChat
from .keyboard_button_request_user import KeyboardButtonRequestUser
from .web_app_info import WebAppInfo
from .keyboard_button_poll_type import KeyboardButtonPollType
from .keyboard_button_request_chat import KeyboardButtonRequestChat
from .keyboard_button_request_user import KeyboardButtonRequestUser
from .web_app_info import WebAppInfo
class KeyboardButton(MutableTelegramObject):

View file

@ -3,12 +3,10 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import MutableTelegramObject
if TYPE_CHECKING:
from .web_app_info import WebAppInfo
from .web_app_info import WebAppInfo
class MenuButton(MutableTelegramObject):
class MenuButton(MutableTelegramObject, tag_field="op", tag=str.lower):
"""
This object describes the bot's menu button in a private chat. It should be one of

View file

@ -1,6 +1,6 @@
from __future__ import annotations
from pydantic import Field
import msgspec
from ..enums import MenuButtonType
from .menu_button import MenuButton
@ -13,5 +13,5 @@ class MenuButtonCommands(MenuButton):
Source: https://core.telegram.org/bots/api#menubuttoncommands
"""
type: str = Field(MenuButtonType.COMMANDS, const=True)
type: str = msgspec.field(default_factory=lambda: MenuButtonType.COMMANDS)
"""Type of the button, must be *commands*"""

View file

@ -1,6 +1,6 @@
from __future__ import annotations
from pydantic import Field
import msgspec
from ..enums import MenuButtonType
from .menu_button import MenuButton
@ -13,5 +13,5 @@ class MenuButtonDefault(MenuButton):
Source: https://core.telegram.org/bots/api#menubuttondefault
"""
type: str = Field(MenuButtonType.DEFAULT, const=True)
type: str = msgspec.field(default_factory=lambda: MenuButtonType.DEFAULT)
"""Type of the button, must be *default*"""

View file

@ -2,23 +2,21 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from pydantic import Field
import msgspec
from ..enums import MenuButtonType
from .menu_button import MenuButton
if TYPE_CHECKING:
from .web_app_info import WebAppInfo
from .web_app_info import WebAppInfo
class MenuButtonWebApp(MenuButton):
class MenuButtonWebApp(MenuButton, kw_only=True):
"""
Represents a menu button, which launches a `Web App <https://core.telegram.org/bots/webapps>`_.
Source: https://core.telegram.org/bots/api#menubuttonwebapp
"""
type: str = Field(MenuButtonType.WEB_APP, const=True)
type: str = msgspec.field(default_factory=lambda: MenuButtonType.WEB_APP)
"""Type of the button, must be *web_app*"""
text: str
"""Text on the button"""

View file

@ -3,7 +3,7 @@ from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, Any, List, Optional, Union
from pydantic import Field
import msgspec
from aiogram.utils.text_decorations import (
TextDecoration,
@ -50,56 +50,57 @@ if TYPE_CHECKING:
StopMessageLiveLocation,
UnpinChatMessage,
)
from .animation import Animation
from .audio import Audio
from .chat import Chat
from .chat_shared import ChatShared
from .contact import Contact
from .dice import Dice
from .document import Document
from .force_reply import ForceReply
from .forum_topic_closed import ForumTopicClosed
from .forum_topic_created import ForumTopicCreated
from .forum_topic_edited import ForumTopicEdited
from .forum_topic_reopened import ForumTopicReopened
from .game import Game
from .general_forum_topic_hidden import GeneralForumTopicHidden
from .general_forum_topic_unhidden import GeneralForumTopicUnhidden
from .inline_keyboard_markup import InlineKeyboardMarkup
from .input_file import InputFile
from .input_media import InputMedia
from .input_media_audio import InputMediaAudio
from .input_media_document import InputMediaDocument
from .input_media_photo import InputMediaPhoto
from .input_media_video import InputMediaVideo
from .invoice import Invoice
from .labeled_price import LabeledPrice
from .location import Location
from .message_auto_delete_timer_changed import MessageAutoDeleteTimerChanged
from .message_entity import MessageEntity
from .passport_data import PassportData
from .photo_size import PhotoSize
from .poll import Poll
from .proximity_alert_triggered import ProximityAlertTriggered
from .reply_keyboard_markup import ReplyKeyboardMarkup
from .reply_keyboard_remove import ReplyKeyboardRemove
from .sticker import Sticker
from .successful_payment import SuccessfulPayment
from .user import User
from .user_shared import UserShared
from .venue import Venue
from .video import Video
from .video_chat_ended import VideoChatEnded
from .video_chat_participants_invited import VideoChatParticipantsInvited
from .video_chat_scheduled import VideoChatScheduled
from .video_chat_started import VideoChatStarted
from .video_note import VideoNote
from .voice import Voice
from .web_app_data import WebAppData
from .write_access_allowed import WriteAccessAllowed
from .animation import Animation
from .audio import Audio
from .chat import Chat
from .chat_shared import ChatShared
from .contact import Contact
from .dice import Dice
from .document import Document
from .force_reply import ForceReply
from .forum_topic_closed import ForumTopicClosed
from .forum_topic_created import ForumTopicCreated
from .forum_topic_edited import ForumTopicEdited
from .forum_topic_reopened import ForumTopicReopened
from .game import Game
from .general_forum_topic_hidden import GeneralForumTopicHidden
from .general_forum_topic_unhidden import GeneralForumTopicUnhidden
from .inline_keyboard_markup import InlineKeyboardMarkup
from .input_file import InputFile
from .input_media import InputMedia
from .input_media_audio import InputMediaAudio
from .input_media_document import InputMediaDocument
from .input_media_photo import InputMediaPhoto
from .input_media_video import InputMediaVideo
from .invoice import Invoice
from .labeled_price import LabeledPrice
from .location import Location
from .message_auto_delete_timer_changed import MessageAutoDeleteTimerChanged
from .message_entity import MessageEntity
from .passport_data import PassportData
from .photo_size import PhotoSize
from .poll import Poll
from .proximity_alert_triggered import ProximityAlertTriggered
from .reply_keyboard_markup import ReplyKeyboardMarkup
from .reply_keyboard_remove import ReplyKeyboardRemove
from .sticker import Sticker
from .successful_payment import SuccessfulPayment
from .user import User
from .user_shared import UserShared
from .venue import Venue
from .video import Video
from .video_chat_ended import VideoChatEnded
from .video_chat_participants_invited import VideoChatParticipantsInvited
from .video_chat_scheduled import VideoChatScheduled
from .video_chat_started import VideoChatStarted
from .video_note import VideoNote
from .voice import Voice
from .web_app_data import WebAppData
from .write_access_allowed import WriteAccessAllowed
class Message(TelegramObject):
class Message(TelegramObject, kw_only=True):
"""
This object represents a message.
@ -108,13 +109,13 @@ class Message(TelegramObject):
message_id: int
"""Unique message identifier inside this chat"""
date: datetime.datetime
date: datetime.datetime | int
"""Date the message was sent in Unix time"""
chat: Chat
"""Conversation the message belongs to"""
message_thread_id: Optional[int] = None
"""*Optional*. Unique identifier of a message thread to which the message belongs; for supergroups only"""
from_user: Optional[User] = Field(None, alias="from")
from_user: Optional[User] = msgspec.field(name="from", default=None)
"""*Optional*. Sender of the message; empty for messages sent to channels. For backward compatibility, the field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat."""
sender_chat: Optional[Chat] = None
"""*Optional*. Sender of the message, sent on behalf of a chat. For example, the channel itself for channel posts, the supergroup itself for messages from anonymous group administrators, the linked channel for messages automatically forwarded to the discussion group. For backward compatibility, the field *from* contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat."""

View file

@ -4,9 +4,7 @@ from typing import TYPE_CHECKING, Optional
from ..utils.text_decorations import add_surrogates, remove_surrogates
from .base import MutableTelegramObject
if TYPE_CHECKING:
from .user import User
from .user import User
class MessageEntity(MutableTelegramObject):

View file

@ -3,9 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from .base import TelegramObject
if TYPE_CHECKING:
from .shipping_address import ShippingAddress
from .shipping_address import ShippingAddress
class OrderInfo(TelegramObject):

View file

@ -3,10 +3,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List
from .base import TelegramObject
if TYPE_CHECKING:
from .encrypted_credentials import EncryptedCredentials
from .encrypted_passport_element import EncryptedPassportElement
from .encrypted_credentials import EncryptedCredentials
from .encrypted_passport_element import EncryptedPassportElement
class PassportData(TelegramObject):

View file

@ -1,18 +1,16 @@
from __future__ import annotations
from pydantic import Field
from .passport_element_error import PassportElementError
class PassportElementErrorDataField(PassportElementError):
class PassportElementErrorDataField(PassportElementError, kw_only=True):
"""
Represents an issue in one of the data fields that was provided by the user. The error is considered resolved when the field's value changes.
Source: https://core.telegram.org/bots/api#passportelementerrordatafield
"""
source: str = Field("data", const=True)
source: str = "data"
"""Error source, must be *data*"""
type: str
"""The section of the user's Telegram Passport which has the error, one of 'personal_details', 'passport', 'driver_license', 'identity_card', 'internal_passport', 'address'"""

View file

@ -1,18 +1,16 @@
from __future__ import annotations
from pydantic import Field
from .passport_element_error import PassportElementError
class PassportElementErrorFile(PassportElementError):
class PassportElementErrorFile(PassportElementError, kw_only=True):
"""
Represents an issue with a document scan. The error is considered resolved when the file with the document scan changes.
Source: https://core.telegram.org/bots/api#passportelementerrorfile
"""
source: str = Field("file", const=True)
source: str = "file"
"""Error source, must be *file*"""
type: str
"""The section of the user's Telegram Passport which has the issue, one of 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'"""

View file

@ -2,19 +2,17 @@ from __future__ import annotations
from typing import List
from pydantic import Field
from .passport_element_error import PassportElementError
class PassportElementErrorFiles(PassportElementError):
class PassportElementErrorFiles(PassportElementError, kw_only=True):
"""
Represents an issue with a list of scans. The error is considered resolved when the list of files containing the scans changes.
Source: https://core.telegram.org/bots/api#passportelementerrorfiles
"""
source: str = Field("files", const=True)
source: str = "files"
"""Error source, must be *files*"""
type: str
"""The section of the user's Telegram Passport which has the issue, one of 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'"""

View file

@ -1,18 +1,16 @@
from __future__ import annotations
from pydantic import Field
from .passport_element_error import PassportElementError
class PassportElementErrorFrontSide(PassportElementError):
class PassportElementErrorFrontSide(PassportElementError, kw_only=True):
"""
Represents an issue with the front side of a document. The error is considered resolved when the file with the front side of the document changes.
Source: https://core.telegram.org/bots/api#passportelementerrorfrontside
"""
source: str = Field("front_side", const=True)
source: str = "front_side"
"""Error source, must be *front_side*"""
type: str
"""The section of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport'"""

View file

@ -1,18 +1,16 @@
from __future__ import annotations
from pydantic import Field
from .passport_element_error import PassportElementError
class PassportElementErrorReverseSide(PassportElementError):
class PassportElementErrorReverseSide(PassportElementError, kw_only=True):
"""
Represents an issue with the reverse side of a document. The error is considered resolved when the file with reverse side of the document changes.
Source: https://core.telegram.org/bots/api#passportelementerrorreverseside
"""
source: str = Field("reverse_side", const=True)
source: str = "reverse_side"
"""Error source, must be *reverse_side*"""
type: str
"""The section of the user's Telegram Passport which has the issue, one of 'driver_license', 'identity_card'"""

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