mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Replace datetime.datetime with DateTime across codebase (#1285)
* #1277 Replace datetime.datetime with DateTime across codebase Replaced all instances of standard library 'datetime.datetime' with a new 'DateTime' type from `.custom` module. This change is necessary to make all date-time values compatible with the Telegram Bot API (it uses Unix time). This will simplify the conversion process and eliminate potential errors related to date-time format mismatches. Changed codebase, butcher files, and modified 'pyproject.toml' to shift the typing-extensions dependency. The 'aiogram/custom_types.py' file was renamed to 'aiogram/types/custom.py' to better reflect its nature as a location for custom types used in the aiogram library.
This commit is contained in:
parent
397f30b58b
commit
6eb5ef2606
25 changed files with 65 additions and 43 deletions
|
|
@ -37,6 +37,7 @@ from .chat_photo import ChatPhoto
|
|||
from .chat_shared import ChatShared
|
||||
from .chosen_inline_result import ChosenInlineResult
|
||||
from .contact import Contact
|
||||
from .custom import DateTime
|
||||
from .dice import Dice
|
||||
from .document import Document
|
||||
from .downloadable import Downloadable
|
||||
|
|
@ -197,6 +198,7 @@ __all__ = (
|
|||
"ChosenInlineResult",
|
||||
"Contact",
|
||||
"ContentType",
|
||||
"DateTime",
|
||||
"Dice",
|
||||
"Document",
|
||||
"Downloadable",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import datetime
|
|||
from typing import TYPE_CHECKING, Any, List, Optional, Union
|
||||
|
||||
from .base import TelegramObject
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..methods import (
|
||||
|
|
@ -70,7 +71,7 @@ class Chat(TelegramObject):
|
|||
"""*Optional*. If non-empty, the list of all `active chat usernames <https://telegram.org/blog/topics-in-groups-collectible-usernames#collectible-usernames>`_; for private chats, supergroups and channels. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
|
||||
emoji_status_custom_emoji_id: Optional[str] = None
|
||||
"""*Optional*. Custom emoji identifier of emoji status of the other party in a private chat. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
|
||||
emoji_status_expiration_date: Optional[datetime.datetime] = None
|
||||
emoji_status_expiration_date: Optional[DateTime] = None
|
||||
"""*Optional*. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
|
||||
bio: Optional[str] = None
|
||||
"""*Optional*. Bio of the other party in a private chat. Returned only in :class:`aiogram.methods.get_chat.GetChat`."""
|
||||
|
|
@ -126,7 +127,7 @@ class Chat(TelegramObject):
|
|||
photo: Optional[ChatPhoto] = None,
|
||||
active_usernames: Optional[List[str]] = None,
|
||||
emoji_status_custom_emoji_id: Optional[str] = None,
|
||||
emoji_status_expiration_date: Optional[datetime.datetime] = None,
|
||||
emoji_status_expiration_date: Optional[DateTime] = None,
|
||||
bio: Optional[str] = None,
|
||||
has_private_forwards: Optional[bool] = None,
|
||||
has_restricted_voice_and_video_messages: Optional[bool] = None,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
|
||||
from .base import TelegramObject
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .user import User
|
||||
|
|
@ -28,7 +28,7 @@ class ChatInviteLink(TelegramObject):
|
|||
""":code:`True`, if the link is revoked"""
|
||||
name: Optional[str] = None
|
||||
"""*Optional*. Invite link name"""
|
||||
expire_date: Optional[datetime.datetime] = None
|
||||
expire_date: Optional[DateTime] = None
|
||||
"""*Optional*. Point in time (Unix timestamp) when the link will expire or has been expired"""
|
||||
member_limit: Optional[int] = None
|
||||
"""*Optional*. The maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; 1-99999"""
|
||||
|
|
@ -48,7 +48,7 @@ class ChatInviteLink(TelegramObject):
|
|||
is_primary: bool,
|
||||
is_revoked: bool,
|
||||
name: Optional[str] = None,
|
||||
expire_date: Optional[datetime.datetime] = None,
|
||||
expire_date: Optional[DateTime] = None,
|
||||
member_limit: Optional[int] = None,
|
||||
pending_join_request_count: Optional[int] = None,
|
||||
**__pydantic_kwargs: Any,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from .base import (
|
|||
UNSET_PROTECT_CONTENT,
|
||||
TelegramObject,
|
||||
)
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..methods import (
|
||||
|
|
@ -63,7 +64,7 @@ class ChatJoinRequest(TelegramObject):
|
|||
"""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."""
|
||||
date: datetime.datetime
|
||||
date: DateTime
|
||||
"""Date the request was sent in Unix time"""
|
||||
bio: Optional[str] = None
|
||||
"""*Optional*. Bio of the user."""
|
||||
|
|
@ -80,7 +81,7 @@ class ChatJoinRequest(TelegramObject):
|
|||
chat: Chat,
|
||||
from_user: User,
|
||||
user_chat_id: int,
|
||||
date: datetime.datetime,
|
||||
date: DateTime,
|
||||
bio: Optional[str] = None,
|
||||
invite_link: Optional[ChatInviteLink] = None,
|
||||
**__pydantic_kwargs: Any,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
from ..enums import ChatMemberStatus
|
||||
from .chat_member import ChatMember
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .user import User
|
||||
|
|
@ -21,7 +21,7 @@ class ChatMemberBanned(ChatMember):
|
|||
"""The member's status in the chat, always 'kicked'"""
|
||||
user: User
|
||||
"""Information about the user"""
|
||||
until_date: datetime.datetime
|
||||
until_date: DateTime
|
||||
"""Date when restrictions will be lifted for this user; unix time. If 0, then the user is banned forever"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -33,7 +33,7 @@ class ChatMemberBanned(ChatMember):
|
|||
*,
|
||||
status: Literal[ChatMemberStatus.KICKED] = ChatMemberStatus.KICKED,
|
||||
user: User,
|
||||
until_date: datetime.datetime,
|
||||
until_date: DateTime,
|
||||
**__pydantic_kwargs: Any,
|
||||
) -> None:
|
||||
# DO NOT EDIT MANUALLY!!!
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
from ..enums import ChatMemberStatus
|
||||
from .chat_member import ChatMember
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .user import User
|
||||
|
|
@ -51,7 +51,7 @@ class ChatMemberRestricted(ChatMember):
|
|||
""":code:`True`, if the user is allowed to pin messages"""
|
||||
can_manage_topics: bool
|
||||
""":code:`True`, if the user is allowed to create forum topics"""
|
||||
until_date: datetime.datetime
|
||||
until_date: DateTime
|
||||
"""Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted forever"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -78,7 +78,7 @@ class ChatMemberRestricted(ChatMember):
|
|||
can_invite_users: bool,
|
||||
can_pin_messages: bool,
|
||||
can_manage_topics: bool,
|
||||
until_date: datetime.datetime,
|
||||
until_date: DateTime,
|
||||
**__pydantic_kwargs: Any,
|
||||
) -> None:
|
||||
# DO NOT EDIT MANUALLY!!!
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from .base import (
|
|||
UNSET_PROTECT_CONTENT,
|
||||
TelegramObject,
|
||||
)
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..methods import (
|
||||
|
|
@ -65,7 +66,7 @@ class ChatMemberUpdated(TelegramObject):
|
|||
"""Chat the user belongs to"""
|
||||
from_user: User = Field(..., alias="from")
|
||||
"""Performer of the action, which resulted in the change"""
|
||||
date: datetime.datetime
|
||||
date: DateTime
|
||||
"""Date the change was done in Unix time"""
|
||||
old_chat_member: Union[
|
||||
ChatMemberOwner,
|
||||
|
|
@ -99,7 +100,7 @@ class ChatMemberUpdated(TelegramObject):
|
|||
*,
|
||||
chat: Chat,
|
||||
from_user: User,
|
||||
date: datetime.datetime,
|
||||
date: DateTime,
|
||||
old_chat_member: Union[
|
||||
ChatMemberOwner,
|
||||
ChatMemberAdministrator,
|
||||
|
|
|
|||
14
aiogram/types/custom.py
Normal file
14
aiogram/types/custom.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
from datetime import datetime
|
||||
|
||||
from pydantic import PlainSerializer
|
||||
from typing_extensions import Annotated
|
||||
|
||||
# Make datetime compatible with Telegram Bot API (unixtime)
|
||||
DateTime = Annotated[
|
||||
datetime,
|
||||
PlainSerializer(
|
||||
func=lambda dt: int(dt.timestamp()),
|
||||
return_type=int,
|
||||
when_used="json-unless-none",
|
||||
),
|
||||
]
|
||||
|
|
@ -18,6 +18,7 @@ from .base import (
|
|||
UNSET_PROTECT_CONTENT,
|
||||
TelegramObject,
|
||||
)
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..methods import (
|
||||
|
|
@ -109,7 +110,7 @@ class Message(TelegramObject):
|
|||
|
||||
message_id: int
|
||||
"""Unique message identifier inside this chat"""
|
||||
date: datetime.datetime
|
||||
date: DateTime
|
||||
"""Date the message was sent in Unix time"""
|
||||
chat: Chat
|
||||
"""Conversation the message belongs to"""
|
||||
|
|
@ -129,7 +130,7 @@ class Message(TelegramObject):
|
|||
"""*Optional*. For forwarded messages that were originally sent in channels or by an anonymous chat administrator, signature of the message sender if present"""
|
||||
forward_sender_name: Optional[str] = None
|
||||
"""*Optional*. Sender's name for messages forwarded from users who disallow adding a link to their account in forwarded messages"""
|
||||
forward_date: Optional[datetime.datetime] = None
|
||||
forward_date: Optional[DateTime] = None
|
||||
"""*Optional*. For forwarded messages, date the original message was sent in Unix time"""
|
||||
is_topic_message: Optional[bool] = None
|
||||
"""*Optional*. :code:`True`, if the message is sent to a forum topic"""
|
||||
|
|
@ -260,7 +261,7 @@ class Message(TelegramObject):
|
|||
__pydantic__self__,
|
||||
*,
|
||||
message_id: int,
|
||||
date: datetime.datetime,
|
||||
date: DateTime,
|
||||
chat: Chat,
|
||||
message_thread_id: Optional[int] = None,
|
||||
from_user: Optional[User] = None,
|
||||
|
|
@ -270,7 +271,7 @@ class Message(TelegramObject):
|
|||
forward_from_message_id: Optional[int] = None,
|
||||
forward_signature: Optional[str] = None,
|
||||
forward_sender_name: Optional[str] = None,
|
||||
forward_date: Optional[datetime.datetime] = None,
|
||||
forward_date: Optional[DateTime] = None,
|
||||
is_topic_message: Optional[bool] = None,
|
||||
is_automatic_forward: Optional[bool] = None,
|
||||
reply_to_message: Optional[Message] = None,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Any, List, Optional
|
||||
|
||||
from .base import TelegramObject
|
||||
from .custom import DateTime
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .message_entity import MessageEntity
|
||||
|
|
@ -41,7 +41,7 @@ class Poll(TelegramObject):
|
|||
"""*Optional*. Special entities like usernames, URLs, bot commands, etc. that appear in the *explanation*"""
|
||||
open_period: Optional[int] = None
|
||||
"""*Optional*. Amount of time in seconds the poll will be active after creation"""
|
||||
close_date: Optional[datetime.datetime] = None
|
||||
close_date: Optional[DateTime] = None
|
||||
"""*Optional*. Point in time (Unix timestamp) when the poll will be automatically closed"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -63,7 +63,7 @@ class Poll(TelegramObject):
|
|||
explanation: Optional[str] = None,
|
||||
explanation_entities: Optional[List[MessageEntity]] = None,
|
||||
open_period: Optional[int] = None,
|
||||
close_date: Optional[datetime.datetime] = None,
|
||||
close_date: Optional[DateTime] = None,
|
||||
**__pydantic_kwargs: Any,
|
||||
) -> None:
|
||||
# DO NOT EDIT MANUALLY!!!
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from .base import TelegramObject
|
||||
from .custom import DateTime
|
||||
|
||||
|
||||
class VideoChatScheduled(TelegramObject):
|
||||
|
|
@ -13,7 +13,7 @@ class VideoChatScheduled(TelegramObject):
|
|||
Source: https://core.telegram.org/bots/api#videochatscheduled
|
||||
"""
|
||||
|
||||
start_date: datetime.datetime
|
||||
start_date: DateTime
|
||||
"""Point in time (Unix timestamp) when the video chat is supposed to be started by a chat administrator"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -21,7 +21,7 @@ class VideoChatScheduled(TelegramObject):
|
|||
# This section was auto-generated via `butcher`
|
||||
|
||||
def __init__(
|
||||
__pydantic__self__, *, start_date: datetime.datetime, **__pydantic_kwargs: Any
|
||||
__pydantic__self__, *, start_date: DateTime, **__pydantic_kwargs: Any
|
||||
) -> None:
|
||||
# DO NOT EDIT MANUALLY!!!
|
||||
# This method was auto-generated via `butcher`
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Any, List, Optional
|
||||
|
||||
from .base import TelegramObject
|
||||
from .custom import DateTime
|
||||
|
||||
|
||||
class WebhookInfo(TelegramObject):
|
||||
|
|
@ -21,11 +21,11 @@ class WebhookInfo(TelegramObject):
|
|||
"""Number of updates awaiting delivery"""
|
||||
ip_address: Optional[str] = None
|
||||
"""*Optional*. Currently used webhook IP address"""
|
||||
last_error_date: Optional[datetime.datetime] = None
|
||||
last_error_date: Optional[DateTime] = None
|
||||
"""*Optional*. Unix time for the most recent error that happened when trying to deliver an update via webhook"""
|
||||
last_error_message: Optional[str] = None
|
||||
"""*Optional*. Error message in human-readable format for the most recent error that happened when trying to deliver an update via webhook"""
|
||||
last_synchronization_error_date: Optional[datetime.datetime] = None
|
||||
last_synchronization_error_date: Optional[DateTime] = None
|
||||
"""*Optional*. Unix time of the most recent error that happened when trying to synchronize available updates with Telegram datacenters"""
|
||||
max_connections: Optional[int] = None
|
||||
"""*Optional*. The maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery"""
|
||||
|
|
@ -43,9 +43,9 @@ class WebhookInfo(TelegramObject):
|
|||
has_custom_certificate: bool,
|
||||
pending_update_count: int,
|
||||
ip_address: Optional[str] = None,
|
||||
last_error_date: Optional[datetime.datetime] = None,
|
||||
last_error_date: Optional[DateTime] = None,
|
||||
last_error_message: Optional[str] = None,
|
||||
last_synchronization_error_date: Optional[datetime.datetime] = None,
|
||||
last_synchronization_error_date: Optional[DateTime] = None,
|
||||
max_connections: Optional[int] = None,
|
||||
allowed_updates: Optional[List[str]] = None,
|
||||
**__pydantic_kwargs: Any,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue