diff --git a/docs/source/conf.py b/docs/source/conf.py index 53ac9012..cb273c07 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,7 +18,6 @@ import os import sys -from datetime import datetime sys.path.insert(0, os.path.abspath("../..")) @@ -38,9 +37,14 @@ extensions = [ "sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx.ext.autosummary", + "sphinx.ext.intersphinx", "sphinx_copybutton" ] +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None) +} + master_doc = "index" source_suffix = ".rst" autodoc_member_order = "bysource" diff --git a/pyrogram/methods/chats/ban_chat_member.py b/pyrogram/methods/chats/ban_chat_member.py index bdf11751..3edcb164 100644 --- a/pyrogram/methods/chats/ban_chat_member.py +++ b/pyrogram/methods/chats/ban_chat_member.py @@ -16,9 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.scaffold import Scaffold @@ -28,7 +29,7 @@ class BanChatMember(Scaffold): self, chat_id: Union[int, str], user_id: Union[int, str], - until_date: int = 0 + until_date: datetime = datetime.fromtimestamp(0) ) -> Union["types.Message", bool]: """Ban a user from a group, a supergroup or a channel. In the case of supergroups and channels, the user will not be able to return to the group on their own using @@ -48,10 +49,10 @@ class BanChatMember(Scaffold): Unique identifier (int) or username (str) of the target user. For a contact that exists in your Telegram address book you can use his phone number (str). - until_date (``int``, *optional*): - Date when the user will be unbanned, unix time. + until_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the user will be unbanned. If user is banned for more than 366 days or less than 30 seconds from the current time they are - considered to be banned forever. Defaults to 0 (ban forever). + considered to be banned forever. Defaults to epoch (ban forever). Returns: :obj:`~pyrogram.types.Message` | ``bool``: On success, a service message will be returned (when applicable), @@ -60,13 +61,13 @@ class BanChatMember(Scaffold): Example: .. code-block:: python - from time import time + from datetime import datetime, timedelta # Ban chat member forever app.ban_chat_member(chat_id, user_id) # Ban chat member and automatically unban after 24h - app.ban_chat_member(chat_id, user_id, int(time.time() + 86400)) + app.ban_chat_member(chat_id, user_id, datetime.now() + timedelta(days=1)) """ chat_peer = await self.resolve_peer(chat_id) user_peer = await self.resolve_peer(user_id) @@ -77,7 +78,7 @@ class BanChatMember(Scaffold): channel=chat_peer, participant=user_peer, banned_rights=raw.types.ChatBannedRights( - until_date=until_date, + until_date=utils.datetime_to_timestamp(until_date), view_messages=True, send_messages=True, send_media=True, diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py index 7a9d6a48..9fb907ca 100644 --- a/pyrogram/methods/chats/get_dialogs.py +++ b/pyrogram/methods/chats/get_dialogs.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . import logging +from datetime import datetime from typing import List from pyrogram import raw @@ -30,7 +31,7 @@ log = logging.getLogger(__name__) class GetDialogs(Scaffold): async def get_dialogs( self, - offset_date: int = 0, + offset_date: datetime = datetime.fromtimestamp(0), limit: int = 100, pinned_only: bool = False ) -> List["types.Dialog"]: @@ -40,9 +41,9 @@ class GetDialogs(Scaffold): For a more convenient way of getting a user's dialogs see :meth:`~pyrogram.Client.iter_dialogs`. Parameters: - offset_date (``int``): - The offset date in Unix time taken from the top message of a :obj:`~pyrogram.types.Dialog`. - Defaults to 0. Valid for non-pinned dialogs only. + offset_date (:py:obj:`~datetime.datetime`): + The offset date taken from the top message of a :obj:`~pyrogram.types.Dialog`. + Defaults to epoch. Valid for non-pinned dialogs only. limit (``str``, *optional*): Limits the number of dialogs to be retrieved. @@ -73,7 +74,7 @@ class GetDialogs(Scaffold): else: r = await self.send( raw.functions.messages.GetDialogs( - offset_date=offset_date, + offset_date=utils.datetime_to_timestamp(offset_date), offset_id=0, offset_peer=raw.types.InputPeerEmpty(), limit=limit, diff --git a/pyrogram/methods/chats/restrict_chat_member.py b/pyrogram/methods/chats/restrict_chat_member.py index 7a759185..22eee519 100644 --- a/pyrogram/methods/chats/restrict_chat_member.py +++ b/pyrogram/methods/chats/restrict_chat_member.py @@ -16,9 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.scaffold import Scaffold @@ -29,7 +30,7 @@ class RestrictChatMember(Scaffold): chat_id: Union[int, str], user_id: Union[int, str], permissions: "types.ChatPermissions", - until_date: int = 0 + until_date: datetime = datetime.fromtimestamp(0) ) -> "types.Chat": """Restrict a user in a supergroup. @@ -47,10 +48,10 @@ class RestrictChatMember(Scaffold): permissions (:obj:`~pyrogram.types.ChatPermissions`): New user permissions. - until_date (``int``, *optional*): - Date when the user will be unbanned, unix time. + until_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the user will be unbanned. If user is banned for more than 366 days or less than 30 seconds from the current time they are - considered to be banned forever. Defaults to 0 (ban forever). + considered to be banned forever. Defaults to epoch (ban forever). Returns: :obj:`~pyrogram.types.Chat`: On success, a chat object is returned. @@ -58,7 +59,7 @@ class RestrictChatMember(Scaffold): Example: .. code-block:: python - from time import time + from datetime import datetime, timedelta from pyrogram.types import ChatPermissions @@ -66,7 +67,7 @@ class RestrictChatMember(Scaffold): app.restrict_chat_member(chat_id, user_id, ChatPermissions()) # Chat member muted for 24h - app.restrict_chat_member(chat_id, user_id, ChatPermissions(), int(time() + 86400)) + app.restrict_chat_member(chat_id, user_id, ChatPermissions(), datetime.now() + timedelta(days=1)) # Chat member can only send text messages app.restrict_chat_member(chat_id, user_id, ChatPermissions(can_send_messages=True)) @@ -76,7 +77,7 @@ class RestrictChatMember(Scaffold): channel=await self.resolve_peer(chat_id), participant=await self.resolve_peer(user_id), banned_rights=raw.types.ChatBannedRights( - until_date=until_date, + until_date=utils.datetime_to_timestamp(until_date), send_messages=not permissions.can_send_messages, send_media=not permissions.can_send_media_messages, send_stickers=not permissions.can_send_other_messages, diff --git a/pyrogram/methods/invite_links/create_chat_invite_link.py b/pyrogram/methods/invite_links/create_chat_invite_link.py index 4e6aded0..eec25787 100644 --- a/pyrogram/methods/invite_links/create_chat_invite_link.py +++ b/pyrogram/methods/invite_links/create_chat_invite_link.py @@ -16,9 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.scaffold import Scaffold @@ -28,7 +29,7 @@ class CreateChatInviteLink(Scaffold): self, chat_id: Union[int, str], name: str = None, - expire_date: int = None, + expire_date: datetime = None, member_limit: int = None, creates_join_request: bool = None ) -> "types.ChatInviteLink": @@ -46,8 +47,8 @@ class CreateChatInviteLink(Scaffold): name (``str``, *optional*): Invite link name. - expire_date (``int``, *optional*): - Point in time (Unix timestamp) when the link will expire. + expire_date (:py:obj:`~datetime.datetime`, *optional*): + Point in time when the link will expire. Defaults to None (no expiration date). member_limit (``int``, *optional*): @@ -74,7 +75,7 @@ class CreateChatInviteLink(Scaffold): r = await self.send( raw.functions.messages.ExportChatInvite( peer=await self.resolve_peer(chat_id), - expire_date=expire_date, + expire_date=utils.datetime_to_timestamp(expire_date), usage_limit=member_limit, title=name, request_needed=creates_join_request diff --git a/pyrogram/methods/invite_links/edit_chat_invite_link.py b/pyrogram/methods/invite_links/edit_chat_invite_link.py index 5c9dc9ff..9a375360 100644 --- a/pyrogram/methods/invite_links/edit_chat_invite_link.py +++ b/pyrogram/methods/invite_links/edit_chat_invite_link.py @@ -16,9 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.scaffold import Scaffold @@ -29,7 +30,7 @@ class EditChatInviteLink(Scaffold): chat_id: Union[int, str], invite_link: str, name: str = None, - expire_date: int = None, + expire_date: datetime = None, member_limit: int = None, creates_join_request: bool = None ) -> "types.ChatInviteLink": @@ -48,9 +49,9 @@ class EditChatInviteLink(Scaffold): name (``str``, *optional*): Invite link name. - expire_date (``int``, *optional*): - Point in time (Unix timestamp) when the link will expire. - Defaults to None (no change), pass 0 to set no expiration date. + expire_date (:py:obj:`~datetime.datetime`, *optional*): + Point in time when the link will expire. + Defaults to None (no change), pass ``datetime.fromtimestamp(0)`` to set no expiration date. member_limit (``int``, *optional*): Maximum number of users that can be members of the chat simultaneously after joining the chat via this @@ -77,7 +78,7 @@ class EditChatInviteLink(Scaffold): raw.functions.messages.EditExportedChatInvite( peer=await self.resolve_peer(chat_id), link=invite_link, - expire_date=expire_date, + expire_date=utils.datetime_to_timestamp(expire_date), usage_limit=member_limit, title=name, request_needed=creates_join_request diff --git a/pyrogram/methods/messages/copy_media_group.py b/pyrogram/methods/messages/copy_media_group.py index 72d8d04b..06aa6c20 100644 --- a/pyrogram/methods/messages/copy_media_group.py +++ b/pyrogram/methods/messages/copy_media_group.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, List from pyrogram import types, utils, raw @@ -31,7 +32,7 @@ class CopyMediaGroup(Scaffold): captions: Union[List[str], str] = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, ) -> List["types.Message"]: """Copy a media group by providing one of the message ids. @@ -65,8 +66,8 @@ class CopyMediaGroup(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. Returns: List of :obj:`~pyrogram.types.Message`: On success, a list of copied messages is returned. @@ -114,7 +115,7 @@ class CopyMediaGroup(Scaffold): multi_media=multi_media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, - schedule_date=schedule_date + schedule_date=utils.datetime_to_timestamp(schedule_date) ), sleep_threshold=60 ) diff --git a/pyrogram/methods/messages/copy_message.py b/pyrogram/methods/messages/copy_message.py index 07c0c5fa..ee40945b 100644 --- a/pyrogram/methods/messages/copy_message.py +++ b/pyrogram/methods/messages/copy_message.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . import logging +from datetime import datetime from typing import Union, List, Optional from pyrogram import types, enums @@ -36,7 +37,7 @@ class CopyMessage(Scaffold): caption_entities: List["types.MessageEntity"] = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -83,8 +84,8 @@ class CopyMessage(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. diff --git a/pyrogram/methods/messages/forward_messages.py b/pyrogram/methods/messages/forward_messages.py index caa627d8..acddd6e6 100644 --- a/pyrogram/methods/messages/forward_messages.py +++ b/pyrogram/methods/messages/forward_messages.py @@ -16,9 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, Iterable, List -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.scaffold import Scaffold @@ -30,7 +31,7 @@ class ForwardMessages(Scaffold): from_chat_id: Union[int, str], message_ids: Union[int, Iterable[int]], disable_notification: bool = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None ) -> Union["types.Message", List["types.Message"]]: """Forward messages of any kind. @@ -54,8 +55,8 @@ class ForwardMessages(Scaffold): Sends the message silently. Users will receive a notification with no sound. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -85,7 +86,7 @@ class ForwardMessages(Scaffold): id=message_ids, silent=disable_notification or None, random_id=[self.rnd_id() for _ in message_ids], - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content ) ) diff --git a/pyrogram/methods/messages/get_history.py b/pyrogram/methods/messages/get_history.py index d80a6b8b..a461b720 100644 --- a/pyrogram/methods/messages/get_history.py +++ b/pyrogram/methods/messages/get_history.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . import logging +from datetime import datetime from typing import Union, List from pyrogram import raw @@ -34,7 +35,7 @@ class GetHistory(Scaffold): limit: int = 100, offset: int = 0, offset_id: int = 0, - offset_date: int = 0, + offset_date: datetime = datetime.fromtimestamp(0), reverse: bool = False ) -> List["types.Message"]: """Retrieve a chunk of the history of a chat. @@ -59,8 +60,8 @@ class GetHistory(Scaffold): offset_id (``int``, *optional*): Pass a message identifier as offset to retrieve only older messages starting from that message. - offset_date (``int``, *optional*): - Pass a date in Unix time as offset to retrieve only older messages starting from that date. + offset_date (:py:obj:`~datetime.datetime`, *optional*): + Pass a date as offset to retrieve only older messages starting from that date. reverse (``bool``, *optional*): Pass True to retrieve the messages in reversed order (from older to most recent). @@ -89,7 +90,7 @@ class GetHistory(Scaffold): raw.functions.messages.GetHistory( peer=await self.resolve_peer(chat_id), offset_id=offset_id, - offset_date=offset_date, + offset_date=utils.datetime_to_timestamp(offset_date), add_offset=offset * (-1 if reverse else 1) - (limit if reverse else 0), limit=limit, max_id=0, diff --git a/pyrogram/methods/messages/iter_history.py b/pyrogram/methods/messages/iter_history.py index 2e60dfde..b9dd2009 100644 --- a/pyrogram/methods/messages/iter_history.py +++ b/pyrogram/methods/messages/iter_history.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, Optional, AsyncGenerator from pyrogram import types @@ -29,7 +30,7 @@ class IterHistory(Scaffold): limit: int = 0, offset: int = 0, offset_id: int = 0, - offset_date: int = 0, + offset_date: datetime = datetime.fromtimestamp(0), reverse: bool = False ) -> Optional[AsyncGenerator["types.Message", None]]: """Iterate through a chat history sequentially. @@ -55,8 +56,8 @@ class IterHistory(Scaffold): offset_id (``int``, *optional*): Identifier of the first message to be returned. - offset_date (``int``, *optional*): - Pass a date in Unix time as offset to retrieve only older messages starting from that date. + offset_date (:py:obj:`~datetime.datetime`, *optional*): + Pass a date as offset to retrieve only older messages starting from that date. reverse (``bool``, *optional*): Pass True to retrieve the messages in reversed order (from older to most recent). diff --git a/pyrogram/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py index 3777b3ea..4e6a9f40 100644 --- a/pyrogram/methods/messages/send_animation.py +++ b/pyrogram/methods/messages/send_animation.py @@ -18,6 +18,7 @@ import os import re +from datetime import datetime from typing import Union, BinaryIO, List, Optional from pyrogram import StopTransmission, enums @@ -45,7 +46,7 @@ class SendAnimation(Scaffold): file_name: str = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -111,8 +112,8 @@ class SendAnimation(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -222,7 +223,7 @@ class SendAnimation(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/methods/messages/send_audio.py b/pyrogram/methods/messages/send_audio.py index e00930af..6cef5b47 100644 --- a/pyrogram/methods/messages/send_audio.py +++ b/pyrogram/methods/messages/send_audio.py @@ -27,6 +27,7 @@ from pyrogram import utils from pyrogram.errors import FilePartMissing from pyrogram.file_id import FileType from pyrogram.scaffold import Scaffold +from datetime import datetime class SendAudio(Scaffold): @@ -44,7 +45,7 @@ class SendAudio(Scaffold): file_name: str = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -108,8 +109,8 @@ class SendAudio(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -216,7 +217,7 @@ class SendAudio(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/methods/messages/send_cached_media.py b/pyrogram/methods/messages/send_cached_media.py index 5c895121..60832553 100644 --- a/pyrogram/methods/messages/send_cached_media.py +++ b/pyrogram/methods/messages/send_cached_media.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, List, Optional from pyrogram import raw, enums @@ -34,7 +35,7 @@ class SendCachedMedia(Scaffold): caption_entities: List["types.MessageEntity"] = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -76,8 +77,8 @@ class SendCachedMedia(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -102,7 +103,7 @@ class SendCachedMedia(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/methods/messages/send_contact.py b/pyrogram/methods/messages/send_contact.py index f3965777..f9c84f4c 100644 --- a/pyrogram/methods/messages/send_contact.py +++ b/pyrogram/methods/messages/send_contact.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union from pyrogram import raw @@ -33,7 +34,7 @@ class SendContact(Scaffold): vcard: str = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -69,8 +70,8 @@ class SendContact(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -100,7 +101,7 @@ class SendContact(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) diff --git a/pyrogram/methods/messages/send_dice.py b/pyrogram/methods/messages/send_dice.py index dfc9d5b8..9c7f5d1a 100644 --- a/pyrogram/methods/messages/send_dice.py +++ b/pyrogram/methods/messages/send_dice.py @@ -21,6 +21,7 @@ from typing import Union, Optional from pyrogram import raw from pyrogram import types from pyrogram.scaffold import Scaffold +from datetime import datetime class SendDice(Scaffold): @@ -30,7 +31,7 @@ class SendDice(Scaffold): emoji: str = "🎲", disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -61,8 +62,8 @@ class SendDice(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -94,7 +95,7 @@ class SendDice(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, message="" diff --git a/pyrogram/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py index 4a35f8a5..5844d2d2 100644 --- a/pyrogram/methods/messages/send_document.py +++ b/pyrogram/methods/messages/send_document.py @@ -18,6 +18,7 @@ import os import re +from datetime import datetime from typing import Union, BinaryIO, List, Optional from pyrogram import StopTransmission, enums @@ -42,7 +43,7 @@ class SendDocument(Scaffold): force_document: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -100,8 +101,8 @@ class SendDocument(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -194,7 +195,7 @@ class SendDocument(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/methods/messages/send_location.py b/pyrogram/methods/messages/send_location.py index d2b6616d..6c33c1b4 100644 --- a/pyrogram/methods/messages/send_location.py +++ b/pyrogram/methods/messages/send_location.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union from pyrogram import raw @@ -31,7 +32,7 @@ class SendLocation(Scaffold): longitude: float, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -61,8 +62,8 @@ class SendLocation(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -92,7 +93,7 @@ class SendLocation(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) diff --git a/pyrogram/methods/messages/send_media_group.py b/pyrogram/methods/messages/send_media_group.py index 13d4d62a..04c91c3b 100644 --- a/pyrogram/methods/messages/send_media_group.py +++ b/pyrogram/methods/messages/send_media_group.py @@ -19,6 +19,7 @@ import logging import os import re +from datetime import datetime from typing import Union, List from pyrogram import raw @@ -43,7 +44,7 @@ class SendMediaGroup(Scaffold): ]], disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, ) -> List["types.Message"]: """Send a group of photos or videos as an album. @@ -64,8 +65,8 @@ class SendMediaGroup(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -381,7 +382,7 @@ class SendMediaGroup(Scaffold): multi_media=multi_media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content ), sleep_threshold=60 diff --git a/pyrogram/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py index 575aea33..a094ba92 100644 --- a/pyrogram/methods/messages/send_message.py +++ b/pyrogram/methods/messages/send_message.py @@ -22,6 +22,8 @@ from pyrogram import raw, utils, enums from pyrogram import types from pyrogram.scaffold import Scaffold +from datetime import datetime + class SendMessage(Scaffold): async def send_message( @@ -33,7 +35,7 @@ class SendMessage(Scaffold): disable_web_page_preview: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -70,8 +72,8 @@ class SendMessage(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -129,7 +131,7 @@ class SendMessage(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), reply_markup=await reply_markup.write(self) if reply_markup else None, message=message, entities=entities, @@ -150,11 +152,11 @@ class SendMessage(Scaffold): message_id=r.id, chat=types.Chat( id=peer_id, - type="private", + type=enums.ChatType.PRIVATE, client=self ), text=message, - date=r.date, + date=utils.timestamp_to_datetime(r.date), outgoing=r.out, reply_markup=reply_markup, entities=[ diff --git a/pyrogram/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py index 442b45ae..bf7b482c 100644 --- a/pyrogram/methods/messages/send_photo.py +++ b/pyrogram/methods/messages/send_photo.py @@ -18,6 +18,7 @@ import os import re +from datetime import datetime from typing import Union, BinaryIO, List, Optional import pyrogram @@ -40,7 +41,7 @@ class SendPhoto(Scaffold): ttl_seconds: int = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -88,8 +89,8 @@ class SendPhoto(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -172,7 +173,7 @@ class SendPhoto(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/methods/messages/send_poll.py b/pyrogram/methods/messages/send_poll.py index df27c057..a02c5266 100644 --- a/pyrogram/methods/messages/send_poll.py +++ b/pyrogram/methods/messages/send_poll.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, List from pyrogram import raw @@ -35,7 +36,7 @@ class SendPoll(Scaffold): correct_option_id: int = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -81,8 +82,8 @@ class SendPoll(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -120,7 +121,7 @@ class SendPoll(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) diff --git a/pyrogram/methods/messages/send_sticker.py b/pyrogram/methods/messages/send_sticker.py index 641cc635..76571d99 100644 --- a/pyrogram/methods/messages/send_sticker.py +++ b/pyrogram/methods/messages/send_sticker.py @@ -18,6 +18,7 @@ import os import re +from datetime import datetime from typing import Union, BinaryIO, Optional from pyrogram import StopTransmission @@ -36,7 +37,7 @@ class SendSticker(Scaffold): sticker: Union[str, BinaryIO], disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -69,8 +70,8 @@ class SendSticker(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -153,7 +154,7 @@ class SendSticker(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, message="" diff --git a/pyrogram/methods/messages/send_venue.py b/pyrogram/methods/messages/send_venue.py index 7941485e..5293cf01 100644 --- a/pyrogram/methods/messages/send_venue.py +++ b/pyrogram/methods/messages/send_venue.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union from pyrogram import raw @@ -35,7 +36,7 @@ class SendVenue(Scaffold): foursquare_type: str = "", disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -78,8 +79,8 @@ class SendVenue(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -116,7 +117,7 @@ class SendVenue(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py index f6dc00ee..96f2a9c3 100644 --- a/pyrogram/methods/messages/send_video.py +++ b/pyrogram/methods/messages/send_video.py @@ -18,6 +18,7 @@ import os import re +from datetime import datetime from typing import Union, BinaryIO, List, Optional from pyrogram import StopTransmission, enums @@ -46,7 +47,7 @@ class SendVideo(Scaffold): supports_streaming: bool = True, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -117,8 +118,8 @@ class SendVideo(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -228,7 +229,7 @@ class SendVideo(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/methods/messages/send_video_note.py b/pyrogram/methods/messages/send_video_note.py index 1e52f3ab..c2f0a159 100644 --- a/pyrogram/methods/messages/send_video_note.py +++ b/pyrogram/methods/messages/send_video_note.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . import os +from datetime import datetime from typing import Union, BinaryIO, Optional from pyrogram import StopTransmission @@ -38,7 +39,7 @@ class SendVideoNote(Scaffold): thumb: Union[str, BinaryIO] = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -83,8 +84,8 @@ class SendVideoNote(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -177,7 +178,7 @@ class SendVideoNote(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, message="" diff --git a/pyrogram/methods/messages/send_voice.py b/pyrogram/methods/messages/send_voice.py index c7e960fd..79fefcab 100644 --- a/pyrogram/methods/messages/send_voice.py +++ b/pyrogram/methods/messages/send_voice.py @@ -18,6 +18,7 @@ import os import re +from datetime import datetime from typing import Union, BinaryIO, List, Optional from pyrogram import StopTransmission, enums @@ -40,7 +41,7 @@ class SendVoice(Scaffold): duration: int = 0, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -86,8 +87,8 @@ class SendVoice(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -178,7 +179,7 @@ class SendVoice(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), - schedule_date=schedule_date, + schedule_date=utils.datetime_to_timestamp(schedule_date), noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) diff --git a/pyrogram/parser/parser.py b/pyrogram/parser/parser.py index 884e1755..35a15d0c 100644 --- a/pyrogram/parser/parser.py +++ b/pyrogram/parser/parser.py @@ -30,7 +30,7 @@ class Parser: self.html = HTML(client) self.markdown = Markdown(client) - async def parse(self, text: str, mode: Optional[str] = None): + async def parse(self, text: str, mode: Optional[enums.ParseMode] = None): text = str(text if text else "").strip() if mode is None: diff --git a/pyrogram/types/messages_and_media/animation.py b/pyrogram/types/messages_and_media/animation.py index ce901734..1e7bf4cf 100644 --- a/pyrogram/types/messages_and_media/animation.py +++ b/pyrogram/types/messages_and_media/animation.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType from ..object import Object @@ -54,8 +55,8 @@ class Animation(Object): file_size (``int``, *optional*): File size. - date (``int``, *optional*): - Date the animation was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the animation was sent. thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*): Animation thumbnails. @@ -73,7 +74,7 @@ class Animation(Object): file_name: str = None, mime_type: str = None, file_size: int = None, - date: int = None, + date: datetime = None, thumbs: List["types.Thumbnail"] = None ): super().__init__(client) @@ -114,7 +115,7 @@ class Animation(Object): mime_type=animation.mime_type, file_size=animation.size, file_name=file_name, - date=animation.date, + date=utils.timestamp_to_datetime(animation.date), thumbs=types.Thumbnail._parse(client, animation), client=client ) diff --git a/pyrogram/types/messages_and_media/audio.py b/pyrogram/types/messages_and_media/audio.py index 60b37a59..e474282f 100644 --- a/pyrogram/types/messages_and_media/audio.py +++ b/pyrogram/types/messages_and_media/audio.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType from ..object import Object @@ -54,8 +55,8 @@ class Audio(Object): file_size (``int``, *optional*): File size. - date (``int``, *optional*): - Date the audio was originally sent, in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the audio was originally sent. thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*): Thumbnails of the music file album cover. @@ -73,7 +74,7 @@ class Audio(Object): file_name: str = None, mime_type: str = None, file_size: int = None, - date: int = None, + date: datetime = None, thumbs: List["types.Thumbnail"] = None ): super().__init__(client) @@ -114,7 +115,7 @@ class Audio(Object): mime_type=audio.mime_type, file_size=audio.size, file_name=file_name, - date=audio.date, + date=utils.timestamp_to_datetime(audio.date), thumbs=types.Thumbnail._parse(client, audio), client=client ) diff --git a/pyrogram/types/messages_and_media/document.py b/pyrogram/types/messages_and_media/document.py index 333d38ab..95ebe3f2 100644 --- a/pyrogram/types/messages_and_media/document.py +++ b/pyrogram/types/messages_and_media/document.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType from ..object import Object @@ -45,8 +46,8 @@ class Document(Object): file_size (``int``, *optional*): File size. - date (``int``, *optional*): - Date the document was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the document was sent. thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*): Document thumbnails as defined by sender. @@ -61,7 +62,7 @@ class Document(Object): file_name: str = None, mime_type: str = None, file_size: int = None, - date: int = None, + date: datetime = None, thumbs: List["types.Thumbnail"] = None ): super().__init__(client) @@ -91,7 +92,7 @@ class Document(Object): file_name=file_name, mime_type=document.mime_type, file_size=document.size, - date=document.date, + date=utils.timestamp_to_datetime(document.date), thumbs=types.Thumbnail._parse(client, document), client=client ) diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index 2c2f7e05..86c340ae 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -17,6 +17,7 @@ # along with Pyrogram. If not, see . import logging +from datetime import datetime from functools import partial from typing import List, Match, Union, BinaryIO, Optional @@ -71,8 +72,8 @@ class Message(Object, Update): The supergroup itself for messages from anonymous group administrators. The linked channel for messages automatically forwarded to the discussion group. - date (``int``, *optional*): - Date the message was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the message was sent. chat (:obj:`~pyrogram.types.Chat`, *optional*): Conversation the message belongs to. @@ -92,8 +93,8 @@ class Message(Object, Update): forward_signature (``str``, *optional*): For messages forwarded from channels, signature of the post author if present. - forward_date (``int``, *optional*): - For forwarded messages, date the original message was sent in Unix time. + forward_date (:py:obj:`~datetime.datetime`, *optional*): + For forwarded messages, date the original message was sent. reply_to_message_id (``int``, *optional*): The id of the message which this message directly replied to. @@ -122,8 +123,8 @@ class Message(Object, Update): This field will contain the enumeration type of the media message. You can use ``media = getattr(message, message.media.value)`` to access the media message. - edit_date (``int``, *optional*): - Date the message was last edited in Unix time. + edit_date (:py:obj:`~datetime.datetime`, *optional*): + Date the message was last edited. media_group_id (``str``, *optional*): The unique identifier of a media message group this message belongs to. @@ -304,14 +305,14 @@ class Message(Object, Update): message_id: int, from_user: "types.User" = None, sender_chat: "types.Chat" = None, - date: int = None, + date: datetime = None, chat: "types.Chat" = None, forward_from: "types.User" = None, forward_sender_name: str = None, forward_from_chat: "types.Chat" = None, forward_from_message_id: int = None, forward_signature: str = None, - forward_date: int = None, + forward_date: datetime = None, reply_to_message_id: int = None, reply_to_top_message_id: int = None, reply_to_message: "Message" = None, @@ -321,7 +322,7 @@ class Message(Object, Update): scheduled: bool = None, from_scheduled: bool = None, media: str = None, - edit_date: int = None, + edit_date: datetime = None, media_group_id: str = None, author_signature: str = None, has_protected_content: bool = None, @@ -542,7 +543,7 @@ class Message(Object, Update): parsed_message = Message( message_id=message.id, - date=message.date, + date=utils.timestamp_to_datetime(message.date), chat=types.Chat._parse(client, message, users, chats, is_chat=True), from_user=from_user, sender_chat=sender_chat, @@ -607,7 +608,7 @@ class Message(Object, Update): forward_header = message.fwd_from # type: raw.types.MessageFwdHeader if forward_header: - forward_date = forward_header.date + forward_date = utils.timestamp_to_datetime(forward_header.date) if forward_header.from_id: raw_peer_id = utils.get_raw_peer_id(forward_header.from_id) @@ -739,7 +740,7 @@ class Message(Object, Update): parsed_message = Message( message_id=message.id, - date=message.date, + date=utils.timestamp_to_datetime(message.date), chat=types.Chat._parse(client, message, users, chats, is_chat=True), from_user=from_user, sender_chat=sender_chat, @@ -775,7 +776,7 @@ class Message(Object, Update): scheduled=is_scheduled, from_scheduled=message.from_scheduled, media=media_type, - edit_date=message.edit_date, + edit_date=utils.timestamp_to_datetime(message.edit_date), media_group_id=message.grouped_id, photo=photo, location=location, @@ -864,7 +865,7 @@ class Message(Object, Update): disable_web_page_preview: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup = None ) -> "Message": @@ -913,8 +914,8 @@ class Message(Object, Update): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. @@ -1449,7 +1450,7 @@ class Message(Object, Update): force_document: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -1519,8 +1520,8 @@ class Message(Object, Update): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, @@ -1982,7 +1983,7 @@ class Message(Object, Update): correct_option_id: int = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -2042,8 +2043,8 @@ class Message(Object, Update): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, @@ -2859,7 +2860,7 @@ class Message(Object, Update): self, chat_id: Union[int, str], disable_notification: bool = None, - schedule_date: int = None + schedule_date: datetime = None ) -> Union["types.Message", List["types.Message"]]: """Bound method *forward* of :obj:`~pyrogram.types.Message`. @@ -2888,8 +2889,8 @@ class Message(Object, Update): Sends the message silently. Users will receive a notification with no sound. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. Returns: On success, the forwarded Message is returned. @@ -2913,7 +2914,7 @@ class Message(Object, Update): caption_entities: List["types.MessageEntity"] = None, disable_notification: bool = None, reply_to_message_id: int = None, - schedule_date: int = None, + schedule_date: datetime = None, protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", @@ -2964,8 +2965,8 @@ class Message(Object, Update): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. - schedule_date (``int``, *optional*): - Date when the message will be automatically sent. Unix time. + schedule_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the message will be automatically sent. protect_content (``bool``, *optional*): Protects the contents of the sent message from forwarding and saving. diff --git a/pyrogram/types/messages_and_media/photo.py b/pyrogram/types/messages_and_media/photo.py index fc496cd4..d6ad9226 100644 --- a/pyrogram/types/messages_and_media/photo.py +++ b/pyrogram/types/messages_and_media/photo.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource from ..object import Object @@ -45,8 +46,8 @@ class Photo(Object): file_size (``int``): File size. - date (``int``): - Date the photo was sent in Unix time. + date (:py:obj:`~datetime.datetime`): + Date the photo was sent. ttl_seconds (``int``, *optional*): Time-to-live seconds, for secret photos. @@ -64,7 +65,7 @@ class Photo(Object): width: int, height: int, file_size: int, - date: int, + date: datetime, ttl_seconds: int = None, thumbs: List["types.Thumbnail"] = None ): @@ -122,7 +123,7 @@ class Photo(Object): width=main.w, height=main.h, file_size=main.size, - date=photo.date, + date=utils.timestamp_to_datetime(photo.date), ttl_seconds=ttl_seconds, thumbs=types.Thumbnail._parse(client, photo), client=client diff --git a/pyrogram/types/messages_and_media/sticker.py b/pyrogram/types/messages_and_media/sticker.py index bd08792f..fa6e0be3 100644 --- a/pyrogram/types/messages_and_media/sticker.py +++ b/pyrogram/types/messages_and_media/sticker.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.errors import StickersetInvalid from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType @@ -58,8 +59,8 @@ class Sticker(Object): file_size (``int``, *optional*): File size. - date (``int``, *optional*): - Date the sticker was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the sticker was sent. emoji (``str``, *optional*): Emoji associated with the sticker. @@ -86,7 +87,7 @@ class Sticker(Object): file_name: str = None, mime_type: str = None, file_size: int = None, - date: int = None, + date: datetime = None, emoji: str = None, set_name: str = None, thumbs: List["types.Thumbnail"] = None @@ -179,7 +180,7 @@ class Sticker(Object): file_size=sticker.size, mime_type=sticker.mime_type, file_name=file_name, - date=sticker.date, + date=utils.timestamp_to_datetime(sticker.date), thumbs=types.Thumbnail._parse(client, sticker), client=client ) diff --git a/pyrogram/types/messages_and_media/video.py b/pyrogram/types/messages_and_media/video.py index 1cdf055f..b50f9fca 100644 --- a/pyrogram/types/messages_and_media/video.py +++ b/pyrogram/types/messages_and_media/video.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType from ..object import Object @@ -60,8 +61,8 @@ class Video(Object): ttl_seconds (``int``. *optional*): Time-to-live seconds, for secret photos. - date (``int``, *optional*): - Date the video was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the video was sent. thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*): Video thumbnails. @@ -81,7 +82,7 @@ class Video(Object): file_size: int = None, supports_streaming: bool = None, ttl_seconds: int = None, - date: int = None, + date: datetime = None, thumbs: List["types.Thumbnail"] = None ): super().__init__(client) @@ -126,7 +127,7 @@ class Video(Object): mime_type=video.mime_type, supports_streaming=video_attributes.supports_streaming, file_size=video.size, - date=video.date, + date=utils.timestamp_to_datetime(video.date), ttl_seconds=ttl_seconds, thumbs=types.Thumbnail._parse(client, video), client=client diff --git a/pyrogram/types/messages_and_media/video_note.py b/pyrogram/types/messages_and_media/video_note.py index 3a9e8a61..450d536d 100644 --- a/pyrogram/types/messages_and_media/video_note.py +++ b/pyrogram/types/messages_and_media/video_note.py @@ -19,10 +19,11 @@ from typing import List import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType from ..object import Object +from datetime import datetime class VideoNote(Object): @@ -48,8 +49,8 @@ class VideoNote(Object): file_size (``int``, *optional*): File size. - date (``int``, *optional*): - Date the video note was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the video note was sent. thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*): Video thumbnails. @@ -66,7 +67,7 @@ class VideoNote(Object): thumbs: List["types.Thumbnail"] = None, mime_type: str = None, file_size: int = None, - date: int = None + date: datetime = None ): super().__init__(client) @@ -101,7 +102,7 @@ class VideoNote(Object): duration=video_attributes.duration, file_size=video_note.size, mime_type=video_note.mime_type, - date=video_note.date, + date=utils.timestamp_to_datetime(video_note.date), thumbs=types.Thumbnail._parse(client, video_note), client=client ) diff --git a/pyrogram/types/messages_and_media/voice.py b/pyrogram/types/messages_and_media/voice.py index 4175b7ba..8d1c15f6 100644 --- a/pyrogram/types/messages_and_media/voice.py +++ b/pyrogram/types/messages_and_media/voice.py @@ -16,8 +16,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime + import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType from ..object import Object @@ -45,8 +47,8 @@ class Voice(Object): file_size (``int``, *optional*): File size. - date (``int``, *optional*): - Date the voice was sent in Unix time. + date (:py:obj:`~datetime.datetime`, *optional*): + Date the voice was sent. """ def __init__( @@ -59,7 +61,7 @@ class Voice(Object): waveform: bytes = None, mime_type: str = None, file_size: int = None, - date: int = None + date: datetime = None ): super().__init__(client) @@ -89,6 +91,6 @@ class Voice(Object): mime_type=voice.mime_type, file_size=voice.size, waveform=attributes.waveform, - date=voice.date, + date=utils.timestamp_to_datetime(voice.date), client=client ) diff --git a/pyrogram/types/object.py b/pyrogram/types/object.py index a0925779..a3641b16 100644 --- a/pyrogram/types/object.py +++ b/pyrogram/types/object.py @@ -56,14 +56,14 @@ class Object(metaclass=Meta): if isinstance(obj, Enum): return str(obj) + if isinstance(obj, datetime): + return str(obj) + return { "_": obj.__class__.__name__, **{ attr: ( - "*" * 9 - if attr == "phone_number" else - str(datetime.fromtimestamp(getattr(obj, attr))) - if attr.endswith("date") else + "*" * 9 if attr == "phone_number" else getattr(obj, attr) ) for attr in filter(lambda x: not x.startswith("_"), obj.__dict__) diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py index 2282b1e0..870391a4 100644 --- a/pyrogram/types/user_and_chats/chat.py +++ b/pyrogram/types/user_and_chats/chat.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, List, Generator, Optional import pyrogram @@ -513,7 +514,7 @@ class Chat(Object): async def ban_member( self, user_id: Union[int, str], - until_date: int = 0 + until_date: datetime = datetime.fromtimestamp(0) ) -> Union["types.Message", bool]: """Bound method *ban_member* of :obj:`~pyrogram.types.Chat`. @@ -541,10 +542,10 @@ class Chat(Object): Unique identifier (int) or username (str) of the target user. For a contact that exists in your Telegram address book you can use his phone number (str). - until_date (``int``, *optional*): - Date when the user will be unbanned, unix time. + until_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the user will be unbanned. If user is banned for more than 366 days or less than 30 seconds from the current time they are - considered to be banned forever. Defaults to 0 (ban forever). + considered to be banned forever. Defaults to epoch (ban forever). Returns: :obj:`~pyrogram.types.Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in @@ -601,7 +602,7 @@ class Chat(Object): self, user_id: Union[int, str], permissions: "types.ChatPermissions", - until_date: int = 0, + until_date: datetime = datetime.fromtimestamp(0), ) -> "types.Chat": """Bound method *unban_member* of :obj:`~pyrogram.types.Chat`. @@ -628,10 +629,10 @@ class Chat(Object): permissions (:obj:`~pyrogram.types.ChatPermissions`): New user permissions. - until_date (``int``, *optional*): - Date when the user will be unbanned, unix time. + until_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the user will be unbanned. If user is banned for more than 366 days or less than 30 seconds from the current time they are - considered to be banned forever. Defaults to 0 (ban forever). + considered to be banned forever. Defaults to epoch (ban forever). Returns: :obj:`~pyrogram.types.Chat`: On success, a chat object is returned. diff --git a/pyrogram/types/user_and_chats/chat_event.py b/pyrogram/types/user_and_chats/chat_event.py index 3abfd1f9..fa539be8 100644 --- a/pyrogram/types/user_and_chats/chat_event.py +++ b/pyrogram/types/user_and_chats/chat_event.py @@ -16,57 +16,15 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from enum import Enum, auto +from datetime import datetime from typing import List, Optional import pyrogram from pyrogram import raw -from pyrogram import types +from pyrogram import types, utils, enums from ..object import Object -class AutoName(Enum): - def _generate_next_value_(self, *args): - return self.lower() - - -class ChatEventAction(AutoName): - DESCRIPTION_CHANGED = auto() - HISTORY_TTL_CHANGED = auto() - LINKED_CHAT_CHANGED = auto() - # LOCATION_CHANGED = auto() - PHOTO_CHANGED = auto() - # STICKER_SET_CHANGED = auto() - TITLE_CHANGED = auto() - USERNAME_CHANGED = auto() - CHAT_PERMISSIONS_CHANGED = auto() - MESSAGE_DELETED = auto() - # VOICE_CHAT_DISCARDED = auto() - MESSAGE_EDITED = auto() - INVITE_LINK_EDITED = auto() - INVITE_LINK_REVOKED = auto() - INVITE_LINK_DELETED = auto() - MEMBER_INVITED = auto() - MEMBER_JOINED = auto() - # MEMBER_JOINED_BY_LINK = auto() - MEMBER_LEFT = auto() - # MEMBER_MUTED = auto() - ADMIN_RIGHTS_CHANGED = auto() - MEMBER_PERMISSIONS_CHANGED = auto() - # MEMBER_UNMUTED = auto() - # MEMBER_VOLUME_CHANGED = auto() - # VOICE_CHAT_STARTED = auto() - POLL_STOPPED = auto() - # VOICE_CHAT_SETTINGS_CHANGED = auto() - INVITES_ENABLED = auto() - HISTORY_HIDDEN = auto() - SIGNATURES_ENABLED = auto() - SLOW_MODE_CHANGED = auto() - MESSAGE_PINNED = auto() - MESSAGE_UNPINNED = auto() - UNKNOWN = auto() - - class ChatEvent(Object): """A chat event from the recent actions log (also known as admin log). @@ -76,8 +34,8 @@ class ChatEvent(Object): id (``int``): Chat event identifier. - date (``int``): - Date of the event. Unix time. + date (:py:obj:`~datetime.datetime`): + Date of the event. action (:obj:`~pyrogram.enums.ChatEventAction`): Event action. @@ -177,7 +135,7 @@ class ChatEvent(Object): def __init__( self, *, id: int, - date: int, + date: datetime, user: "types.User", action: str, @@ -232,7 +190,7 @@ class ChatEvent(Object): old_invite_link: "types.ChatInviteLink" = None, new_invite_link: "types.ChatInviteLink" = None, revoked_invite_link: "types.ChatInviteLink" = None, - deleted_invite_link: "types.ChatInviteLink" = None, + deleted_invite_link: "types.ChatInviteLink" = None ): super().__init__() @@ -296,10 +254,10 @@ class ChatEvent(Object): @staticmethod async def _parse( - client: "pyrogram.Client", - event: "raw.base.ChannelAdminLogEvent", - users: List["raw.base.User"], - chats: List["raw.base.Chat"] + client: "pyrogram.Client", + event: "raw.base.ChannelAdminLogEvent", + users: List["raw.base.User"], + chats: List["raw.base.Chat"] ): users = {i.id: i for i in users} chats = {i.id: i for i in chats} @@ -363,117 +321,117 @@ class ChatEvent(Object): if isinstance(action, raw.types.ChannelAdminLogEventActionChangeAbout): old_description = action.prev_value new_description = action.new_value - action = ChatEventAction.DESCRIPTION_CHANGED + action = enums.ChatEventAction.DESCRIPTION_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeHistoryTTL): old_history_ttl = action.prev_value new_history_ttl = action.new_value - action = ChatEventAction.HISTORY_TTL_CHANGED + action = enums.ChatEventAction.HISTORY_TTL_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeLinkedChat): old_linked_chat = types.Chat._parse_chat(client, chats[action.prev_value]) new_linked_chat = types.Chat._parse_chat(client, chats[action.new_value]) - action = ChatEventAction.LINKED_CHAT_CHANGED + action = enums.ChatEventAction.LINKED_CHAT_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangePhoto): old_photo = types.Photo._parse(client, action.prev_photo) new_photo = types.Photo._parse(client, action.new_photo) - action = ChatEventAction.PHOTO_CHANGED + action = enums.ChatEventAction.PHOTO_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeTitle): old_title = action.prev_value new_title = action.new_value - action = ChatEventAction.TITLE_CHANGED + action = enums.ChatEventAction.TITLE_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeUsername): old_username = action.prev_value new_username = action.new_value - action = ChatEventAction.USERNAME_CHANGED + action = enums.ChatEventAction.USERNAME_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionDefaultBannedRights): old_chat_permissions = types.ChatPermissions._parse(action.prev_banned_rights) new_chat_permissions = types.ChatPermissions._parse(action.new_banned_rights) - action = ChatEventAction.CHAT_PERMISSIONS_CHANGED + action = enums.ChatEventAction.CHAT_PERMISSIONS_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionDeleteMessage): deleted_message = await types.Message._parse(client, action.message, users, chats) - action = ChatEventAction.MESSAGE_DELETED + action = enums.ChatEventAction.MESSAGE_DELETED elif isinstance(action, raw.types.ChannelAdminLogEventActionEditMessage): old_message = await types.Message._parse(client, action.prev_message, users, chats) new_message = await types.Message._parse(client, action.new_message, users, chats) - action = ChatEventAction.MESSAGE_EDITED + action = enums.ChatEventAction.MESSAGE_EDITED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantInvite): invited_member = types.ChatMember._parse(client, action.participant, users, chats) - action = ChatEventAction.MEMBER_INVITED + action = enums.ChatEventAction.MEMBER_INVITED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantToggleAdmin): old_administrator_privileges = types.ChatMember._parse(client, action.prev_participant, users, chats) new_administrator_privileges = types.ChatMember._parse(client, action.new_participant, users, chats) - action = ChatEventAction.ADMIN_RIGHTS_CHANGED + action = enums.ChatEventAction.ADMIN_RIGHTS_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantToggleBan): old_member_permissions = types.ChatMember._parse(client, action.prev_participant, users, chats) new_member_permissions = types.ChatMember._parse(client, action.new_participant, users, chats) - action = ChatEventAction.MEMBER_PERMISSIONS_CHANGED + action = enums.ChatEventAction.MEMBER_PERMISSIONS_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionStopPoll): stopped_poll = await types.Message._parse(client, action.message, users, chats) - action = ChatEventAction.POLL_STOPPED + action = enums.ChatEventAction.POLL_STOPPED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantJoin): - action = ChatEventAction.MEMBER_JOINED + action = enums.ChatEventAction.MEMBER_JOINED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantLeave): - action = ChatEventAction.MEMBER_LEFT + action = enums.ChatEventAction.MEMBER_LEFT elif isinstance(action, raw.types.ChannelAdminLogEventActionToggleInvites): invites_enabled = action.new_value - action = ChatEventAction.INVITES_ENABLED + action = enums.ChatEventAction.INVITES_ENABLED elif isinstance(action, raw.types.ChannelAdminLogEventActionTogglePreHistoryHidden): history_hidden = action.new_value - action = ChatEventAction.HISTORY_HIDDEN + action = enums.ChatEventAction.HISTORY_HIDDEN elif isinstance(action, raw.types.ChannelAdminLogEventActionToggleSignatures): signatures_enabled = action.new_value - action = ChatEventAction.SIGNATURES_ENABLED + action = enums.ChatEventAction.SIGNATURES_ENABLED elif isinstance(action, raw.types.ChannelAdminLogEventActionToggleSlowMode): old_slow_mode = action.prev_value new_slow_mode = action.new_value - action = ChatEventAction.SLOW_MODE_CHANGED + action = enums.ChatEventAction.SLOW_MODE_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionUpdatePinned): message = action.message if message.pinned: pinned_message = await types.Message._parse(client, message, users, chats) - action = ChatEventAction.MESSAGE_PINNED + action = enums.ChatEventAction.MESSAGE_PINNED else: unpinned_message = await types.Message._parse(client, message, users, chats) - action = ChatEventAction.MESSAGE_UNPINNED + action = enums.ChatEventAction.MESSAGE_UNPINNED elif isinstance(action, raw.types.ChannelAdminLogEventActionExportedInviteEdit): old_invite_link = types.ChatInviteLink._parse(client, action.prev_invite, users) new_invite_link = types.ChatInviteLink._parse(client, action.new_invite, users) - action = ChatEventAction.INVITE_LINK_EDITED + action = enums.ChatEventAction.INVITE_LINK_EDITED elif isinstance(action, raw.types.ChannelAdminLogEventActionExportedInviteRevoke): revoked_invite_link = types.ChatInviteLink._parse(client, action.invite, users) - action = ChatEventAction.INVITE_LINK_REVOKED + action = enums.ChatEventAction.INVITE_LINK_REVOKED elif isinstance(action, raw.types.ChannelAdminLogEventActionExportedInviteDelete): deleted_invite_link = types.ChatInviteLink._parse(client, action.invite, users) - action = ChatEventAction.INVITE_LINK_DELETED + action = enums.ChatEventAction.INVITE_LINK_DELETED else: - action = f"{ChatEventAction.UNKNOWN}-{action.QUALNAME}" + action = f"{enums.ChatEventAction.UNKNOWN}-{action.QUALNAME}" return ChatEvent( id=event.id, - date=event.date, + date=utils.timestamp_to_datetime(event.date), user=user, action=action, old_description=old_description, diff --git a/pyrogram/types/user_and_chats/chat_invite_link.py b/pyrogram/types/user_and_chats/chat_invite_link.py index 9dddea48..7aaa56a8 100644 --- a/pyrogram/types/user_and_chats/chat_invite_link.py +++ b/pyrogram/types/user_and_chats/chat_invite_link.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Dict import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from ..object import Object @@ -32,8 +33,8 @@ class ChatInviteLink(Object): The invite link. If the link was created by another chat administrator, then the second part of the link will be replaced with "...". - date (``int``): - The date in Unix timestamp when the link was created. + date (:py:obj:`~datetime.datetime`): + The date when the link was created. is_primary (``bool``): True, if the link is primary. @@ -50,8 +51,11 @@ class ChatInviteLink(Object): creates_join_request (``bool``, *optional*): True, if users joining the chat via the link need to be approved by chat administrators. - expire_date (``int``, *optional*): - Point in time (Unix timestamp) when the link will expire or has been expired. + start_date (:py:obj:`~datetime.datetime`, *optional*): + Point in time when the link has been edited. + + expire_date (:py:obj:`~datetime.datetime`, *optional*): + Point in time when the link will expire or has been expired. member_limit (``int``, *optional*): Maximum number of users that can be members of the chat simultaneously after joining the chat via this @@ -67,14 +71,14 @@ class ChatInviteLink(Object): def __init__( self, *, invite_link: str, - date: int, + date: datetime, is_primary: bool = None, is_revoked: bool = None, creator: "types.User" = None, name: str = None, creates_join_request: bool = None, - start_date: int = None, - expire_date: int = None, + start_date: datetime = None, + expire_date: datetime = None, member_limit: int = None, member_count: int = None, pending_join_request_count: int = None @@ -108,13 +112,14 @@ class ChatInviteLink(Object): return ChatInviteLink( invite_link=invite.link, - date=invite.date, + date=utils.timestamp_to_datetime(invite.date), is_primary=invite.permanent, is_revoked=invite.revoked, creator=creator, name=invite.title, creates_join_request=invite.request_needed, - expire_date=invite.expire_date, + start_date=utils.timestamp_to_datetime(invite.start_date), + expire_date=utils.timestamp_to_datetime(invite.expire_date), member_limit=invite.usage_limit, member_count=invite.usage, pending_join_request_count=invite.requested diff --git a/pyrogram/types/user_and_chats/chat_join_request.py b/pyrogram/types/user_and_chats/chat_join_request.py index fe051de4..ee9da3ef 100644 --- a/pyrogram/types/user_and_chats/chat_join_request.py +++ b/pyrogram/types/user_and_chats/chat_join_request.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Dict import pyrogram @@ -35,8 +36,8 @@ class ChatJoinRequest(Object, Update): from_user (:obj:`~pyrogram.types.User`): User that sent the join request. - date (``int``): - Date the request was sent in Unix time + date (:py:obj:`~datetime.datetime`): + Date the request was sent. bio (``str``, *optional*): Bio of the user. @@ -51,7 +52,7 @@ class ChatJoinRequest(Object, Update): client: "pyrogram.Client" = None, chat: "types.Chat", from_user: "types.User", - date: int, + date: datetime, bio: str = None, invite_link: "types.ChatInviteLink" = None ): @@ -75,7 +76,7 @@ class ChatJoinRequest(Object, Update): return ChatJoinRequest( chat=types.Chat._parse_chat(client, chats[chat_id]), from_user=types.User._parse(client, users[update.user_id]), - date=update.date, + date=utils.timestamp_to_datetime(update.date), bio=update.about, invite_link=types.ChatInviteLink._parse(client, update.invite, users), client=client diff --git a/pyrogram/types/user_and_chats/chat_member.py b/pyrogram/types/user_and_chats/chat_member.py index dc00354f..06f45b8d 100644 --- a/pyrogram/types/user_and_chats/chat_member.py +++ b/pyrogram/types/user_and_chats/chat_member.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Union, Dict import pyrogram @@ -36,17 +37,17 @@ class ChatMember(Object): chat (:obj:`~pyrogram.types.Chat`, *optional*): Information about the chat (useful in case of banned channel senders). - joined_date (``int``, *optional*): - Date when the user joined, unix time. + joined_date (:py:obj:`~datetime.datetime`, *optional*): + Date when the user joined.. Not available for the owner. custom_title (``str``, *optional*): A custom title that will be shown to all members instead of "Owner" or "Admin". Creator (owner) and administrators only. Can be None in case there's no custom title set. - until_date (``int``, *optional*): + until_date (:py:obj:`~datetime.datetime`, *optional*): Restricted and banned only. - Date when restrictions will be lifted for this user; unix time. + Date when restrictions will be lifted for this user. invited_by (:obj:`~pyrogram.types.User`, *optional*): Administrators and self member only. Information about the user who invited this member. @@ -79,8 +80,8 @@ class ChatMember(Object): user: "types.User" = None, chat: "types.Chat" = None, custom_title: str = None, - until_date: int = None, - joined_date: int = None, + until_date: datetime = None, + joined_date: datetime = None, invited_by: "types.User" = None, promoted_by: "types.User" = None, restricted_by: "types.User" = None, @@ -109,15 +110,15 @@ class ChatMember(Object): def _parse( client: "pyrogram.Client", member: Union["raw.base.ChatParticipant", "raw.base.ChannelParticipant"], - users: Dict[int, "raw.base.User"], - chats: Dict[int, "raw.base.Chat"] + users: Dict[int, "raw.base.User"], + chats: Dict[int, "raw.base.Chat"] ) -> "ChatMember": # Chat participants if isinstance(member, raw.types.ChatParticipant): return ChatMember( status=enums.ChatMemberStatus.MEMBER, user=types.User._parse(client, users[member.user_id]), - joined_date=member.date, + joined_date=utils.timestamp_to_datetime(member.date), invited_by=types.User._parse(client, users[member.inviter_id]), client=client ) @@ -125,7 +126,7 @@ class ChatMember(Object): return ChatMember( status=enums.ChatMemberStatus.ADMINISTRATOR, user=types.User._parse(client, users[member.user_id]), - joined_date=member.date, + joined_date=utils.timestamp_to_datetime(member.date), invited_by=types.User._parse(client, users[member.inviter_id]), client=client ) @@ -141,14 +142,14 @@ class ChatMember(Object): return ChatMember( status=enums.ChatMemberStatus.MEMBER, user=types.User._parse(client, users[member.user_id]), - joined_date=member.date, + joined_date=utils.timestamp_to_datetime(member.date), client=client ) elif isinstance(member, raw.types.ChannelParticipantAdmin): return ChatMember( status=enums.ChatMemberStatus.ADMINISTRATOR, user=types.User._parse(client, users[member.user_id]), - joined_date=member.date, + joined_date=utils.timestamp_to_datetime(member.date), promoted_by=types.User._parse(client, users[member.promoted_by]), invited_by=types.User._parse(client, users[member.inviter_id]), custom_title=member.rank, @@ -178,8 +179,8 @@ class ChatMember(Object): ), user=user, chat=chat, - until_date=member.banned_rights.until_date, - joined_date=member.date, + until_date=utils.timestamp_to_datetime(member.banned_rights.until_date), + joined_date=utils.timestamp_to_datetime(member.date), is_member=not member.left, restricted_by=types.User._parse(client, users[member.kicked_by]), permissions=types.ChatPermissions._parse(member.banned_rights), @@ -217,7 +218,7 @@ class ChatMember(Object): return ChatMember( status=enums.ChatMemberStatus.MEMBER, user=types.User._parse(client, users[member.user_id]), - joined_date=member.date, + joined_date=utils.timestamp_to_datetime(member.date), invited_by=types.User._parse(client, users[member.inviter_id]), client=client ) diff --git a/pyrogram/types/user_and_chats/chat_member_updated.py b/pyrogram/types/user_and_chats/chat_member_updated.py index 5fa7d84e..f8b6638d 100644 --- a/pyrogram/types/user_and_chats/chat_member_updated.py +++ b/pyrogram/types/user_and_chats/chat_member_updated.py @@ -16,10 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from datetime import datetime from typing import Dict, Union import pyrogram -from pyrogram import raw +from pyrogram import raw, utils from pyrogram import types from ..object import Object from ..update import Update @@ -35,8 +36,8 @@ class ChatMemberUpdated(Object, Update): from_user (:obj:`~pyrogram.types.User`): Performer of the action, which resulted in the change. - date (``int``): - Date the change was done in Unix time. + date (:py:obj:`~datetime.datetime`): + Date the change was done. old_chat_member (:obj:`~pyrogram.types.ChatMember`, *optional*): Previous information about the chat member. @@ -54,7 +55,7 @@ class ChatMemberUpdated(Object, Update): client: "pyrogram.Client" = None, chat: "types.Chat", from_user: "types.User", - date: int, + date: datetime, old_chat_member: "types.ChatMember", new_chat_member: "types.ChatMember", invite_link: "types.ChatInviteLink" = None, @@ -93,7 +94,7 @@ class ChatMemberUpdated(Object, Update): return ChatMemberUpdated( chat=types.Chat._parse_chat(client, chats[chat_id]), from_user=types.User._parse(client, users[update.actor_id]), - date=update.date, + date=utils.timestamp_to_datetime(update.date), old_chat_member=old_chat_member, new_chat_member=new_chat_member, invite_link=invite_link, diff --git a/pyrogram/types/user_and_chats/invite_link_importer.py b/pyrogram/types/user_and_chats/invite_link_importer.py index db8569f5..34e5f397 100644 --- a/pyrogram/types/user_and_chats/invite_link_importer.py +++ b/pyrogram/types/user_and_chats/invite_link_importer.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from pyrogram import raw +from datetime import datetime + +from pyrogram import raw, utils from pyrogram import types from ..object import Object @@ -25,14 +27,18 @@ class InviteLinkImporter(Object): """The date and user of when someone has joined with an invite link. Parameters: - date (``int``): - The unix time of when this user used the given link + date (:py:obj:`~datetime.datetime`): + The time of when this user used the given link user (:obj:`~pyrogram.types.User`): The user that has used the given invite link """ - def __init__(self, *, date, user): + def __init__( + self, *, + date: datetime, + user: "types.User" + ): super().__init__(None) self.date = date @@ -47,7 +53,7 @@ class InviteLinkImporter(Object): for j in invite_importers.importers: importers.append( InviteLinkImporter( - date=j.date, + date=utils.timestamp_to_datetime(j.date), user=types.User._parse(client=None, user=d[j.user_id]) ) ) diff --git a/pyrogram/types/user_and_chats/user.py b/pyrogram/types/user_and_chats/user.py index f4678a35..2ec09fb5 100644 --- a/pyrogram/types/user_and_chats/user.py +++ b/pyrogram/types/user_and_chats/user.py @@ -17,10 +17,11 @@ # along with Pyrogram. If not, see . import html +from datetime import datetime from typing import List, Optional import pyrogram -from pyrogram import enums +from pyrogram import enums, utils from pyrogram import raw from pyrogram import types from ..object import Object @@ -103,13 +104,13 @@ class User(Object, Update): User's or bot's last name. status (:obj:`~pyrogram.enums.UserStatus`, *optional*): - User's last seen & online status. *None*, for bots. + User's last seen & online status. ``None``, for bots. - last_online_date (``int``, *optional*): - Last online date of a user, unix time. Only available in case status is "*offline*". + last_online_date (:py:obj:`~datetime.datetime`, *optional*): + Last online date of a user. Only available in case status is :obj:`~pyrogram.enums.UserStatus.OFFLINE`. - next_offline_date (``int``, *optional*): - Date when a user will automatically go offline, unix time. Only available in case status is "*online*". + next_offline_date (:py:obj:`~datetime.datetime`, *optional*): + Date when a user will automatically go offline. Only available in case status is :obj:`~pyrogram.enums.UserStatus.ONLINE`. username (``str``, *optional*): User's or bot's username. @@ -158,8 +159,8 @@ class User(Object, Update): first_name: str = None, last_name: str = None, status: str = None, - last_online_date: int = None, - next_offline_date: int = None, + last_online_date: datetime = None, + next_offline_date: datetime = None, username: str = None, language_code: str = None, dc_id: int = None, @@ -247,10 +248,10 @@ class User(Object, Update): status = None if status == enums.UserStatus.ONLINE: - next_offline_date = date + next_offline_date = utils.timestamp_to_datetime(date) if status == enums.UserStatus.OFFLINE: - last_online_date = date + last_online_date = utils.timestamp_to_datetime(date) return { "status": status, diff --git a/pyrogram/types/user_and_chats/voice_chat_scheduled.py b/pyrogram/types/user_and_chats/voice_chat_scheduled.py index 82d2125e..0bb00bc5 100644 --- a/pyrogram/types/user_and_chats/voice_chat_scheduled.py +++ b/pyrogram/types/user_and_chats/voice_chat_scheduled.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from pyrogram import raw +from datetime import datetime + +from pyrogram import raw, utils from ..object import Object @@ -24,13 +26,13 @@ class VoiceChatScheduled(Object): """A service message about a voice chat scheduled in the chat. Parameters: - start_date (``int``): - Point in time (Unix timestamp) when the voice chat is supposed to be started by a chat administrator. + start_date (:py:obj:`~datetime.datetime`): + Point in time when the voice chat is supposed to be started by a chat administrator. """ def __init__( self, *, - start_date: int + start_date: datetime ): super().__init__() @@ -38,4 +40,4 @@ class VoiceChatScheduled(Object): @staticmethod def _parse(action: "raw.types.MessageActionGroupCallScheduled") -> "VoiceChatScheduled": - return VoiceChatScheduled(start_date=action.schedule_date) + return VoiceChatScheduled(start_date=utils.timestamp_to_datetime(action.schedule_date)) diff --git a/pyrogram/utils.py b/pyrogram/utils.py index 6a0c8bac..94a54946 100644 --- a/pyrogram/utils.py +++ b/pyrogram/utils.py @@ -23,11 +23,12 @@ import hashlib import os import struct from concurrent.futures.thread import ThreadPoolExecutor +from datetime import datetime from getpass import getpass from typing import Union, List, Dict, Optional import pyrogram -from pyrogram import raw +from pyrogram import raw, enums from pyrogram import types from pyrogram.file_id import FileId, FileType, PHOTO_TYPES, DOCUMENT_TYPES @@ -294,7 +295,7 @@ def compute_password_check(r: raw.types.account.Password, password: str) -> raw. async def parse_text_entities( client: "pyrogram.Client", text: str, - parse_mode: str, + parse_mode: enums.ParseMode, entities: List["types.MessageEntity"] ) -> Dict[str, raw.base.MessageEntity]: if entities: @@ -310,3 +311,11 @@ async def parse_text_entities( "message": text, "entities": entities } + + +def timestamp_to_datetime(ts: Optional[int]) -> Optional[datetime]: + return datetime.fromtimestamp(ts) if ts else None + + +def datetime_to_timestamp(dt: Optional[datetime]) -> Optional[int]: + return int(dt.timestamp()) if dt else None