mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-30 13:57:54 +00:00
Merge develop -> asyncio
This commit is contained in:
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github: delivrance
|
||||||
|
custom: https://docs.pyrogram.org/support-pyrogram
|
@@ -333,6 +333,7 @@ def start():
|
|||||||
docstring_args = "No parameters required."
|
docstring_args = "No parameters required."
|
||||||
|
|
||||||
docstring_args = "Attributes:\n ID: ``{}``\n\n ".format(c.id) + docstring_args
|
docstring_args = "Attributes:\n ID: ``{}``\n\n ".format(c.id) + docstring_args
|
||||||
|
docstring_args = "Attributes:\n LAYER: ``{}``\n\n ".format(layer) + docstring_args
|
||||||
|
|
||||||
if c.section == "functions":
|
if c.section == "functions":
|
||||||
docstring_args += "\n\n Returns:\n " + get_docstring_arg_type(c.return_type)
|
docstring_args += "\n\n Returns:\n " + get_docstring_arg_type(c.return_type)
|
||||||
|
@@ -22,10 +22,13 @@ inputPeerSelf#7da07ec9 = InputPeer;
|
|||||||
inputPeerChat#179be863 chat_id:int = InputPeer;
|
inputPeerChat#179be863 chat_id:int = InputPeer;
|
||||||
inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
|
inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
|
||||||
inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer;
|
inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer;
|
||||||
|
inputPeerUserFromMessage#17bae2e6 peer:InputPeer msg_id:int user_id:int = InputPeer;
|
||||||
|
inputPeerChannelFromMessage#9c95f7bb peer:InputPeer msg_id:int channel_id:int = InputPeer;
|
||||||
|
|
||||||
inputUserEmpty#b98886cf = InputUser;
|
inputUserEmpty#b98886cf = InputUser;
|
||||||
inputUserSelf#f7c1b13f = InputUser;
|
inputUserSelf#f7c1b13f = InputUser;
|
||||||
inputUser#d8292816 user_id:int access_hash:long = InputUser;
|
inputUser#d8292816 user_id:int access_hash:long = InputUser;
|
||||||
|
inputUserFromMessage#2d117597 peer:InputPeer msg_id:int user_id:int = InputUser;
|
||||||
|
|
||||||
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
|
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
|
||||||
|
|
||||||
@@ -60,9 +63,12 @@ inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
|
|||||||
|
|
||||||
inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
|
inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
|
||||||
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
|
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
|
||||||
inputDocumentFileLocation#196683d9 id:long access_hash:long file_reference:bytes = InputFileLocation;
|
inputDocumentFileLocation#bad07584 id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
|
||||||
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
|
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
|
||||||
inputTakeoutFileLocation#29be5899 = InputFileLocation;
|
inputTakeoutFileLocation#29be5899 = InputFileLocation;
|
||||||
|
inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
|
||||||
|
inputPeerPhotoFileLocation#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation;
|
||||||
|
inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation;
|
||||||
|
|
||||||
peerUser#9db1bc6d user_id:int = Peer;
|
peerUser#9db1bc6d user_id:int = Peer;
|
||||||
peerChat#bad0e5bb chat_id:int = Peer;
|
peerChat#bad0e5bb chat_id:int = Peer;
|
||||||
@@ -79,14 +85,11 @@ storage.fileMov#4b09ebbc = storage.FileType;
|
|||||||
storage.fileMp4#b3cea0e4 = storage.FileType;
|
storage.fileMp4#b3cea0e4 = storage.FileType;
|
||||||
storage.fileWebp#1081464c = storage.FileType;
|
storage.fileWebp#1081464c = storage.FileType;
|
||||||
|
|
||||||
fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
|
|
||||||
fileLocation#91d11eb dc_id:int volume_id:long local_id:int secret:long file_reference:bytes = FileLocation;
|
|
||||||
|
|
||||||
userEmpty#200250ba id:int = User;
|
userEmpty#200250ba id:int = User;
|
||||||
user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
||||||
|
|
||||||
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
||||||
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
|
userProfilePhoto#ecd75d8c photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto;
|
||||||
|
|
||||||
userStatusEmpty#9d05049 = UserStatus;
|
userStatusEmpty#9d05049 = UserStatus;
|
||||||
userStatusOnline#edb93949 expires:int = UserStatus;
|
userStatusOnline#edb93949 expires:int = UserStatus;
|
||||||
@@ -98,11 +101,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
|||||||
chatEmpty#9ba2d800 id:int = Chat;
|
chatEmpty#9ba2d800 id:int = Chat;
|
||||||
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
||||||
chatForbidden#7328bdb id:int title:string = Chat;
|
chatForbidden#7328bdb id:int title:string = Chat;
|
||||||
channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||||
|
|
||||||
chatFull#22a235da flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int = ChatFull;
|
chatFull#1b7c9db3 flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
|
||||||
channelFull#1c87a71a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;
|
channelFull#9882e516 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.13?int pts:int = ChatFull;
|
||||||
|
|
||||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||||
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
||||||
@@ -112,11 +115,11 @@ chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0?
|
|||||||
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
|
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
|
||||||
|
|
||||||
chatPhotoEmpty#37c1011c = ChatPhoto;
|
chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||||
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
|
chatPhoto#475cdbd5 photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
|
||||||
|
|
||||||
messageEmpty#83e5de54 id:int = Message;
|
messageEmpty#83e5de54 id:int = Message;
|
||||||
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
|
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
|
||||||
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
|
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
|
||||||
|
|
||||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||||
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
|
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
|
||||||
@@ -147,7 +150,7 @@ messageActionHistoryClear#9fbab604 = MessageAction;
|
|||||||
messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
|
messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
|
||||||
messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
|
messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
|
||||||
messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
|
messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
|
||||||
messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
|
messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
|
||||||
messageActionScreenshotTaken#4792929b = MessageAction;
|
messageActionScreenshotTaken#4792929b = MessageAction;
|
||||||
messageActionCustomAction#fae69f56 message:string = MessageAction;
|
messageActionCustomAction#fae69f56 message:string = MessageAction;
|
||||||
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
||||||
@@ -155,10 +158,11 @@ messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:
|
|||||||
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
|
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
|
||||||
messageActionContactSignUp#f3f25f76 = MessageAction;
|
messageActionContactSignUp#f3f25f76 = MessageAction;
|
||||||
|
|
||||||
dialog#e4def5db flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
|
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
|
||||||
|
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||||
|
|
||||||
photoEmpty#2331b22d id:long = Photo;
|
photoEmpty#2331b22d id:long = Photo;
|
||||||
photo#9c477dd8 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> = Photo;
|
photo#d07504a5 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> dc_id:int = Photo;
|
||||||
|
|
||||||
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
||||||
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
||||||
@@ -196,7 +200,7 @@ inputReportReasonChildAbuse#adf44ee3 = ReportReason;
|
|||||||
inputReportReasonOther#e1746d0a text:string = ReportReason;
|
inputReportReasonOther#e1746d0a text:string = ReportReason;
|
||||||
inputReportReasonCopyright#9b89f93a = ReportReason;
|
inputReportReasonCopyright#9b89f93a = ReportReason;
|
||||||
|
|
||||||
userFull#8ea4a881 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int = UserFull;
|
userFull#745559cc flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int = UserFull;
|
||||||
|
|
||||||
contact#f911c994 user_id:int mutual:Bool = Contact;
|
contact#f911c994 user_id:int mutual:Bool = Contact;
|
||||||
|
|
||||||
@@ -221,7 +225,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
|
|||||||
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
||||||
|
|
||||||
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||||
messages.messagesSlice#a6c47aaa flags:# inexact:flags.1?true count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
messages.messagesSlice#c8edce1e flags:# inexact:flags.1?true count:int next_rate:flags.0?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||||
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||||
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
||||||
|
|
||||||
@@ -271,14 +275,14 @@ updateNotifySettings#bec268ef peer:NotifyPeer notify_settings:PeerNotifySettings
|
|||||||
updateServiceNotification#ebe46819 flags:# popup:flags.0?true inbox_date:flags.1?int type:string message:string media:MessageMedia entities:Vector<MessageEntity> = Update;
|
updateServiceNotification#ebe46819 flags:# popup:flags.0?true inbox_date:flags.1?int type:string message:string media:MessageMedia entities:Vector<MessageEntity> = Update;
|
||||||
updatePrivacy#ee3b272a key:PrivacyKey rules:Vector<PrivacyRule> = Update;
|
updatePrivacy#ee3b272a key:PrivacyKey rules:Vector<PrivacyRule> = Update;
|
||||||
updateUserPhone#12b9417b user_id:int phone:string = Update;
|
updateUserPhone#12b9417b user_id:int phone:string = Update;
|
||||||
updateReadHistoryInbox#9961fd5c peer:Peer max_id:int pts:int pts_count:int = Update;
|
updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update;
|
||||||
updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update;
|
updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update;
|
||||||
updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update;
|
updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update;
|
||||||
updateReadMessagesContents#68c13933 messages:Vector<int> pts:int pts_count:int = Update;
|
updateReadMessagesContents#68c13933 messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateChannelTooLong#eb0467fb flags:# channel_id:int pts:flags.0?int = Update;
|
updateChannelTooLong#eb0467fb flags:# channel_id:int pts:flags.0?int = Update;
|
||||||
updateChannel#b6d45656 channel_id:int = Update;
|
updateChannel#b6d45656 channel_id:int = Update;
|
||||||
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
|
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
|
||||||
updateReadChannelInbox#4214f37f channel_id:int max_id:int = Update;
|
updateReadChannelInbox#330b5424 flags:# folder_id:flags.0?int channel_id:int max_id:int still_unread_count:int pts:int = Update;
|
||||||
updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update;
|
updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update;
|
||||||
updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update;
|
updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update;
|
||||||
@@ -300,8 +304,8 @@ updateRecentStickers#9a422c20 = Update;
|
|||||||
updateConfig#a229dd06 = Update;
|
updateConfig#a229dd06 = Update;
|
||||||
updatePtsChanged#3354678f = Update;
|
updatePtsChanged#3354678f = Update;
|
||||||
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
|
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
|
||||||
updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update;
|
updateDialogPinned#6e6fe51c flags:# pinned:flags.0?true folder_id:flags.1?int peer:DialogPeer = Update;
|
||||||
updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector<DialogPeer> = Update;
|
updatePinnedDialogs#fa0f3ca2 flags:# folder_id:flags.1?int order:flags.0?Vector<DialogPeer> = Update;
|
||||||
updateBotWebhookJSON#8317c0c3 data:DataJSON = Update;
|
updateBotWebhookJSON#8317c0c3 data:DataJSON = Update;
|
||||||
updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update;
|
updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update;
|
||||||
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
|
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
|
||||||
@@ -318,6 +322,7 @@ updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
|
|||||||
updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
|
updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
|
||||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||||
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||||
|
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
||||||
|
|
||||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||||
|
|
||||||
@@ -344,7 +349,7 @@ upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes
|
|||||||
|
|
||||||
dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
|
dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
|
||||||
|
|
||||||
config#e6ca25f6 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
|
config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
|
||||||
|
|
||||||
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
||||||
|
|
||||||
@@ -413,6 +418,7 @@ inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
|
|||||||
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
||||||
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
|
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
|
||||||
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
|
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
|
||||||
|
inputPrivacyKeyPhoneNumber#352dafa = InputPrivacyKey;
|
||||||
|
|
||||||
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||||
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
||||||
@@ -420,6 +426,7 @@ privacyKeyPhoneCall#3d662b7b = PrivacyKey;
|
|||||||
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
||||||
privacyKeyForwards#69ec56a3 = PrivacyKey;
|
privacyKeyForwards#69ec56a3 = PrivacyKey;
|
||||||
privacyKeyProfilePhoto#96151fed = PrivacyKey;
|
privacyKeyProfilePhoto#96151fed = PrivacyKey;
|
||||||
|
privacyKeyPhoneNumber#d19ae46d = PrivacyKey;
|
||||||
|
|
||||||
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||||
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||||
@@ -427,6 +434,8 @@ inputPrivacyValueAllowUsers#131cc67f users:Vector<InputUser> = InputPrivacyRule;
|
|||||||
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
|
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
|
||||||
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
|
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
|
||||||
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
|
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
|
||||||
|
inputPrivacyValueAllowChatParticipants#4c81c1ba chats:Vector<int> = InputPrivacyRule;
|
||||||
|
inputPrivacyValueDisallowChatParticipants#d82363af chats:Vector<int> = InputPrivacyRule;
|
||||||
|
|
||||||
privacyValueAllowContacts#fffe1bac = PrivacyRule;
|
privacyValueAllowContacts#fffe1bac = PrivacyRule;
|
||||||
privacyValueAllowAll#65427b82 = PrivacyRule;
|
privacyValueAllowAll#65427b82 = PrivacyRule;
|
||||||
@@ -434,8 +443,10 @@ privacyValueAllowUsers#4d5bbe0c users:Vector<int> = PrivacyRule;
|
|||||||
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
|
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
|
||||||
privacyValueDisallowAll#8b73e763 = PrivacyRule;
|
privacyValueDisallowAll#8b73e763 = PrivacyRule;
|
||||||
privacyValueDisallowUsers#c7f49b7 users:Vector<int> = PrivacyRule;
|
privacyValueDisallowUsers#c7f49b7 users:Vector<int> = PrivacyRule;
|
||||||
|
privacyValueAllowChatParticipants#18be796b chats:Vector<int> = PrivacyRule;
|
||||||
|
privacyValueDisallowChatParticipants#acae0690 chats:Vector<int> = PrivacyRule;
|
||||||
|
|
||||||
account.privacyRules#554abb6f rules:Vector<PrivacyRule> users:Vector<User> = account.PrivacyRules;
|
account.privacyRules#50a04e45 rules:Vector<PrivacyRule> chats:Vector<Chat> users:Vector<User> = account.PrivacyRules;
|
||||||
|
|
||||||
accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;
|
accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;
|
||||||
|
|
||||||
@@ -459,7 +470,6 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess
|
|||||||
|
|
||||||
contactLinkUnknown#5f4f9247 = ContactLink;
|
contactLinkUnknown#5f4f9247 = ContactLink;
|
||||||
contactLinkNone#feedd3ad = ContactLink;
|
contactLinkNone#feedd3ad = ContactLink;
|
||||||
contactLinkHasPhone#268f3f59 = ContactLink;
|
|
||||||
contactLinkContact#d502c2d0 = ContactLink;
|
contactLinkContact#d502c2d0 = ContactLink;
|
||||||
|
|
||||||
webPageEmpty#eb1477e8 id:long = WebPage;
|
webPageEmpty#eb1477e8 id:long = WebPage;
|
||||||
@@ -485,13 +495,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
|
|||||||
chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
|
chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
|
||||||
|
|
||||||
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
|
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
|
||||||
chatInvite#db74f558 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:ChatPhoto participants_count:int participants:flags.4?Vector<User> = ChatInvite;
|
chatInvite#dfc2f58e flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:Photo participants_count:int participants:flags.4?Vector<User> = ChatInvite;
|
||||||
|
|
||||||
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
|
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
|
||||||
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
||||||
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
||||||
|
|
||||||
stickerSet#6a90bcb7 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize count:int hash:int = StickerSet;
|
stickerSet#eeb46f27 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
|
||||||
|
|
||||||
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
||||||
|
|
||||||
@@ -507,6 +517,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
|
|||||||
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
|
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
|
||||||
keyboardButtonGame#50f41ccf text:string = KeyboardButton;
|
keyboardButtonGame#50f41ccf text:string = KeyboardButton;
|
||||||
keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
|
keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
|
||||||
|
keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton;
|
||||||
|
inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton;
|
||||||
|
|
||||||
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
|
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
|
||||||
|
|
||||||
@@ -533,13 +545,14 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
|
|||||||
|
|
||||||
inputChannelEmpty#ee8c1e86 = InputChannel;
|
inputChannelEmpty#ee8c1e86 = InputChannel;
|
||||||
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
|
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
|
||||||
|
inputChannelFromMessage#2a286531 peer:InputPeer msg_id:int channel_id:int = InputChannel;
|
||||||
|
|
||||||
contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector<Chat> users:Vector<User> = contacts.ResolvedPeer;
|
contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector<Chat> users:Vector<User> = contacts.ResolvedPeer;
|
||||||
|
|
||||||
messageRange#ae30253 min_id:int max_id:int = MessageRange;
|
messageRange#ae30253 min_id:int max_id:int = MessageRange;
|
||||||
|
|
||||||
updates.channelDifferenceEmpty#3e11affb flags:# final:flags.0?true pts:int timeout:flags.1?int = updates.ChannelDifference;
|
updates.channelDifferenceEmpty#3e11affb flags:# final:flags.0?true pts:int timeout:flags.1?int = updates.ChannelDifference;
|
||||||
updates.channelDifferenceTooLong#6a9d7b35 flags:# final:flags.0?true pts:int timeout:flags.1?int top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
|
updates.channelDifferenceTooLong#a4bcc6fe flags:# final:flags.0?true timeout:flags.1?int dialog:Dialog messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
|
||||||
updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:flags.1?int new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
|
updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:flags.1?int new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
|
||||||
|
|
||||||
channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
|
channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
|
||||||
@@ -628,6 +641,8 @@ topPeerCategoryCorrespondents#637b7ed = TopPeerCategory;
|
|||||||
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
|
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
|
||||||
topPeerCategoryChannels#161d9628 = TopPeerCategory;
|
topPeerCategoryChannels#161d9628 = TopPeerCategory;
|
||||||
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
|
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
|
||||||
|
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
|
||||||
|
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;
|
||||||
|
|
||||||
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
|
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
|
||||||
|
|
||||||
@@ -767,11 +782,11 @@ inputStickerSetItem#ffa0a496 flags:# document:InputDocument emoji:string mask_co
|
|||||||
inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall;
|
inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall;
|
||||||
|
|
||||||
phoneCallEmpty#5366c915 id:long = PhoneCall;
|
phoneCallEmpty#5366c915 id:long = PhoneCall;
|
||||||
phoneCallWaiting#1b8f4ad1 flags:# id:long access_hash:long date:int admin_id:int participant_id:int protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall;
|
phoneCallWaiting#1b8f4ad1 flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall;
|
||||||
phoneCallRequested#83761ce4 id:long access_hash:long date:int admin_id:int participant_id:int g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall;
|
phoneCallRequested#87eabb53 flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall;
|
||||||
phoneCallAccepted#6d003d3f id:long access_hash:long date:int admin_id:int participant_id:int g_b:bytes protocol:PhoneCallProtocol = PhoneCall;
|
phoneCallAccepted#997c454a flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_b:bytes protocol:PhoneCallProtocol = PhoneCall;
|
||||||
phoneCall#e6f9ddf3 flags:# p2p_allowed:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connection:PhoneConnection alternative_connections:Vector<PhoneConnection> start_date:int = PhoneCall;
|
phoneCall#8742ae7f flags:# p2p_allowed:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector<PhoneConnection> start_date:int = PhoneCall;
|
||||||
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall;
|
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.5?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall;
|
||||||
|
|
||||||
phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
|
phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
|
||||||
|
|
||||||
@@ -797,7 +812,7 @@ langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:fl
|
|||||||
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangePhoto#b82f55c3 prev_photo:ChatPhoto new_photo:ChatPhoto = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangePhoto#434bd2af prev_photo:Photo new_photo:Photo = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionToggleInvites#1b7907ae new_value:Bool = ChannelAdminLogEventAction;
|
channelAdminLogEventActionToggleInvites#1b7907ae new_value:Bool = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction;
|
channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction;
|
channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction;
|
||||||
@@ -812,6 +827,7 @@ channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputSticker
|
|||||||
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
|
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
|
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
|
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
|
||||||
|
channelAdminLogEventActionChangeLinkedChat#a26f881b prev_value:int new_value:int = ChannelAdminLogEventAction;
|
||||||
|
|
||||||
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
||||||
|
|
||||||
@@ -843,8 +859,10 @@ inputMessageReplyTo#bad88395 id:int = InputMessage;
|
|||||||
inputMessagePinned#86872538 = InputMessage;
|
inputMessagePinned#86872538 = InputMessage;
|
||||||
|
|
||||||
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
|
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
|
||||||
|
inputDialogPeerFolder#64600527 folder_id:int = InputDialogPeer;
|
||||||
|
|
||||||
dialogPeer#e56dbf05 peer:Peer = DialogPeer;
|
dialogPeer#e56dbf05 peer:Peer = DialogPeer;
|
||||||
|
dialogPeerFolder#514519e2 folder_id:int = DialogPeer;
|
||||||
|
|
||||||
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
|
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
|
||||||
messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = messages.FoundStickerSets;
|
messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = messages.FoundStickerSets;
|
||||||
@@ -1000,6 +1018,22 @@ emojiKeywordsDifference#5cc761bd lang_code:string from_version:int version:int k
|
|||||||
|
|
||||||
emojiURL#a575739d url:string = EmojiURL;
|
emojiURL#a575739d url:string = EmojiURL;
|
||||||
|
|
||||||
|
emojiLanguage#b3fb5361 lang_code:string = EmojiLanguage;
|
||||||
|
|
||||||
|
fileLocationToBeDeprecated#bc7fc6cd volume_id:long local_id:int = FileLocation;
|
||||||
|
|
||||||
|
folder#ff544e65 flags:# autofill_new_broadcasts:flags.0?true autofill_public_groups:flags.1?true autofill_new_correspondents:flags.2?true id:int title:string photo:flags.3?ChatPhoto = Folder;
|
||||||
|
|
||||||
|
inputFolderPeer#fbd2c296 peer:InputPeer folder_id:int = InputFolderPeer;
|
||||||
|
|
||||||
|
folderPeer#e9baa668 peer:Peer folder_id:int = FolderPeer;
|
||||||
|
|
||||||
|
messages.searchCounter#e844ebff flags:# inexact:flags.1?true filter:MessagesFilter count:int = messages.SearchCounter;
|
||||||
|
|
||||||
|
urlAuthResultRequest#92d33a0e flags:# request_write_access:flags.0?true bot:User domain:string = UrlAuthResult;
|
||||||
|
urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult;
|
||||||
|
urlAuthResultDefault#a9d6db1f = UrlAuthResult;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
@@ -1098,14 +1132,14 @@ contacts.unblock#e54100bd id:InputUser = Bool;
|
|||||||
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
|
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
|
||||||
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
||||||
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
|
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
|
||||||
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
|
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
|
||||||
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
|
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
|
||||||
contacts.resetSaved#879537f1 = Bool;
|
contacts.resetSaved#879537f1 = Bool;
|
||||||
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
||||||
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
|
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
|
||||||
|
|
||||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
||||||
messages.getDialogs#b098aee6 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
|
messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
|
||||||
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||||
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||||
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
||||||
@@ -1152,7 +1186,7 @@ messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_par
|
|||||||
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
||||||
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
||||||
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
||||||
messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
messages.searchGlobal#f79c611 q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||||
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
|
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
|
||||||
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
||||||
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
|
||||||
@@ -1185,8 +1219,8 @@ messages.getCommonChats#d0a48c4 user_id:InputUser max_id:int limit:int = message
|
|||||||
messages.getAllChats#eba80ff0 except_ids:Vector<int> = messages.Chats;
|
messages.getAllChats#eba80ff0 except_ids:Vector<int> = messages.Chats;
|
||||||
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
||||||
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||||
messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
|
messages.reorderPinnedDialogs#3b1adf37 flags:# force:flags.0?true folder_id:int order:Vector<InputDialogPeer> = Bool;
|
||||||
messages.getPinnedDialogs#e254d64e = messages.PeerDialogs;
|
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
|
||||||
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
|
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
|
||||||
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
|
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
|
||||||
messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia;
|
messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia;
|
||||||
@@ -1212,7 +1246,11 @@ messages.editChatAbout#def60797 peer:InputPeer about:string = Bool;
|
|||||||
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
|
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
|
||||||
messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
|
messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
|
||||||
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
|
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
|
||||||
|
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
|
||||||
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
||||||
|
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
||||||
|
messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
||||||
|
messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
||||||
|
|
||||||
updates.getState#edd4882a = updates.State;
|
updates.getState#edd4882a = updates.State;
|
||||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||||
@@ -1281,6 +1319,9 @@ channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool
|
|||||||
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
|
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
|
||||||
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
|
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
|
||||||
|
channels.getGroupsForDiscussion#f5dad378 = messages.Chats;
|
||||||
|
channels.getBroadcastsForDiscussion#1a87f304 = messages.Chats;
|
||||||
|
channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool;
|
||||||
|
|
||||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||||
@@ -1298,11 +1339,11 @@ stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = mes
|
|||||||
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
|
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
|
||||||
|
|
||||||
phone.getCallConfig#55451fa9 = DataJSON;
|
phone.getCallConfig#55451fa9 = DataJSON;
|
||||||
phone.requestCall#5b95b3d4 user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||||
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||||
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
|
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||||
phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool;
|
phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool;
|
||||||
phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
|
phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
|
||||||
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
||||||
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
||||||
|
|
||||||
@@ -1312,7 +1353,7 @@ langpack.getDifference#cd984aa5 lang_pack:string lang_code:string from_version:i
|
|||||||
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
|
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
|
||||||
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
|
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
|
||||||
|
|
||||||
// LAYER 97
|
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
||||||
|
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
||||||
|
|
||||||
// Ports
|
// LAYER 100
|
||||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import ast
|
import ast
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
HOME = "compiler/docs"
|
HOME = "compiler/docs"
|
||||||
@@ -29,8 +30,10 @@ TYPES_PATH = "pyrogram/api/types"
|
|||||||
FUNCTIONS_BASE = "functions"
|
FUNCTIONS_BASE = "functions"
|
||||||
TYPES_BASE = "types"
|
TYPES_BASE = "types"
|
||||||
|
|
||||||
shutil.rmtree(TYPES_BASE, ignore_errors=True)
|
|
||||||
shutil.rmtree(FUNCTIONS_BASE, ignore_errors=True)
|
def snek(s: str):
|
||||||
|
s = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", s)
|
||||||
|
return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s).lower()
|
||||||
|
|
||||||
|
|
||||||
def generate(source_path, base):
|
def generate(source_path, base):
|
||||||
@@ -50,9 +53,11 @@ def generate(source_path, base):
|
|||||||
for node in ast.walk(p):
|
for node in ast.walk(p):
|
||||||
if isinstance(node, ast.ClassDef):
|
if isinstance(node, ast.ClassDef):
|
||||||
name = node.name
|
name = node.name
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
# name = "".join([str(j.title()) for j in os.path.splitext(i)[0].split("_")])
|
full_path = os.path.basename(path) + "/" + snek(name).replace("_", "-") + ".rst"
|
||||||
full_path = os.path.basename(path) + "/" + name + ".rst"
|
|
||||||
|
|
||||||
if level:
|
if level:
|
||||||
full_path = base + "/" + full_path
|
full_path = base + "/" + full_path
|
||||||
@@ -65,7 +70,7 @@ def generate(source_path, base):
|
|||||||
title=name,
|
title=name,
|
||||||
title_markup="=" * len(name),
|
title_markup="=" * len(name),
|
||||||
full_class_path="pyrogram.api.{}".format(
|
full_class_path="pyrogram.api.{}".format(
|
||||||
os.path.splitext(full_path)[0].replace("/", ".")
|
".".join(full_path.split("/")[:-1]) + "." + name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -82,7 +87,7 @@ def generate(source_path, base):
|
|||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
for i in v:
|
for i in v:
|
||||||
entities.append(i)
|
entities.append(snek(i).replace("_", "-"))
|
||||||
|
|
||||||
if k != base:
|
if k != base:
|
||||||
inner_path = base + "/" + k + "/index" + ".rst"
|
inner_path = base + "/" + k + "/index" + ".rst"
|
||||||
@@ -98,6 +103,7 @@ def generate(source_path, base):
|
|||||||
with open(DESTINATION + "/" + inner_path, "w", encoding="utf-8") as f:
|
with open(DESTINATION + "/" + inner_path, "w", encoding="utf-8") as f:
|
||||||
if k == base:
|
if k == base:
|
||||||
f.write(":tocdepth: 1\n\n")
|
f.write(":tocdepth: 1\n\n")
|
||||||
|
k = "Raw " + k
|
||||||
|
|
||||||
f.write(
|
f.write(
|
||||||
toctree.format(
|
toctree.format(
|
||||||
@@ -115,6 +121,8 @@ def start():
|
|||||||
global page_template
|
global page_template
|
||||||
global toctree
|
global toctree
|
||||||
|
|
||||||
|
shutil.rmtree(DESTINATION, ignore_errors=True)
|
||||||
|
|
||||||
with open(HOME + "/template/page.txt", encoding="utf-8") as f:
|
with open(HOME + "/template/page.txt", encoding="utf-8") as f:
|
||||||
page_template = f.read()
|
page_template = f.read()
|
||||||
|
|
||||||
|
@@ -98,4 +98,5 @@ RESULTS_TOO_MUCH The result contains too many items
|
|||||||
RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
|
RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
|
||||||
ACCESS_TOKEN_INVALID The bot access token is invalid
|
ACCESS_TOKEN_INVALID The bot access token is invalid
|
||||||
INVITE_HASH_EXPIRED The chat invite link is no longer valid
|
INVITE_HASH_EXPIRED The chat invite link is no longer valid
|
||||||
USER_BANNED_IN_CHANNEL You are limited, check @SpamBot for details
|
USER_BANNED_IN_CHANNEL You are limited, check @SpamBot for details
|
||||||
|
MESSAGE_EDIT_TIME_EXPIRED You can no longer edit this message
|
|
@@ -2,6 +2,7 @@ id message
|
|||||||
AUTH_KEY_UNREGISTERED The key is not registered in the system
|
AUTH_KEY_UNREGISTERED The key is not registered in the system
|
||||||
AUTH_KEY_INVALID The key is invalid
|
AUTH_KEY_INVALID The key is invalid
|
||||||
USER_DEACTIVATED The user has been deleted/deactivated
|
USER_DEACTIVATED The user has been deleted/deactivated
|
||||||
|
USER_DEACTIVATED_BAN The user has been deleted/deactivated
|
||||||
SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions
|
SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions
|
||||||
SESSION_EXPIRED The authorization has expired
|
SESSION_EXPIRED The authorization has expired
|
||||||
ACTIVE_USER_REQUIRED The method is only available to already activated users
|
ACTIVE_USER_REQUIRED The method is only available to already activated users
|
||||||
|
|
@@ -23,11 +23,11 @@ canonical = "https://docs.pyrogram.org/"
|
|||||||
|
|
||||||
dirs = {
|
dirs = {
|
||||||
".": ("weekly", 1.0),
|
".": ("weekly", 1.0),
|
||||||
"intro": ("weekly", 0.8),
|
"intro": ("weekly", 0.9),
|
||||||
"start": ("weekly", 0.8),
|
"start": ("weekly", 0.9),
|
||||||
"api": ("weekly", 0.6),
|
"api": ("weekly", 0.8),
|
||||||
"topics": ("weekly", 0.6),
|
"topics": ("weekly", 0.8),
|
||||||
"telegram": ("weekly", 0.4)
|
"telegram": ("weekly", 0.6)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -22,43 +22,65 @@ some of the required arguments.
|
|||||||
|
|
||||||
.. currentmodule:: pyrogram
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
- Message_
|
Index
|
||||||
- CallbackQuery_
|
-----
|
||||||
- InlineQuery_
|
|
||||||
|
|
||||||
.. _Message:
|
|
||||||
|
|
||||||
Message
|
Message
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 3
|
||||||
|
|
||||||
|
- :meth:`~Message.click`
|
||||||
|
- :meth:`~Message.delete`
|
||||||
|
- :meth:`~Message.download`
|
||||||
|
- :meth:`~Message.edit`
|
||||||
|
- :meth:`~Message.edit_caption`
|
||||||
|
- :meth:`~Message.edit_media`
|
||||||
|
- :meth:`~Message.edit_reply_markup`
|
||||||
|
- :meth:`~Message.forward`
|
||||||
|
- :meth:`~Message.pin`
|
||||||
|
- :meth:`~Message.reply`
|
||||||
|
- :meth:`~Message.reply_animation`
|
||||||
|
- :meth:`~Message.reply_audio`
|
||||||
|
- :meth:`~Message.reply_cached_media`
|
||||||
|
- :meth:`~Message.reply_chat_action`
|
||||||
|
- :meth:`~Message.reply_contact`
|
||||||
|
- :meth:`~Message.reply_document`
|
||||||
|
- :meth:`~Message.reply_game`
|
||||||
|
- :meth:`~Message.reply_inline_bot_result`
|
||||||
|
- :meth:`~Message.reply_location`
|
||||||
|
- :meth:`~Message.reply_media_group`
|
||||||
|
- :meth:`~Message.reply_photo`
|
||||||
|
- :meth:`~Message.reply_poll`
|
||||||
|
- :meth:`~Message.reply_sticker`
|
||||||
|
- :meth:`~Message.reply_venue`
|
||||||
|
- :meth:`~Message.reply_video`
|
||||||
|
- :meth:`~Message.reply_video_note`
|
||||||
|
- :meth:`~Message.reply_voice`
|
||||||
|
|
||||||
|
CallbackQuery
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 2
|
||||||
|
|
||||||
|
- :meth:`~CallbackQuery.answer`
|
||||||
|
|
||||||
|
InlineQuery
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 2
|
||||||
|
|
||||||
|
- :meth:`~InlineQuery.answer`
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Details
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- :meth:`Message.click()`
|
.. Message
|
||||||
- :meth:`Message.delete()`
|
|
||||||
- :meth:`Message.download()`
|
|
||||||
- :meth:`Message.edit()`
|
|
||||||
- :meth:`Message.edit_caption()`
|
|
||||||
- :meth:`Message.edit_media()`
|
|
||||||
- :meth:`Message.edit_reply_markup()`
|
|
||||||
- :meth:`Message.forward()`
|
|
||||||
- :meth:`Message.pin()`
|
|
||||||
- :meth:`Message.reply()`
|
|
||||||
- :meth:`Message.reply_animation()`
|
|
||||||
- :meth:`Message.reply_audio()`
|
|
||||||
- :meth:`Message.reply_cached_media()`
|
|
||||||
- :meth:`Message.reply_chat_action()`
|
|
||||||
- :meth:`Message.reply_contact()`
|
|
||||||
- :meth:`Message.reply_document()`
|
|
||||||
- :meth:`Message.reply_game()`
|
|
||||||
- :meth:`Message.reply_inline_bot_result()`
|
|
||||||
- :meth:`Message.reply_location()`
|
|
||||||
- :meth:`Message.reply_media_group()`
|
|
||||||
- :meth:`Message.reply_photo()`
|
|
||||||
- :meth:`Message.reply_poll()`
|
|
||||||
- :meth:`Message.reply_sticker()`
|
|
||||||
- :meth:`Message.reply_venue()`
|
|
||||||
- :meth:`Message.reply_video()`
|
|
||||||
- :meth:`Message.reply_video_note()`
|
|
||||||
- :meth:`Message.reply_voice()`
|
|
||||||
|
|
||||||
.. automethod:: Message.click()
|
.. automethod:: Message.click()
|
||||||
.. automethod:: Message.delete()
|
.. automethod:: Message.delete()
|
||||||
.. automethod:: Message.download()
|
.. automethod:: Message.download()
|
||||||
@@ -87,16 +109,8 @@ Message
|
|||||||
.. automethod:: Message.reply_video_note()
|
.. automethod:: Message.reply_video_note()
|
||||||
.. automethod:: Message.reply_voice()
|
.. automethod:: Message.reply_voice()
|
||||||
|
|
||||||
.. _CallbackQuery:
|
.. CallbackQuery
|
||||||
|
|
||||||
CallbackQuery
|
|
||||||
-------------
|
|
||||||
|
|
||||||
.. automethod:: CallbackQuery.answer()
|
.. automethod:: CallbackQuery.answer()
|
||||||
|
|
||||||
.. _InlineQuery:
|
.. InlineQuery
|
||||||
|
.. automethod:: InlineQuery.answer()
|
||||||
InlineQuery
|
|
||||||
-----------
|
|
||||||
|
|
||||||
.. automethod:: InlineQuery.answer()
|
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
Decorators
|
Decorators
|
||||||
==========
|
==========
|
||||||
|
|
||||||
While still being methods bound to the :obj:`Client <pyrogram.Client>` class, decorators are of a special kind and thus deserve a
|
While still being methods bound to the :class:`~pyrogram.Client` class, decorators are of a special kind and thus
|
||||||
dedicated page.
|
deserve a dedicated page.
|
||||||
|
|
||||||
Decorators are able to register callback functions for handling updates in a much easier and cleaner way compared to
|
Decorators are able to register callback functions for handling updates in a much easier and cleaner way compared to
|
||||||
`Handlers <Handlers.html>`_; they do so by instantiating the correct handler and calling
|
:doc:`Handlers <handlers>`; they do so by instantiating the correct handler and calling
|
||||||
:meth:`add_handler() <pyrogram.Client.add_handler>`, automatically. All you need to do is adding the decorators on top
|
:meth:`~pyrogram.Client.add_handler`, automatically. All you need to do is adding the decorators on top of your
|
||||||
of your functions.
|
functions.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:emphasize-lines: 6
|
:emphasize-lines: 6
|
||||||
@@ -24,25 +24,34 @@ of your functions.
|
|||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
.. currentmodule:: pyrogram.Client
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
.. autosummary::
|
Index
|
||||||
:nosignatures:
|
-----
|
||||||
|
|
||||||
on_message
|
.. hlist::
|
||||||
on_callback_query
|
:columns: 3
|
||||||
on_inline_query
|
|
||||||
on_deleted_messages
|
|
||||||
on_user_status
|
|
||||||
on_poll
|
|
||||||
on_disconnect
|
|
||||||
on_raw_update
|
|
||||||
|
|
||||||
.. automethod:: pyrogram.Client.on_message()
|
- :meth:`~Client.on_message`
|
||||||
.. automethod:: pyrogram.Client.on_callback_query()
|
- :meth:`~Client.on_callback_query`
|
||||||
.. automethod:: pyrogram.Client.on_inline_query()
|
- :meth:`~Client.on_inline_query`
|
||||||
.. automethod:: pyrogram.Client.on_deleted_messages()
|
- :meth:`~Client.on_deleted_messages`
|
||||||
.. automethod:: pyrogram.Client.on_user_status()
|
- :meth:`~Client.on_user_status`
|
||||||
.. automethod:: pyrogram.Client.on_poll()
|
- :meth:`~Client.on_poll`
|
||||||
.. automethod:: pyrogram.Client.on_disconnect()
|
- :meth:`~Client.on_disconnect`
|
||||||
.. automethod:: pyrogram.Client.on_raw_update()
|
- :meth:`~Client.on_raw_update`
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Details
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. Decorators
|
||||||
|
.. autodecorator:: pyrogram.Client.on_message()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_callback_query()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_inline_query()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_deleted_messages()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_user_status()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_poll()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_disconnect()
|
||||||
|
.. autodecorator:: pyrogram.Client.on_raw_update()
|
@@ -3,8 +3,8 @@ Update Handlers
|
|||||||
|
|
||||||
Handlers are used to instruct Pyrogram about which kind of updates you'd like to handle with your callback functions.
|
Handlers are used to instruct Pyrogram about which kind of updates you'd like to handle with your callback functions.
|
||||||
|
|
||||||
For a much more convenient way of registering callback functions have a look at `Decorators <Decorators.html>`_ instead.
|
For a much more convenient way of registering callback functions have a look at :doc:`Decorators <decorators>` instead.
|
||||||
In case you decided to manually create a handler, use :meth:`add_handler() <pyrogram.Client.add_handler>` to register
|
In case you decided to manually create a handler, use :class:`~pyrogram.Client.add_handler` to register
|
||||||
it.
|
it.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@@ -25,18 +25,27 @@ it.
|
|||||||
|
|
||||||
.. currentmodule:: pyrogram
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
.. autosummary::
|
Index
|
||||||
:nosignatures:
|
-----
|
||||||
|
|
||||||
MessageHandler
|
.. hlist::
|
||||||
DeletedMessagesHandler
|
:columns: 3
|
||||||
CallbackQueryHandler
|
|
||||||
InlineQueryHandler
|
|
||||||
UserStatusHandler
|
|
||||||
PollHandler
|
|
||||||
DisconnectHandler
|
|
||||||
RawUpdateHandler
|
|
||||||
|
|
||||||
|
- :class:`MessageHandler`
|
||||||
|
- :class:`DeletedMessagesHandler`
|
||||||
|
- :class:`CallbackQueryHandler`
|
||||||
|
- :class:`InlineQueryHandler`
|
||||||
|
- :class:`UserStatusHandler`
|
||||||
|
- :class:`PollHandler`
|
||||||
|
- :class:`DisconnectHandler`
|
||||||
|
- :class:`RawUpdateHandler`
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Details
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. Handlers
|
||||||
.. autoclass:: MessageHandler()
|
.. autoclass:: MessageHandler()
|
||||||
.. autoclass:: DeletedMessagesHandler()
|
.. autoclass:: DeletedMessagesHandler()
|
||||||
.. autoclass:: CallbackQueryHandler()
|
.. autoclass:: CallbackQueryHandler()
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
Available Methods
|
Available Methods
|
||||||
=================
|
=================
|
||||||
|
|
||||||
All Pyrogram methods listed here are bound to a :obj:`Client <pyrogram.Client>` instance.
|
All Pyrogram methods listed here are bound to a :class:`~pyrogram.Client` instance.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:emphasize-lines: 6
|
:emphasize-lines: 6
|
||||||
@@ -13,253 +13,253 @@ All Pyrogram methods listed here are bound to a :obj:`Client <pyrogram.Client>`
|
|||||||
with app:
|
with app:
|
||||||
app.send_message("haskell", "hi")
|
app.send_message("haskell", "hi")
|
||||||
|
|
||||||
.. currentmodule:: pyrogram.Client
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
|
Index
|
||||||
|
-----
|
||||||
|
|
||||||
Utilities
|
Utilities
|
||||||
---------
|
^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 4
|
||||||
|
|
||||||
start
|
- :meth:`~Client.start`
|
||||||
stop
|
- :meth:`~Client.stop`
|
||||||
restart
|
- :meth:`~Client.restart`
|
||||||
idle
|
- :meth:`~Client.idle`
|
||||||
run
|
- :meth:`~Client.run`
|
||||||
add_handler
|
- :meth:`~Client.add_handler`
|
||||||
remove_handler
|
- :meth:`~Client.remove_handler`
|
||||||
send
|
- :meth:`~Client.send`
|
||||||
resolve_peer
|
- :meth:`~Client.resolve_peer`
|
||||||
save_file
|
- :meth:`~Client.save_file`
|
||||||
stop_transmission
|
- :meth:`~Client.stop_transmission`
|
||||||
|
|
||||||
Messages
|
Messages
|
||||||
--------
|
^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
send_message
|
- :meth:`~Client.send_message`
|
||||||
forward_messages
|
- :meth:`~Client.forward_messages`
|
||||||
send_photo
|
- :meth:`~Client.send_photo`
|
||||||
send_audio
|
- :meth:`~Client.send_audio`
|
||||||
send_document
|
- :meth:`~Client.send_document`
|
||||||
send_sticker
|
- :meth:`~Client.send_sticker`
|
||||||
send_video
|
- :meth:`~Client.send_animated_sticker`
|
||||||
send_animation
|
- :meth:`~Client.send_video`
|
||||||
send_voice
|
- :meth:`~Client.send_animation`
|
||||||
send_video_note
|
- :meth:`~Client.send_voice`
|
||||||
send_media_group
|
- :meth:`~Client.send_video_note`
|
||||||
send_location
|
- :meth:`~Client.send_media_group`
|
||||||
send_venue
|
- :meth:`~Client.send_location`
|
||||||
send_contact
|
- :meth:`~Client.send_venue`
|
||||||
send_cached_media
|
- :meth:`~Client.send_contact`
|
||||||
send_chat_action
|
- :meth:`~Client.send_cached_media`
|
||||||
edit_message_text
|
- :meth:`~Client.send_chat_action`
|
||||||
edit_message_caption
|
- :meth:`~Client.edit_message_text`
|
||||||
edit_message_reply_markup
|
- :meth:`~Client.edit_message_caption`
|
||||||
edit_message_media
|
- :meth:`~Client.edit_message_reply_markup`
|
||||||
delete_messages
|
- :meth:`~Client.edit_message_media`
|
||||||
get_messages
|
- :meth:`~Client.delete_messages`
|
||||||
get_history
|
- :meth:`~Client.get_messages`
|
||||||
get_history_count
|
- :meth:`~Client.get_history`
|
||||||
iter_history
|
- :meth:`~Client.get_history_count`
|
||||||
send_poll
|
- :meth:`~Client.iter_history`
|
||||||
vote_poll
|
- :meth:`~Client.send_poll`
|
||||||
stop_poll
|
- :meth:`~Client.vote_poll`
|
||||||
retract_vote
|
- :meth:`~Client.stop_poll`
|
||||||
download_media
|
- :meth:`~Client.retract_vote`
|
||||||
|
- :meth:`~Client.download_media`
|
||||||
|
|
||||||
Chats
|
Chats
|
||||||
-----
|
^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
join_chat
|
- :meth:`~Client.join_chat`
|
||||||
leave_chat
|
- :meth:`~Client.leave_chat`
|
||||||
kick_chat_member
|
- :meth:`~Client.kick_chat_member`
|
||||||
unban_chat_member
|
- :meth:`~Client.unban_chat_member`
|
||||||
restrict_chat_member
|
- :meth:`~Client.restrict_chat_member`
|
||||||
promote_chat_member
|
- :meth:`~Client.promote_chat_member`
|
||||||
export_chat_invite_link
|
- :meth:`~Client.export_chat_invite_link`
|
||||||
set_chat_photo
|
- :meth:`~Client.set_chat_photo`
|
||||||
delete_chat_photo
|
- :meth:`~Client.delete_chat_photo`
|
||||||
set_chat_title
|
- :meth:`~Client.set_chat_title`
|
||||||
set_chat_description
|
- :meth:`~Client.set_chat_description`
|
||||||
pin_chat_message
|
- :meth:`~Client.pin_chat_message`
|
||||||
unpin_chat_message
|
- :meth:`~Client.unpin_chat_message`
|
||||||
get_chat
|
- :meth:`~Client.get_chat`
|
||||||
get_chat_member
|
- :meth:`~Client.get_chat_member`
|
||||||
get_chat_members
|
- :meth:`~Client.get_chat_members`
|
||||||
get_chat_members_count
|
- :meth:`~Client.get_chat_members_count`
|
||||||
iter_chat_members
|
- :meth:`~Client.iter_chat_members`
|
||||||
get_dialogs
|
- :meth:`~Client.get_dialogs`
|
||||||
iter_dialogs
|
- :meth:`~Client.iter_dialogs`
|
||||||
get_dialogs_count
|
- :meth:`~Client.get_dialogs_count`
|
||||||
restrict_chat
|
- :meth:`~Client.restrict_chat`
|
||||||
update_chat_username
|
- :meth:`~Client.update_chat_username`
|
||||||
|
|
||||||
Users
|
Users
|
||||||
-----
|
^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
get_me
|
- :meth:`~Client.get_me`
|
||||||
get_users
|
- :meth:`~Client.get_users`
|
||||||
get_user_profile_photos
|
- :meth:`~Client.get_profile_photos`
|
||||||
get_user_profile_photos_count
|
- :meth:`~Client.get_profile_photos_count`
|
||||||
set_user_profile_photo
|
- :meth:`~Client.iter_profile_photos`
|
||||||
delete_user_profile_photos
|
- :meth:`~Client.set_profile_photo`
|
||||||
update_username
|
- :meth:`~Client.delete_profile_photos`
|
||||||
|
- :meth:`~Client.update_username`
|
||||||
|
- :meth:`~Client.get_user_dc`
|
||||||
|
|
||||||
Contacts
|
Contacts
|
||||||
--------
|
^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
add_contacts
|
- :meth:`~Client.add_contacts`
|
||||||
get_contacts
|
- :meth:`~Client.get_contacts`
|
||||||
get_contacts_count
|
- :meth:`~Client.get_contacts_count`
|
||||||
delete_contacts
|
- :meth:`~Client.delete_contacts`
|
||||||
|
|
||||||
Password
|
Password
|
||||||
--------
|
^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
enable_cloud_password
|
- :meth:`~Client.enable_cloud_password`
|
||||||
change_cloud_password
|
- :meth:`~Client.change_cloud_password`
|
||||||
remove_cloud_password
|
- :meth:`~Client.remove_cloud_password`
|
||||||
|
|
||||||
Bots
|
Bots
|
||||||
----
|
^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
get_inline_bot_results
|
- :meth:`~Client.get_inline_bot_results`
|
||||||
send_inline_bot_result
|
- :meth:`~Client.send_inline_bot_result`
|
||||||
answer_callback_query
|
- :meth:`~Client.answer_callback_query`
|
||||||
answer_inline_query
|
- :meth:`~Client.answer_inline_query`
|
||||||
request_callback_answer
|
- :meth:`~Client.request_callback_answer`
|
||||||
send_game
|
- :meth:`~Client.send_game`
|
||||||
set_game_score
|
- :meth:`~Client.set_game_score`
|
||||||
get_game_high_scores
|
- :meth:`~Client.get_game_high_scores`
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Details
|
||||||
|
-------
|
||||||
|
|
||||||
.. Utilities
|
.. Utilities
|
||||||
---------
|
.. automethod:: Client.start()
|
||||||
|
.. automethod:: Client.stop()
|
||||||
.. automethod:: pyrogram.Client.start()
|
.. automethod:: Client.restart()
|
||||||
.. automethod:: pyrogram.Client.stop()
|
.. automethod:: Client.idle()
|
||||||
.. automethod:: pyrogram.Client.restart()
|
.. automethod:: Client.run()
|
||||||
.. automethod:: pyrogram.Client.idle()
|
.. automethod:: Client.add_handler()
|
||||||
.. automethod:: pyrogram.Client.run()
|
.. automethod:: Client.remove_handler()
|
||||||
.. automethod:: pyrogram.Client.add_handler()
|
.. automethod:: Client.send()
|
||||||
.. automethod:: pyrogram.Client.remove_handler()
|
.. automethod:: Client.resolve_peer()
|
||||||
.. automethod:: pyrogram.Client.send()
|
.. automethod:: Client.save_file()
|
||||||
.. automethod:: pyrogram.Client.resolve_peer()
|
.. automethod:: Client.stop_transmission()
|
||||||
.. automethod:: pyrogram.Client.save_file()
|
|
||||||
.. automethod:: pyrogram.Client.stop_transmission()
|
|
||||||
|
|
||||||
.. Messages
|
.. Messages
|
||||||
--------
|
.. automethod:: Client.send_message()
|
||||||
|
.. automethod:: Client.forward_messages()
|
||||||
.. automethod:: pyrogram.Client.send_message()
|
.. automethod:: Client.send_photo()
|
||||||
.. automethod:: pyrogram.Client.forward_messages()
|
.. automethod:: Client.send_audio()
|
||||||
.. automethod:: pyrogram.Client.send_photo()
|
.. automethod:: Client.send_document()
|
||||||
.. automethod:: pyrogram.Client.send_audio()
|
.. automethod:: Client.send_sticker()
|
||||||
.. automethod:: pyrogram.Client.send_document()
|
.. automethod:: Client.send_animated_sticker()
|
||||||
.. automethod:: pyrogram.Client.send_sticker()
|
.. automethod:: Client.send_video()
|
||||||
.. automethod:: pyrogram.Client.send_video()
|
.. automethod:: Client.send_animation()
|
||||||
.. automethod:: pyrogram.Client.send_animation()
|
.. automethod:: Client.send_voice()
|
||||||
.. automethod:: pyrogram.Client.send_voice()
|
.. automethod:: Client.send_video_note()
|
||||||
.. automethod:: pyrogram.Client.send_video_note()
|
.. automethod:: Client.send_media_group()
|
||||||
.. automethod:: pyrogram.Client.send_media_group()
|
.. automethod:: Client.send_location()
|
||||||
.. automethod:: pyrogram.Client.send_location()
|
.. automethod:: Client.send_venue()
|
||||||
.. automethod:: pyrogram.Client.send_venue()
|
.. automethod:: Client.send_contact()
|
||||||
.. automethod:: pyrogram.Client.send_contact()
|
.. automethod:: Client.send_cached_media()
|
||||||
.. automethod:: pyrogram.Client.send_cached_media()
|
.. automethod:: Client.send_chat_action()
|
||||||
.. automethod:: pyrogram.Client.send_chat_action()
|
.. automethod:: Client.edit_message_text()
|
||||||
.. automethod:: pyrogram.Client.edit_message_text()
|
.. automethod:: Client.edit_message_caption()
|
||||||
.. automethod:: pyrogram.Client.edit_message_caption()
|
.. automethod:: Client.edit_message_reply_markup()
|
||||||
.. automethod:: pyrogram.Client.edit_message_reply_markup()
|
.. automethod:: Client.edit_message_media()
|
||||||
.. automethod:: pyrogram.Client.edit_message_media()
|
.. automethod:: Client.delete_messages()
|
||||||
.. automethod:: pyrogram.Client.delete_messages()
|
.. automethod:: Client.get_messages()
|
||||||
.. automethod:: pyrogram.Client.get_messages()
|
.. automethod:: Client.get_history()
|
||||||
.. automethod:: pyrogram.Client.get_history()
|
.. automethod:: Client.get_history_count()
|
||||||
.. automethod:: pyrogram.Client.get_history_count()
|
.. automethod:: Client.iter_history()
|
||||||
.. automethod:: pyrogram.Client.iter_history()
|
.. automethod:: Client.send_poll()
|
||||||
.. automethod:: pyrogram.Client.send_poll()
|
.. automethod:: Client.vote_poll()
|
||||||
.. automethod:: pyrogram.Client.vote_poll()
|
.. automethod:: Client.stop_poll()
|
||||||
.. automethod:: pyrogram.Client.stop_poll()
|
.. automethod:: Client.retract_vote()
|
||||||
.. automethod:: pyrogram.Client.retract_vote()
|
.. automethod:: Client.download_media()
|
||||||
.. automethod:: pyrogram.Client.download_media()
|
|
||||||
|
|
||||||
.. Chats
|
.. Chats
|
||||||
-----
|
.. automethod:: Client.join_chat()
|
||||||
|
.. automethod:: Client.leave_chat()
|
||||||
.. automethod:: pyrogram.Client.join_chat()
|
.. automethod:: Client.kick_chat_member()
|
||||||
.. automethod:: pyrogram.Client.leave_chat()
|
.. automethod:: Client.unban_chat_member()
|
||||||
.. automethod:: pyrogram.Client.kick_chat_member()
|
.. automethod:: Client.restrict_chat_member()
|
||||||
.. automethod:: pyrogram.Client.unban_chat_member()
|
.. automethod:: Client.promote_chat_member()
|
||||||
.. automethod:: pyrogram.Client.restrict_chat_member()
|
.. automethod:: Client.export_chat_invite_link()
|
||||||
.. automethod:: pyrogram.Client.promote_chat_member()
|
.. automethod:: Client.set_chat_photo()
|
||||||
.. automethod:: pyrogram.Client.export_chat_invite_link()
|
.. automethod:: Client.delete_chat_photo()
|
||||||
.. automethod:: pyrogram.Client.set_chat_photo()
|
.. automethod:: Client.set_chat_title()
|
||||||
.. automethod:: pyrogram.Client.delete_chat_photo()
|
.. automethod:: Client.set_chat_description()
|
||||||
.. automethod:: pyrogram.Client.set_chat_title()
|
.. automethod:: Client.pin_chat_message()
|
||||||
.. automethod:: pyrogram.Client.set_chat_description()
|
.. automethod:: Client.unpin_chat_message()
|
||||||
.. automethod:: pyrogram.Client.pin_chat_message()
|
.. automethod:: Client.get_chat()
|
||||||
.. automethod:: pyrogram.Client.unpin_chat_message()
|
.. automethod:: Client.get_chat_member()
|
||||||
.. automethod:: pyrogram.Client.get_chat()
|
.. automethod:: Client.get_chat_members()
|
||||||
.. automethod:: pyrogram.Client.get_chat_member()
|
.. automethod:: Client.get_chat_members_count()
|
||||||
.. automethod:: pyrogram.Client.get_chat_members()
|
.. automethod:: Client.iter_chat_members()
|
||||||
.. automethod:: pyrogram.Client.get_chat_members_count()
|
.. automethod:: Client.get_dialogs()
|
||||||
.. automethod:: pyrogram.Client.iter_chat_members()
|
.. automethod:: Client.iter_dialogs()
|
||||||
.. automethod:: pyrogram.Client.get_dialogs()
|
.. automethod:: Client.get_dialogs_count()
|
||||||
.. automethod:: pyrogram.Client.iter_dialogs()
|
.. automethod:: Client.restrict_chat()
|
||||||
.. automethod:: pyrogram.Client.get_dialogs_count()
|
.. automethod:: Client.update_chat_username()
|
||||||
.. automethod:: pyrogram.Client.restrict_chat()
|
|
||||||
.. automethod:: pyrogram.Client.update_chat_username()
|
|
||||||
|
|
||||||
.. Users
|
.. Users
|
||||||
-----
|
.. automethod:: Client.get_me()
|
||||||
|
.. automethod:: Client.get_users()
|
||||||
.. automethod:: pyrogram.Client.get_me()
|
.. automethod:: Client.get_profile_photos()
|
||||||
.. automethod:: pyrogram.Client.get_users()
|
.. automethod:: Client.get_profile_photos_count()
|
||||||
.. automethod:: pyrogram.Client.get_user_profile_photos()
|
.. automethod:: Client.iter_profile_photos()
|
||||||
.. automethod:: pyrogram.Client.get_user_profile_photos_count()
|
.. automethod:: Client.set_profile_photo()
|
||||||
.. automethod:: pyrogram.Client.set_user_profile_photo()
|
.. automethod:: Client.delete_profile_photos()
|
||||||
.. automethod:: pyrogram.Client.delete_user_profile_photos()
|
.. automethod:: Client.update_username()
|
||||||
.. automethod:: pyrogram.Client.update_username()
|
.. automethod:: Client.get_user_dc()
|
||||||
|
|
||||||
.. Contacts
|
.. Contacts
|
||||||
--------
|
.. automethod:: Client.add_contacts()
|
||||||
|
.. automethod:: Client.get_contacts()
|
||||||
.. automethod:: pyrogram.Client.add_contacts()
|
.. automethod:: Client.get_contacts_count()
|
||||||
.. automethod:: pyrogram.Client.get_contacts()
|
.. automethod:: Client.delete_contacts()
|
||||||
.. automethod:: pyrogram.Client.get_contacts_count()
|
|
||||||
.. automethod:: pyrogram.Client.delete_contacts()
|
|
||||||
|
|
||||||
.. Password
|
.. Password
|
||||||
--------
|
.. automethod:: Client.enable_cloud_password()
|
||||||
|
.. automethod:: Client.change_cloud_password()
|
||||||
.. automethod:: pyrogram.Client.enable_cloud_password()
|
.. automethod:: Client.remove_cloud_password()
|
||||||
.. automethod:: pyrogram.Client.change_cloud_password()
|
|
||||||
.. automethod:: pyrogram.Client.remove_cloud_password()
|
|
||||||
|
|
||||||
.. Bots
|
.. Bots
|
||||||
----
|
.. automethod:: Client.get_inline_bot_results()
|
||||||
|
.. automethod:: Client.send_inline_bot_result()
|
||||||
.. automethod:: pyrogram.Client.get_inline_bot_results()
|
.. automethod:: Client.answer_callback_query()
|
||||||
.. automethod:: pyrogram.Client.send_inline_bot_result()
|
.. automethod:: Client.answer_inline_query()
|
||||||
.. automethod:: pyrogram.Client.answer_callback_query()
|
.. automethod:: Client.request_callback_answer()
|
||||||
.. automethod:: pyrogram.Client.answer_inline_query()
|
.. automethod:: Client.send_game()
|
||||||
.. automethod:: pyrogram.Client.request_callback_answer()
|
.. automethod:: Client.set_game_score()
|
||||||
.. automethod:: pyrogram.Client.send_game()
|
.. automethod:: Client.get_game_high_scores()
|
||||||
.. automethod:: pyrogram.Client.set_game_score()
|
|
||||||
.. automethod:: pyrogram.Client.get_game_high_scores()
|
|
||||||
|
@@ -15,102 +15,108 @@ All Pyrogram types listed here are accessible through the main package directly.
|
|||||||
|
|
||||||
.. currentmodule:: pyrogram
|
.. currentmodule:: pyrogram
|
||||||
|
|
||||||
|
Index
|
||||||
|
-----
|
||||||
|
|
||||||
Users & Chats
|
Users & Chats
|
||||||
-------------
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 5
|
||||||
|
|
||||||
User
|
- :class:`User`
|
||||||
UserStatus
|
- :class:`UserStatus`
|
||||||
Chat
|
- :class:`Chat`
|
||||||
ChatPreview
|
- :class:`ChatPreview`
|
||||||
ChatPhoto
|
- :class:`ChatPhoto`
|
||||||
ChatMember
|
- :class:`ChatMember`
|
||||||
ChatMembers
|
- :class:`ChatMembers`
|
||||||
ChatPermissions
|
- :class:`ChatPermissions`
|
||||||
Dialog
|
- :class:`Dialog`
|
||||||
Dialogs
|
- :class:`Dialogs`
|
||||||
|
|
||||||
Messages & Media
|
Messages & Media
|
||||||
----------------
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 5
|
||||||
|
|
||||||
Message
|
- :class:`Message`
|
||||||
Messages
|
- :class:`Messages`
|
||||||
MessageEntity
|
- :class:`MessageEntity`
|
||||||
Photo
|
- :class:`Photo`
|
||||||
PhotoSize
|
- :class:`Photos`
|
||||||
UserProfilePhotos
|
- :class:`Thumbnail`
|
||||||
Audio
|
- :class:`Audio`
|
||||||
Document
|
- :class:`Document`
|
||||||
Animation
|
- :class:`Animation`
|
||||||
Video
|
- :class:`Video`
|
||||||
Voice
|
- :class:`Voice`
|
||||||
VideoNote
|
- :class:`VideoNote`
|
||||||
Contact
|
- :class:`Contact`
|
||||||
Location
|
- :class:`Location`
|
||||||
Venue
|
- :class:`Venue`
|
||||||
Sticker
|
- :class:`Sticker`
|
||||||
Game
|
- :class:`Game`
|
||||||
Poll
|
- :class:`Poll`
|
||||||
PollOption
|
- :class:`PollOption`
|
||||||
|
|
||||||
Keyboards
|
Keyboards
|
||||||
---------
|
^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 4
|
||||||
|
|
||||||
ReplyKeyboardMarkup
|
- :class:`ReplyKeyboardMarkup`
|
||||||
KeyboardButton
|
- :class:`KeyboardButton`
|
||||||
ReplyKeyboardRemove
|
- :class:`ReplyKeyboardRemove`
|
||||||
InlineKeyboardMarkup
|
- :class:`InlineKeyboardMarkup`
|
||||||
InlineKeyboardButton
|
- :class:`InlineKeyboardButton`
|
||||||
ForceReply
|
- :class:`ForceReply`
|
||||||
CallbackQuery
|
- :class:`CallbackQuery`
|
||||||
GameHighScore
|
- :class:`GameHighScore`
|
||||||
GameHighScores
|
- :class:`GameHighScores`
|
||||||
CallbackGame
|
- :class:`CallbackGame`
|
||||||
|
|
||||||
Input Media
|
Input Media
|
||||||
-----------
|
^^^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 4
|
||||||
|
|
||||||
InputMedia
|
- :class:`InputMedia`
|
||||||
InputMediaPhoto
|
- :class:`InputMediaPhoto`
|
||||||
InputMediaVideo
|
- :class:`InputMediaVideo`
|
||||||
InputMediaAudio
|
- :class:`InputMediaAudio`
|
||||||
InputMediaAnimation
|
- :class:`InputMediaAnimation`
|
||||||
InputMediaDocument
|
- :class:`InputMediaDocument`
|
||||||
InputPhoneContact
|
- :class:`InputPhoneContact`
|
||||||
|
|
||||||
Inline Mode
|
Inline Mode
|
||||||
------------
|
^^^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
InlineQuery
|
- :class:`InlineQuery`
|
||||||
InlineQueryResult
|
- :class:`InlineQueryResult`
|
||||||
InlineQueryResultArticle
|
- :class:`InlineQueryResultArticle`
|
||||||
|
|
||||||
InputMessageContent
|
InputMessageContent
|
||||||
-------------------
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. autosummary::
|
.. hlist::
|
||||||
:nosignatures:
|
:columns: 3
|
||||||
|
|
||||||
InputMessageContent
|
- :class:`InputMessageContent`
|
||||||
InputTextMessageContent
|
- :class:`InputTextMessageContent`
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Details
|
||||||
|
-------
|
||||||
|
|
||||||
.. User & Chats
|
.. User & Chats
|
||||||
------------
|
|
||||||
|
|
||||||
.. autoclass:: User()
|
.. autoclass:: User()
|
||||||
.. autoclass:: UserStatus()
|
.. autoclass:: UserStatus()
|
||||||
.. autoclass:: Chat()
|
.. autoclass:: Chat()
|
||||||
@@ -123,14 +129,12 @@ InputMessageContent
|
|||||||
.. autoclass:: Dialogs()
|
.. autoclass:: Dialogs()
|
||||||
|
|
||||||
.. Messages & Media
|
.. Messages & Media
|
||||||
----------------
|
|
||||||
|
|
||||||
.. autoclass:: Message()
|
.. autoclass:: Message()
|
||||||
.. autoclass:: Messages()
|
.. autoclass:: Messages()
|
||||||
.. autoclass:: MessageEntity()
|
.. autoclass:: MessageEntity()
|
||||||
.. autoclass:: Photo()
|
.. autoclass:: Photo()
|
||||||
.. autoclass:: PhotoSize()
|
.. autoclass:: Photos()
|
||||||
.. autoclass:: UserProfilePhotos()
|
.. autoclass:: Thumbnail()
|
||||||
.. autoclass:: Audio()
|
.. autoclass:: Audio()
|
||||||
.. autoclass:: Document()
|
.. autoclass:: Document()
|
||||||
.. autoclass:: Animation()
|
.. autoclass:: Animation()
|
||||||
@@ -146,8 +150,6 @@ InputMessageContent
|
|||||||
.. autoclass:: PollOption()
|
.. autoclass:: PollOption()
|
||||||
|
|
||||||
.. Keyboards
|
.. Keyboards
|
||||||
---------
|
|
||||||
|
|
||||||
.. autoclass:: ReplyKeyboardMarkup()
|
.. autoclass:: ReplyKeyboardMarkup()
|
||||||
.. autoclass:: KeyboardButton()
|
.. autoclass:: KeyboardButton()
|
||||||
.. autoclass:: ReplyKeyboardRemove()
|
.. autoclass:: ReplyKeyboardRemove()
|
||||||
@@ -160,8 +162,6 @@ InputMessageContent
|
|||||||
.. autoclass:: CallbackGame()
|
.. autoclass:: CallbackGame()
|
||||||
|
|
||||||
.. Input Media
|
.. Input Media
|
||||||
-----------
|
|
||||||
|
|
||||||
.. autoclass:: InputMedia()
|
.. autoclass:: InputMedia()
|
||||||
.. autoclass:: InputMediaPhoto()
|
.. autoclass:: InputMediaPhoto()
|
||||||
.. autoclass:: InputMediaVideo()
|
.. autoclass:: InputMediaVideo()
|
||||||
@@ -171,14 +171,10 @@ InputMessageContent
|
|||||||
.. autoclass:: InputPhoneContact()
|
.. autoclass:: InputPhoneContact()
|
||||||
|
|
||||||
.. Inline Mode
|
.. Inline Mode
|
||||||
-----------
|
|
||||||
|
|
||||||
.. autoclass:: InlineQuery()
|
.. autoclass:: InlineQuery()
|
||||||
.. autoclass:: InlineQueryResult()
|
.. autoclass:: InlineQueryResult()
|
||||||
.. autoclass:: InlineQueryResultArticle()
|
.. autoclass:: InlineQueryResultArticle()
|
||||||
|
|
||||||
.. InputMessageContent
|
.. InputMessageContent
|
||||||
-------------------
|
|
||||||
|
|
||||||
.. autoclass:: InputMessageContent()
|
.. autoclass:: InputMessageContent()
|
||||||
.. autoclass:: InputTextMessageContent()
|
.. autoclass:: InputTextMessageContent()
|
||||||
|
@@ -43,7 +43,6 @@ autodoc_member_order = "bysource"
|
|||||||
|
|
||||||
version = __version__
|
version = __version__
|
||||||
release = version
|
release = version
|
||||||
version_rst = ".. |version| replace:: {}".format(version)
|
|
||||||
|
|
||||||
templates_path = ["_templates"]
|
templates_path = ["_templates"]
|
||||||
|
|
||||||
@@ -61,7 +60,8 @@ html_theme_options = {
|
|||||||
"collapse_navigation": True,
|
"collapse_navigation": True,
|
||||||
"sticky_navigation": False,
|
"sticky_navigation": False,
|
||||||
"logo_only": True,
|
"logo_only": True,
|
||||||
"display_version": True
|
"display_version": True,
|
||||||
|
"style_external_links": True
|
||||||
}
|
}
|
||||||
|
|
||||||
html_logo = "_images/pyrogram.png"
|
html_logo = "_images/pyrogram.png"
|
||||||
|
@@ -17,10 +17,9 @@ What is Pyrogram?
|
|||||||
|
|
||||||
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and
|
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and
|
||||||
C. It enables you to easily create custom applications for both user and bot identities (bot API alternative) via the
|
C. It enables you to easily create custom applications for both user and bot identities (bot API alternative) via the
|
||||||
`MTProto API`_ with the Python programming language.
|
:doc:`MTProto API <topics/mtproto-vs-botapi>` with the Python programming language.
|
||||||
|
|
||||||
.. _Telegram: https://telegram.org
|
.. _Telegram: https://telegram.org
|
||||||
.. _MTProto API: topics/mtproto-vs-botapi#what-is-the-mtproto-api
|
|
||||||
|
|
||||||
Where does the name come from?
|
Where does the name come from?
|
||||||
------------------------------
|
------------------------------
|
||||||
@@ -47,19 +46,17 @@ Why Pyrogram?
|
|||||||
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
||||||
- **Updated**, to make use of the latest Telegram API version and features.
|
- **Updated**, to make use of the latest Telegram API version and features.
|
||||||
- **Bot API-like**: Similar to the Bot API in its simplicity, but much more powerful and detailed.
|
- **Bot API-like**: Similar to the Bot API in its simplicity, but much more powerful and detailed.
|
||||||
- **Pluggable**: The `Smart Plugin`_ system allows to write components with minimal boilerplate code.
|
- **Pluggable**: The :doc:`Smart Plugin <topics/smart-plugins>` system allows to write components with minimal
|
||||||
- **Comprehensive**: Execute any `advanced action`_ an official client is able to do, and even more.
|
boilerplate code.
|
||||||
|
- **Comprehensive**: Execute any :doc:`advanced action <topics/advanced-usage>` an official client is able to do, and
|
||||||
|
even more.
|
||||||
|
|
||||||
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
|
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
|
||||||
.. _Smart Plugin: topics/smart-plugins
|
|
||||||
.. _advanced action: topics/advanced-usage
|
|
||||||
|
|
||||||
What can MTProto do more than the Bot API?
|
What can MTProto do more than the Bot API?
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
For a detailed answer, please refer to the `MTProto vs. Bot API`_ page.
|
For a detailed answer, please refer to the :doc:`MTProto vs. Bot API <topics/mtproto-vs-botapi>` page.
|
||||||
|
|
||||||
.. _MTProto vs. Bot API: topics/mtproto-vs-botapi
|
|
||||||
|
|
||||||
Why do I need an API key for bots?
|
Why do I need an API key for bots?
|
||||||
----------------------------------
|
----------------------------------
|
||||||
@@ -97,9 +94,9 @@ Telegram is slowly changing some server's internals and it's doing it in such a
|
|||||||
inevitably. Not only this, but it seems that the new, hypothetical, file ids could also possibly expire at anytime, thus
|
inevitably. Not only this, but it seems that the new, hypothetical, file ids could also possibly expire at anytime, thus
|
||||||
losing the *persistence* feature.
|
losing the *persistence* feature.
|
||||||
|
|
||||||
This change will most likely affect the official `Bot API <topics/mtproto-vs-botapi#what-is-the-bot-api>`_ too
|
This change will most likely affect the official :doc:`Bot API <topics/mtproto-vs-botapi>` too (unless Telegram
|
||||||
(unless Telegram implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn
|
implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn make use of) and
|
||||||
make use of) and we can expect a proper notice from Telegram.
|
we can expect a proper notice from Telegram.
|
||||||
|
|
||||||
Can I use multiple clients at once on the same account?
|
Can I use multiple clients at once on the same account?
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
@@ -125,8 +122,8 @@ from the beginning every time, and use one separate session for each parallel cl
|
|||||||
I started a client and nothing happens!
|
I started a client and nothing happens!
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
If you are connecting from Russia, China or Iran `you need a proxy`_, because Telegram could be partially or
|
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
|
||||||
totally blocked in those countries.
|
partially or totally blocked in those countries.
|
||||||
|
|
||||||
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
|
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
|
||||||
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
|
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
|
||||||
@@ -146,8 +143,6 @@ fails or not:
|
|||||||
- DC4: ``149.154.167.91``
|
- DC4: ``149.154.167.91``
|
||||||
- DC5: ``91.108.56.149``
|
- DC5: ``91.108.56.149``
|
||||||
|
|
||||||
.. _you need a proxy: topics/proxy
|
|
||||||
|
|
||||||
I keep getting PEER_ID_INVALID error!
|
I keep getting PEER_ID_INVALID error!
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
@@ -160,6 +155,15 @@ things:
|
|||||||
chats).
|
chats).
|
||||||
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
|
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
|
||||||
|
|
||||||
|
My verification code expires immediately!
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
That is because you likely shared it across any of your Telegram chats. Yes, that's right: the server keeps scanning the
|
||||||
|
messages you send and if an active verification code is found it will immediately expire, automatically.
|
||||||
|
|
||||||
|
The reason behind this is to protect unaware users from giving their account access to any potential scammer, but if you
|
||||||
|
legitimately want to share your account(s) verification codes, consider scrambling them, e.g. ``12345`` → ``1-2-3-4-5``.
|
||||||
|
|
||||||
My account has been deactivated/limited!
|
My account has been deactivated/limited!
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
@@ -179,23 +183,15 @@ However, you might be right, and your account was deactivated/limited without an
|
|||||||
mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
|
mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
|
||||||
recover@telegram.org, contact `@smstelegram`_ on Twitter or use `this form`_.
|
recover@telegram.org, contact `@smstelegram`_ on Twitter or use `this form`_.
|
||||||
|
|
||||||
|
Are there any secret easter eggs?
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Yes. If you found one, `let me know`_!
|
||||||
|
|
||||||
|
.. _let me know: https://t.me/pyrogram
|
||||||
|
|
||||||
.. _@smstelegram: https://twitter.com/smstelegram
|
.. _@smstelegram: https://twitter.com/smstelegram
|
||||||
.. _this form: https://telegram.org/support
|
.. _this form: https://telegram.org/support
|
||||||
|
|
||||||
About the License
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png
|
|
||||||
:align: left
|
|
||||||
|
|
||||||
Pyrogram is free software and is currently licensed under the terms of the
|
|
||||||
`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it
|
|
||||||
provided that modifications are described and licensed for free under LGPLv3+.
|
|
||||||
|
|
||||||
In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or
|
|
||||||
different license, or even proprietary --- without being required to release the source code of your own applications.
|
|
||||||
However, any modifications to the library itself are required to be published for free under the same LGPLv3+ license.
|
|
||||||
|
|
||||||
.. _GNU Lesser General Public License v3 or later (LGPLv3+): https://github.com/pyrogram/pyrogram/blob/develop/COPYING.lesser
|
|
||||||
.. _Bug Report: https://github.com/pyrogram/pyrogram/issues/new?labels=bug&template=bug_report.md
|
.. _Bug Report: https://github.com/pyrogram/pyrogram/issues/new?labels=bug&template=bug_report.md
|
||||||
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md
|
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md
|
||||||
|
@@ -18,7 +18,7 @@ general. Some words may as well link to dedicated articles in case the topic is
|
|||||||
API key
|
API key
|
||||||
A secret code used to authenticate and/or authorize a specific application to Telegram in order for it to
|
A secret code used to authenticate and/or authorize a specific application to Telegram in order for it to
|
||||||
control how the API is being used, for example, to prevent abuses of the API.
|
control how the API is being used, for example, to prevent abuses of the API.
|
||||||
`More on API keys <intro/setup#api-keys>`_.
|
:doc:`More on API keys <intro/setup>`.
|
||||||
|
|
||||||
DC
|
DC
|
||||||
Also known as *data center*, is a place where lots of computer systems are housed and used together in order to
|
Also known as *data center*, is a place where lots of computer systems are housed and used together in order to
|
||||||
@@ -30,21 +30,21 @@ general. Some words may as well link to dedicated articles in case the topic is
|
|||||||
|
|
||||||
RPCError
|
RPCError
|
||||||
An error caused by an RPC which must be returned in place of the successful result in order to let the caller
|
An error caused by an RPC which must be returned in place of the successful result in order to let the caller
|
||||||
know something went wrong. `More on RPCError <start/errors>`_.
|
know something went wrong. :doc:`More on RPCError <start/errors>`.
|
||||||
|
|
||||||
MTProto
|
MTProto
|
||||||
The name of the custom-made, open and encrypted protocol by Telegram, implemented in Pyrogram.
|
The name of the custom-made, open and encrypted protocol by Telegram, implemented in Pyrogram.
|
||||||
`More on MTProto <topics/mtproto-vs-botapi>`_.
|
:doc:`More on MTProto <topics/mtproto-vs-botapi>`.
|
||||||
|
|
||||||
MTProto API
|
MTProto API
|
||||||
The Telegram main API Pyrogram makes use of, which is able to connect both users and normal bots to Telegram
|
The Telegram main API Pyrogram makes use of, which is able to connect both users and normal bots to Telegram
|
||||||
using MTProto as application layer protocol and execute any method Telegram provides from its public TL-schema.
|
using MTProto as application layer protocol and execute any method Telegram provides from its public TL-schema.
|
||||||
`More on MTProto API <topics/mtproto-vs-botapi#what-is-the-mtproto-api>`_.
|
:doc:`More on MTProto API <topics/mtproto-vs-botapi>`.
|
||||||
|
|
||||||
Bot API
|
Bot API
|
||||||
The Telegram Bot API that is able to only connect normal bots only to Telegram using HTTP as application layer
|
The Telegram Bot API that is able to only connect normal bots only to Telegram using HTTP as application layer
|
||||||
protocol and allows to execute a sub-set of the main Telegram API.
|
protocol and allows to execute a sub-set of the main Telegram API.
|
||||||
`More on Bot API <topics/mtproto-vs-botapi#what-is-the-bot-api>`_.
|
:doc:`More on Bot API <topics/mtproto-vs-botapi>`.
|
||||||
|
|
||||||
Pyrogrammer
|
Pyrogrammer
|
||||||
A developer that uses Pyrogram to build Telegram applications.
|
A developer that uses Pyrogram to build Telegram applications.
|
||||||
@@ -65,11 +65,11 @@ general. Some words may as well link to dedicated articles in case the topic is
|
|||||||
Handler
|
Handler
|
||||||
An object that wraps around a callback function that is *actually meant* to be registered into the framework,
|
An object that wraps around a callback function that is *actually meant* to be registered into the framework,
|
||||||
which will then be able to handle a specific kind of events, such as a new incoming message, for example.
|
which will then be able to handle a specific kind of events, such as a new incoming message, for example.
|
||||||
`More on Handlers <start/updates>`_.
|
:doc:`More on Handlers <start/updates>`.
|
||||||
|
|
||||||
Decorator
|
Decorator
|
||||||
Also known as *function decorator*, in Python, is a callable object that is used to modify another function.
|
Also known as *function decorator*, in Python, is a callable object that is used to modify another function.
|
||||||
Decorators in Pyrogram are used to automatically register callback functions for handling updates.
|
Decorators in Pyrogram are used to automatically register callback functions for handling updates.
|
||||||
`More on Decorators <start/updates#using-decorators>`_.
|
:doc:`More on Decorators <start/updates>`.
|
||||||
|
|
||||||
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md
|
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md
|
||||||
|
@@ -42,10 +42,9 @@ Welcome to Pyrogram
|
|||||||
|
|
||||||
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and
|
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and
|
||||||
C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the
|
C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the
|
||||||
`MTProto API`_.
|
:doc:`MTProto API <topics/mtproto-vs-botapi>`.
|
||||||
|
|
||||||
.. _Telegram: https://telegram.org
|
.. _Telegram: https://telegram.org
|
||||||
.. _MTProto API: topics/mtproto-vs-botapi#what-is-the-mtproto-api
|
|
||||||
|
|
||||||
How the Documentation is Organized
|
How the Documentation is Organized
|
||||||
----------------------------------
|
----------------------------------
|
||||||
@@ -60,15 +59,10 @@ First Steps
|
|||||||
.. hlist::
|
.. hlist::
|
||||||
:columns: 2
|
:columns: 2
|
||||||
|
|
||||||
- `Quick Start`_: Overview to get you started quickly.
|
- :doc:`Quick Start <intro/quickstart>`: Overview to get you started quickly.
|
||||||
- `Calling Methods`_: How to call Pyrogram's methods.
|
- :doc:`Calling Methods <start/invoking>`: How to call Pyrogram's methods.
|
||||||
- `Handling Updates`_: How to handle Telegram updates.
|
- :doc:`Handling Updates <start/updates>`: How to handle Telegram updates.
|
||||||
- `Error Handling`_: How to handle API errors correctly.
|
- :doc:`Error Handling <start/errors>`: How to handle API errors correctly.
|
||||||
|
|
||||||
.. _Quick Start: intro/quickstart
|
|
||||||
.. _Calling Methods: start/invoking
|
|
||||||
.. _Handling Updates: start/updates
|
|
||||||
.. _Error Handling: start/errors
|
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
@@ -76,15 +70,10 @@ API Reference
|
|||||||
.. hlist::
|
.. hlist::
|
||||||
:columns: 2
|
:columns: 2
|
||||||
|
|
||||||
- `Pyrogram Client`_: Reference details about the Client class.
|
- :doc:`Pyrogram Client <api/client>`: Reference details about the Client class.
|
||||||
- `Available Methods`_: List of available high-level methods.
|
- :doc:`Available Methods <api/methods>`: List of available high-level methods.
|
||||||
- `Available Types`_: List of available high-level types.
|
- :doc:`Available Types <api/types>`: List of available high-level types.
|
||||||
- `Bound Methods`_: List of convenient bound methods.
|
- :doc:`Bound Methods <api/bound-methods>`: List of convenient bound methods.
|
||||||
|
|
||||||
.. _Pyrogram Client: ./api/client
|
|
||||||
.. _Available Methods: api/methods
|
|
||||||
.. _Available Types: api/types
|
|
||||||
.. _Bound Methods: api/bound-methods
|
|
||||||
|
|
||||||
Meta
|
Meta
|
||||||
----
|
----
|
||||||
@@ -92,17 +81,12 @@ Meta
|
|||||||
.. hlist::
|
.. hlist::
|
||||||
:columns: 2
|
:columns: 2
|
||||||
|
|
||||||
- `Pyrogram FAQ`_: Answers to common Pyrogram questions.
|
- :doc:`Pyrogram FAQ <faq>`: Answers to common Pyrogram questions.
|
||||||
- `Pyrogram Glossary`_: List of words with brief explanations.
|
- :doc:`Pyrogram Glossary <glossary>`: List of words with brief explanations.
|
||||||
- `Release Notes`_: Release notes for Pyrogram releases.
|
- :doc:`Release Notes <releases>`: Release notes for Pyrogram releases.
|
||||||
- `Powered by Pyrogram`_: Collection of Pyrogram Projects.
|
- :doc:`Powered by Pyrogram <powered-by>`: Collection of Pyrogram Projects.
|
||||||
- `Support Pyrogram`_: Ways to show your appreciation.
|
- :doc:`Support Pyrogram <support-pyrogram>`: Ways to show your appreciation.
|
||||||
|
- :doc:`About the License <license>`: Information about the Project license.
|
||||||
.. _Pyrogram FAQ: faq
|
|
||||||
.. _Pyrogram Glossary: glossary
|
|
||||||
.. _Release Notes: releases
|
|
||||||
.. _Powered by Pyrogram: powered-by
|
|
||||||
.. _Support Pyrogram: support-pyrogram
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
@@ -163,10 +147,13 @@ Meta
|
|||||||
releases
|
releases
|
||||||
powered-by
|
powered-by
|
||||||
support-pyrogram
|
support-pyrogram
|
||||||
|
license
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
:caption: Telegram API
|
:caption: Telegram API
|
||||||
|
|
||||||
telegram/functions/index
|
telegram/functions/index
|
||||||
telegram/types/index
|
telegram/types/index
|
||||||
|
|
||||||
|
Last updated on |today|
|
@@ -20,7 +20,7 @@ Install Pyrogram
|
|||||||
|
|
||||||
$ pip3 install -U pyrogram
|
$ pip3 install -U pyrogram
|
||||||
|
|
||||||
- or, with TgCrypto_ as extra requirement (recommended):
|
- or, with :doc:`TgCrypto <../topics/tgcrypto>` as extra requirement (recommended):
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@@ -89,5 +89,4 @@ If no error shows up you are good to go.
|
|||||||
>>> pyrogram.__version__
|
>>> pyrogram.__version__
|
||||||
'|version|'
|
'|version|'
|
||||||
|
|
||||||
.. _TgCrypto: ../topics/tgcrypto
|
|
||||||
.. _`Github repo`: http://github.com/pyrogram/pyrogram
|
.. _`Github repo`: http://github.com/pyrogram/pyrogram
|
||||||
|
@@ -43,7 +43,7 @@ Enjoy the API
|
|||||||
That was just a quick overview that barely scratched the surface!
|
That was just a quick overview that barely scratched the surface!
|
||||||
In the next few pages of the introduction, we'll take a much more in-depth look of what we have just done above.
|
In the next few pages of the introduction, we'll take a much more in-depth look of what we have just done above.
|
||||||
|
|
||||||
Feeling eager to continue? You can take a shortcut to `Calling Methods`_ and come back later to learn some more details.
|
Feeling eager to continue? You can take a shortcut to :doc:`Calling Methods <../start/invoking>` and come back later to
|
||||||
|
learn some more details.
|
||||||
|
|
||||||
.. _community: //t.me/Pyrogram
|
.. _community: //t.me/Pyrogram
|
||||||
.. _Calling Methods: ../start/invoking
|
|
@@ -1,8 +1,8 @@
|
|||||||
Project Setup
|
Project Setup
|
||||||
=============
|
=============
|
||||||
|
|
||||||
We have just `installed Pyrogram`_. In this page we'll discuss what you need to do in order to set up a project with
|
We have just :doc:`installed Pyrogram <install>`. In this page we'll discuss what you need to do in order to set up a
|
||||||
the library. Let's see how it's done.
|
project with the library. Let's see how it's done.
|
||||||
|
|
||||||
API Keys
|
API Keys
|
||||||
--------
|
--------
|
||||||
@@ -26,7 +26,7 @@ The very first step requires you to obtain a valid Telegram API key (API id/hash
|
|||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Having the API key from the `previous step <#api-keys>`_ in handy, we can now begin to configure a Pyrogram project.
|
Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project.
|
||||||
There are two ways to do so, and you can choose what fits better for you:
|
There are two ways to do so, and you can choose what fits better for you:
|
||||||
|
|
||||||
- First option (recommended): create a new ``config.ini`` file at the root of your working directory, copy-paste the
|
- First option (recommended): create a new ``config.ini`` file at the root of your working directory, copy-paste the
|
||||||
@@ -57,5 +57,3 @@ There are two ways to do so, and you can choose what fits better for you:
|
|||||||
|
|
||||||
To keep code snippets clean and concise, from now on it is assumed you are making use of the ``config.ini`` file,
|
To keep code snippets clean and concise, from now on it is assumed you are making use of the ``config.ini`` file,
|
||||||
thus, the *api_id* and *api_hash* parameters usage won't be shown anymore.
|
thus, the *api_id* and *api_hash* parameters usage won't be shown anymore.
|
||||||
|
|
||||||
.. _installed Pyrogram: install.html
|
|
||||||
|
15
docs/source/license.rst
Normal file
15
docs/source/license.rst
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
About the License
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png
|
||||||
|
:align: left
|
||||||
|
|
||||||
|
Pyrogram is free software and is currently licensed under the terms of the
|
||||||
|
`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it
|
||||||
|
provided that modifications are described and licensed for free under LGPLv3+.
|
||||||
|
|
||||||
|
In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or a
|
||||||
|
different license, or even proprietary --- without being required to release the source code of your own applications.
|
||||||
|
However, any modifications to the library itself are required to be published for free under the same LGPLv3+ license.
|
||||||
|
|
||||||
|
.. _GNU Lesser General Public License v3 or later (LGPLv3+): https://github.com/pyrogram/pyrogram/blob/develop/COPYING.lesser
|
@@ -1,7 +1,7 @@
|
|||||||
Authorization
|
Authorization
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Once a `project is set up`_, you will still have to follow a few steps before you can actually use Pyrogram to make
|
Once a :doc:`project is set up <../intro/setup>`, you will still have to follow a few steps before you can actually use Pyrogram to make
|
||||||
API calls. This section provides all the information you need in order to authorize yourself as user or bot.
|
API calls. This section provides all the information you need in order to authorize yourself as user or bot.
|
||||||
|
|
||||||
User Authorization
|
User Authorization
|
||||||
@@ -9,8 +9,8 @@ User Authorization
|
|||||||
|
|
||||||
In order to use the API, Telegram requires that users be authorized via their phone numbers.
|
In order to use the API, Telegram requires that users be authorized via their phone numbers.
|
||||||
Pyrogram automatically manages this process, all you need to do is create an instance of the
|
Pyrogram automatically manages this process, all you need to do is create an instance of the
|
||||||
:class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
|
:class:`~pyrogram.Client` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
|
||||||
the :meth:`run() <pyrogram.Client.run>` method:
|
the :meth:`~pyrogram.Client.run` method:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ Bot Authorization
|
|||||||
|
|
||||||
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
|
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
|
||||||
the `Bot Father`_. Bot tokens replace the users' phone numbers only — you still need to
|
the `Bot Father`_. Bot tokens replace the users' phone numbers only — you still need to
|
||||||
`configure a Telegram API key <../intro/setup#configuration>`_ with Pyrogram, even when using bots.
|
:doc:`configure a Telegram API key <../intro/setup>` with Pyrogram, even when using bots.
|
||||||
|
|
||||||
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
|
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
|
||||||
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
|
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
|
||||||
@@ -64,6 +64,5 @@ after the session name, which will be ``my_bot.session`` for the example below.
|
|||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
.. _project is set up: ../intro/setup
|
|
||||||
.. _Country Code: https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
.. _Country Code: https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
||||||
.. _Bot Father: https://t.me/botfather
|
.. _Bot Father: https://t.me/botfather
|
@@ -1,8 +1,8 @@
|
|||||||
Calling Methods
|
Calling Methods
|
||||||
===============
|
===============
|
||||||
|
|
||||||
At this point, we have successfully `installed Pyrogram`_ and authorized_ our account; we are now aiming towards the
|
At this point, we have successfully :doc:`installed Pyrogram <../intro/install>` and :doc:`authorized <auth>` our
|
||||||
core of the library. It's time to start playing with the API!
|
account; we are now aiming towards the core of the library. It's time to start playing with the API!
|
||||||
|
|
||||||
Basic Usage
|
Basic Usage
|
||||||
-----------
|
-----------
|
||||||
@@ -63,8 +63,8 @@ Context Manager
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
You can also use Pyrogram's Client in a context manager with the ``with`` statement. The client will automatically
|
You can also use Pyrogram's Client in a context manager with the ``with`` statement. The client will automatically
|
||||||
:meth:`start() <pyrogram.Client.start>` and :meth:`stop() <pyrogram.Client.stop>` gracefully, even in case of unhandled
|
:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop` gracefully, even in case of unhandled exceptions in
|
||||||
exceptions in your code. The example above can be therefore rewritten in a much nicer way:
|
your code. The example above can be therefore rewritten in a much nicer way:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -79,6 +79,3 @@ exceptions in your code. The example above can be therefore rewritten in a much
|
|||||||
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||||
|
|
||||||
More examples can be found on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
More examples can be found on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
||||||
|
|
||||||
.. _installed Pyrogram: ../intro/install.html
|
|
||||||
.. _authorized: ../intro/setup.html
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
Handling Updates
|
Handling Updates
|
||||||
================
|
================
|
||||||
|
|
||||||
Calling `API methods`_ sequentially is cool, but how to react when, for example, a new message arrives? This page deals
|
Calling :doc:`API methods <invoking>` sequentially is cool, but how to react when, for example, a new message arrives?
|
||||||
with updates and how to handle such events in Pyrogram. Let's have a look at how they work.
|
This page deals with updates and how to handle such events in Pyrogram. Let's have a look at how they work.
|
||||||
|
|
||||||
Defining Updates
|
Defining Updates
|
||||||
----------------
|
----------------
|
||||||
@@ -10,7 +10,7 @@ Defining Updates
|
|||||||
First, let's define what are these updates. As hinted already, updates are simply events that happen in your Telegram
|
First, let's define what are these updates. As hinted already, updates are simply events that happen in your Telegram
|
||||||
account (incoming messages, new members join, bot button presses, etc...), which are meant to notify you about a new
|
account (incoming messages, new members join, bot button presses, etc...), which are meant to notify you about a new
|
||||||
specific state that has changed. These updates are handled by registering one or more callback functions in your app
|
specific state that has changed. These updates are handled by registering one or more callback functions in your app
|
||||||
using `Handlers <../api/handlers>`_.
|
using :doc:`Handlers <../api/handlers>`.
|
||||||
|
|
||||||
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
|
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
|
||||||
function will be called back by the framework and its body executed.
|
function will be called back by the framework and its body executed.
|
||||||
@@ -18,17 +18,16 @@ function will be called back by the framework and its body executed.
|
|||||||
Registering a Handler
|
Registering a Handler
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
To explain how handlers work let's have a look at the most used one, the
|
To explain how handlers work let's have a look at the most used one, the :class:`~pyrogram.MessageHandler`, which will
|
||||||
:obj:`MessageHandler <pyrogram.MessageHandler>`, which will be in charge for handling :obj:`Message <pyrogram.Message>`
|
be in charge for handling :class:`~pyrogram.Message` updates coming from all around your chats. Every other handler shares
|
||||||
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
the same setup logic; you should not have troubles settings them up once you learn from this section.
|
||||||
settings them up once you learn from this section.
|
|
||||||
|
|
||||||
Using add_handler()
|
Using add_handler()
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
The :meth:`add_handler() <pyrogram.Client.add_handler>` method takes any handler instance that wraps around your defined
|
The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback
|
||||||
callback function and registers it in your Client. Here's a full example that prints out the content of a message as
|
function and registers it in your Client. Here's a full example that prints out the content of a message as soon as it
|
||||||
soon as it arrives:
|
arrives:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -55,24 +54,23 @@ call that function by passing the client instance and the new message instance a
|
|||||||
def my_function(client, message):
|
def my_function(client, message):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
Second one: the :obj:`MessageHandler <pyrogram.MessageHandler>`. This object tells Pyrogram the function we defined
|
Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must only
|
||||||
above must only handle updates that are in form of a :obj:`Message <pyrogram.Message>`:
|
handle updates that are in form of a :class:`~pyrogram.Message`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
my_handler = MessageHandler(my_function)
|
my_handler = MessageHandler(my_function)
|
||||||
|
|
||||||
Third: the method :meth:`add_handler() <pyrogram.Client.add_handler>`. This method is used to actually register the
|
Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
|
||||||
handler and let Pyrogram know it needs to be taken into consideration when new updates arrive and the internal
|
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase begins.
|
||||||
dispatching phase begins.
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
app.add_handler(my_handler)
|
app.add_handler(my_handler)
|
||||||
|
|
||||||
Last one, the :meth:`run() <pyrogram.Client.run>` method. What this does is simply call
|
Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and a
|
||||||
:meth:`start() <pyrogram.Client.start>` and a special method :meth:`idle() <pyrogram.Client.idle>` that keeps your main
|
special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the client
|
||||||
scripts alive until you press ``CTRL+C``; the client will be automatically stopped after that.
|
will be automatically stopped after that.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -82,7 +80,7 @@ Using Decorators
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
All of the above will become quite verbose, especially in case you have lots of handlers to register. A much nicer way
|
All of the above will become quite verbose, especially in case you have lots of handlers to register. A much nicer way
|
||||||
to do so is by decorating your callback function with the :meth:`on_message() <pyrogram.Client.on_message>` decorator.
|
to do so is by decorating your callback function with the :meth:`~pyrogram.Client.on_message` decorator.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -108,5 +106,3 @@ to do so is by decorating your callback function with the :meth:`on_message() <p
|
|||||||
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
|
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
|
||||||
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
|
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
|
||||||
tuple, accessed by bracket notation *[0]*.
|
tuple, accessed by bracket notation *[0]*.
|
||||||
|
|
||||||
.. _API methods: invoking
|
|
@@ -1,8 +1,8 @@
|
|||||||
Support Pyrogram
|
Support Pyrogram
|
||||||
================
|
================
|
||||||
|
|
||||||
Pyrogram is free and open source software, and thus supported by your love! If you like the project and have found it to
|
Pyrogram is free and open source software, and thus powered by your love and support! If you like the project and have
|
||||||
be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated.
|
found it to be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
@@ -12,8 +12,9 @@ be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and
|
|||||||
Donate
|
Donate
|
||||||
------
|
------
|
||||||
|
|
||||||
If you'd also like to donate in order to support Pyrogram -- or any of my `other works`_ -- you can use the PayPal
|
As a developer, you probably understand that "open source" doesn't mean "free work". A lot of time and resources has
|
||||||
button below. Thank you.
|
been put into the project and if you'd like to tip me for Pyrogram -- or any of my `other works`_ -- you can use the
|
||||||
|
PayPal button below. Thank you!
|
||||||
|
|
||||||
.. image:: https://i.imgur.com/fasFTzK.png
|
.. image:: https://i.imgur.com/fasFTzK.png
|
||||||
:target: https://paypal.me/delivrance
|
:target: https://paypal.me/delivrance
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
Advanced Usage
|
Advanced Usage
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Pyrogram's API, which consists of well documented convenience methods_ and facade types_, exists to provide a much
|
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods>` and facade
|
||||||
easier interface to the undocumented and often confusing Telegram API.
|
:doc:`types <../api/types>`, exists to provide a much easier interface to the undocumented and often confusing Telegram
|
||||||
|
API.
|
||||||
|
|
||||||
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
|
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
|
||||||
Telegram API with its functions and types.
|
Telegram API with its functions and types.
|
||||||
@@ -11,7 +12,7 @@ Telegram Raw API
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
|
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
|
||||||
Telegram API, you have to use the raw :mod:`functions <pyrogram.api.functions>` and :mod:`types <pyrogram.api.types>`.
|
Telegram API, you have to use the raw :mod:`~pyrogram.api.functions` and :mod:`~pyrogram.api.types`.
|
||||||
|
|
||||||
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
|
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
|
||||||
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
|
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
|
||||||
@@ -21,24 +22,25 @@ some pitfalls to take into consideration when working with the raw API.
|
|||||||
|
|
||||||
Every available high-level methods in Pyrogram is built on top of these raw functions.
|
Every available high-level methods in Pyrogram is built on top of these raw functions.
|
||||||
|
|
||||||
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
|
Nothing stops you from using the raw functions only, but they are rather complex and
|
||||||
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API (yet much more
|
:doc:`plenty of them <../api/methods>` are already re-implemented by providing a much simpler and cleaner interface
|
||||||
powerful).
|
which is very similar to the Bot API (yet much more powerful).
|
||||||
|
|
||||||
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
||||||
|
|
||||||
Invoking Functions
|
Invoking Functions
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Unlike the methods_ found in Pyrogram's API, which can be called in the usual simple way, functions to be invoked from
|
Unlike the :doc:`methods <../api/methods>` found in Pyrogram's API, which can be called in the usual simple way,
|
||||||
the raw Telegram API have a different way of usage and are more complex.
|
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
|
||||||
|
|
||||||
First of all, both `raw functions`_ and `raw types`_ live in their respective packages (and sub-packages):
|
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>` live in their
|
||||||
``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python classes, meaning you need to create an
|
respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python
|
||||||
instance of each every time you need them and fill them in with the correct values using named arguments.
|
classes, meaning you need to create an instance of each every time you need them and fill them in with the correct
|
||||||
|
values using named arguments.
|
||||||
|
|
||||||
Next, to actually invoke the raw function you have to use the :meth:`send() <pyrogram.Client.send>` method provided by
|
Next, to actually invoke the raw function you have to use the :meth:`~pyrogram.Client.send` method provided by the
|
||||||
the Client class and pass the function object you created.
|
Client class and pass the function object you created.
|
||||||
|
|
||||||
Here's some examples:
|
Here's some examples:
|
||||||
|
|
||||||
@@ -101,12 +103,12 @@ sending messages with IDs only thanks to cached access hashes.
|
|||||||
There are three different InputPeer types, one for each kind of Telegram entity.
|
There are three different InputPeer types, one for each kind of Telegram entity.
|
||||||
Whenever an InputPeer is needed you must pass one of these:
|
Whenever an InputPeer is needed you must pass one of these:
|
||||||
|
|
||||||
- :obj:`InputPeerUser <../telegram/types/InputPeerUser>` - Users
|
- :class:`~pyrogram.api.types.InputPeerUser` - Users
|
||||||
- :obj:`InputPeerChat <../telegram/types/InputPeerChat>` - Basic Chats
|
- :class:`~pyrogram.api.types.InputPeerChat` - Basic Chats
|
||||||
- :obj:`InputPeerChannel <../telegram/types/InputPeerChannel>` - Either Channels or Supergroups
|
- :class:`~pyrogram.api.types.InputPeerChannel` - Either Channels or Supergroups
|
||||||
|
|
||||||
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
|
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
|
||||||
:meth:`resolve_peer() <pyrogram.Client.resolve_peer>` as a convenience utility method that returns the correct InputPeer
|
:meth:`~pyrogram.Client.resolve_peer` as a convenience utility method that returns the correct InputPeer
|
||||||
by accepting a peer ID only.
|
by accepting a peer ID only.
|
||||||
|
|
||||||
Another thing to take into consideration about chat IDs is the way they are represented: they are all integers and
|
Another thing to take into consideration about chat IDs is the way they are represented: they are all integers and
|
||||||
@@ -125,9 +127,4 @@ For example, given the ID *123456789*, here's how Pyrogram can tell entities apa
|
|||||||
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
|
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
|
||||||
high-level method.
|
high-level method.
|
||||||
|
|
||||||
.. _methods: ../api/methods
|
|
||||||
.. _types: ../api/types
|
|
||||||
.. _plenty of them: ../api/methods
|
|
||||||
.. _raw functions: ../telegram/functions
|
|
||||||
.. _raw types: ../telegram/types
|
|
||||||
.. _Community: https://t.me/Pyrogram
|
.. _Community: https://t.me/Pyrogram
|
@@ -3,7 +3,7 @@ Auto Authorization
|
|||||||
|
|
||||||
Manually writing phone number, phone code and password on the terminal every time you want to login can be tedious.
|
Manually writing phone number, phone code and password on the terminal every time you want to login can be tedious.
|
||||||
Pyrogram is able to automate both **Log In** and **Sign Up** processes, all you need to do is pass the relevant
|
Pyrogram is able to automate both **Log In** and **Sign Up** processes, all you need to do is pass the relevant
|
||||||
parameters when creating a new :class:`Client <pyrogram.Client>`.
|
parameters when creating a new :class:`~pyrogram.Client`.
|
||||||
|
|
||||||
.. note:: If you omit any of the optional parameter required for the authorization, Pyrogram will ask you to
|
.. note:: If you omit any of the optional parameter required for the authorization, Pyrogram will ask you to
|
||||||
manually write it. For instance, if you don't want to set a ``last_name`` when creating a new account you
|
manually write it. For instance, if you don't want to set a ``last_name`` when creating a new account you
|
||||||
|
@@ -7,8 +7,7 @@ Inline Bots
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
- If a bot accepts inline queries, you can call it by using
|
- If a bot accepts inline queries, you can call it by using
|
||||||
:meth:`get_inline_bot_results() <pyrogram.Client.get_inline_bot_results>` to get the list of its inline results
|
:meth:`~pyrogram.Client.get_inline_bot_results` to get the list of its inline results for a query:
|
||||||
for a query:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ Inline Bots
|
|||||||
results list.
|
results list.
|
||||||
|
|
||||||
- After you retrieved the bot results, you can use
|
- After you retrieved the bot results, you can use
|
||||||
:meth:`send_inline_bot_result() <pyrogram.Client.send_inline_bot_result>` to send a chosen result to any chat:
|
:meth:`~pyrogram.Client.send_inline_bot_result` to send a chosen result to any chat:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ Using Filters
|
|||||||
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
|
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
|
||||||
but there's much more than that to come.
|
but there's much more than that to come.
|
||||||
|
|
||||||
Here we'll discuss about :class:`Filters <pyrogram.Filters>`. Filters enable a fine-grain control over what kind of
|
Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of
|
||||||
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
||||||
|
|
||||||
Single Filters
|
Single Filters
|
||||||
@@ -12,7 +12,7 @@ Single Filters
|
|||||||
|
|
||||||
Let's start right away with a simple example:
|
Let's start right away with a simple example:
|
||||||
|
|
||||||
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
|
- This example will show you how to **only** handle messages containing an :class:`~pyrogram.Audio` object and
|
||||||
ignore any other message. Filters are passed as the first argument of the decorator:
|
ignore any other message. Filters are passed as the first argument of the decorator:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@@ -69,7 +69,7 @@ Here are some examples:
|
|||||||
Advanced Filters
|
Advanced Filters
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Some filters, like :meth:`command() <pyrogram.Filters.command>` or :meth:`regex() <pyrogram.Filters.regex>`
|
Some filters, like :meth:`~pyrogram.Filters.command` or :meth:`~pyrogram.Filters.regex`
|
||||||
can also accept arguments:
|
can also accept arguments:
|
||||||
|
|
||||||
- Message is either a */start* or */help* **command**.
|
- Message is either a */start* or */help* **command**.
|
||||||
@@ -109,18 +109,18 @@ More handlers using different filters can also live together.
|
|||||||
Custom Filters
|
Custom Filters
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Pyrogram already provides lots of built-in :class:`Filters <pyrogram.Filters>` to work with, but in case you can't find
|
Pyrogram already provides lots of built-in :class:`~pyrogram.Filters` to work with, but in case you can't find
|
||||||
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
|
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
|
||||||
for example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
for example) you can use :meth:`~pyrogram.Filters.create`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
|
|
||||||
only.
|
At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only.
|
||||||
|
|
||||||
An example to demonstrate how custom filters work is to show how to create and use one for the
|
An example to demonstrate how custom filters work is to show how to create and use one for the
|
||||||
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by
|
:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots; create and
|
||||||
bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline
|
:doc:`authorize your bot <../start/auth>`, then send a message with an inline keyboard to yourself. This allows you to
|
||||||
keyboard to yourself. This allows you to test your filter by pressing the inline button:
|
test your filter by pressing the inline button:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ keyboard to yourself. This allows you to test your filter by pressing the inline
|
|||||||
Basic Filters
|
Basic Filters
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
For this basic filter we will be using only the first two parameters of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
For this basic filter we will be using only the first two parameters of :meth:`~pyrogram.Filters.create`.
|
||||||
|
|
||||||
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
||||||
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
|
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
|
||||||
@@ -175,7 +175,7 @@ Filters with Arguments
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
|
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
|
||||||
A dynamic filter like this will make use of the third parameter of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
A dynamic filter like this will make use of the third parameter of :meth:`~pyrogram.Filters.create`.
|
||||||
|
|
||||||
This is how a dynamic custom filter looks like:
|
This is how a dynamic custom filter looks like:
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
More on Updates
|
More on Updates
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Here we'll show some advanced usages when working with `update handlers`_ and `filters`_.
|
Here we'll show some advanced usages when working with :doc:`update handlers <../start/updates>` and
|
||||||
|
:doc:`filters <filters>`.
|
||||||
|
|
||||||
Handler Groups
|
Handler Groups
|
||||||
--------------
|
--------------
|
||||||
@@ -44,7 +45,7 @@ Or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-
|
|||||||
def just_text(client, message):
|
def just_text(client, message):
|
||||||
print("Just Text")
|
print("Just Text")
|
||||||
|
|
||||||
With :meth:`add_handler() <pyrogram.Client.add_handler>` (without decorators) the same can be achieved with:
|
With :meth:`~pyrogram.Client.add_handler` (without decorators) the same can be achieved with:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -217,6 +218,3 @@ The output of both (equivalent) examples will be:
|
|||||||
0
|
0
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
|
|
||||||
.. _`update handlers`: ../start/updates
|
|
||||||
.. _`filters`: filters
|
|
@@ -9,7 +9,8 @@ For Humans - str(obj)
|
|||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
If you want a nicely formatted, human readable JSON representation of any object in the API -- namely, any object from
|
If you want a nicely formatted, human readable JSON representation of any object in the API -- namely, any object from
|
||||||
`Pyrogram types`_, `raw functions`_ and `raw types`_ -- you can use use ``str(obj)``.
|
:doc:`Pyrogram types <../api/types>`, :doc:`raw functions <../telegram/functions/index>` and
|
||||||
|
:doc:`raw types <../telegram/types/index>` -- you can use use ``str(obj)``.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -25,10 +26,6 @@ If you want a nicely formatted, human readable JSON representation of any object
|
|||||||
When using ``print()`` you don't actually need to use ``str()`` on the object because it is called automatically, we
|
When using ``print()`` you don't actually need to use ``str()`` on the object because it is called automatically, we
|
||||||
have done that above just to show you how to explicitly convert a Pyrogram object to JSON.
|
have done that above just to show you how to explicitly convert a Pyrogram object to JSON.
|
||||||
|
|
||||||
.. _Pyrogram types: ../api/types
|
|
||||||
.. _raw functions: ../telegram/functions
|
|
||||||
.. _raw types: ../telegram/types
|
|
||||||
|
|
||||||
For Machines - repr(obj)
|
For Machines - repr(obj)
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ As you may probably know, Telegram allows users (and bots) having more than one
|
|||||||
in the system at the same time.
|
in the system at the same time.
|
||||||
|
|
||||||
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
|
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
|
||||||
app (or by invoking `GetAuthorizations <../telegram/functions/account/GetAuthorizations.html>`_ with Pyrogram). They
|
app (or by invoking :class:`~pyrogram.api.functions.account.GetAuthorizations` with Pyrogram). They
|
||||||
store some useful information such as the client who's using them and from which country and IP address.
|
store some useful information such as the client who's using them and from which country and IP address.
|
||||||
|
|
||||||
.. figure:: https://i.imgur.com/YaqtMLO.png
|
.. figure:: https://i.imgur.com/YaqtMLO.png
|
||||||
|
@@ -65,8 +65,8 @@ after importing your modules, like this:
|
|||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
|
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
|
||||||
manually ``import``, manually :meth:`add_handler() <pyrogram.Client.add_handler>` and manually instantiate each
|
manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each
|
||||||
:obj:`MessageHandler <pyrogram.MessageHandler>` object because **you can't use those cool decorators** for your
|
:class:`~pyrogram.MessageHandler` object because **you can't use those cool decorators** for your
|
||||||
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
|
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
|
||||||
|
|
||||||
Using Smart Plugins
|
Using Smart Plugins
|
||||||
@@ -80,7 +80,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
This is the same example application `as shown above <#introduction>`_, written using the Smart Plugin system.
|
This is the same example application as shown above, written using the Smart Plugin system.
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
:emphasize-lines: 2, 3
|
:emphasize-lines: 2, 3
|
||||||
@@ -156,7 +156,7 @@ found inside each module will be, instead, loaded in the order they are defined,
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Remember: there can be at most one handler, within a group, dealing with a specific update. Plugins with overlapping
|
Remember: there can be at most one handler, within a group, dealing with a specific update. Plugins with overlapping
|
||||||
filters included a second time will not work. Learn more at `More on Updates <more-on-updates>`_.
|
filters included a second time will not work. Learn more at :doc:`More on Updates <more-on-updates>`.
|
||||||
|
|
||||||
This default loading behaviour is usually enough, but sometimes you want to have more control on what to include (or
|
This default loading behaviour is usually enough, but sometimes you want to have more control on what to include (or
|
||||||
exclude) and in which exact order to load plugins. The way to do this is to make use of ``include`` and ``exclude``
|
exclude) and in which exact order to load plugins. The way to do this is to make use of ``include`` and ``exclude``
|
||||||
@@ -288,9 +288,8 @@ also organized in subfolders:
|
|||||||
Load/Unload Plugins at Runtime
|
Load/Unload Plugins at Runtime
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
In the `previous section <#specifying-the-plugins-to-include>`_ we've explained how to specify which plugins to load and
|
In the previous section we've explained how to specify which plugins to load and which to ignore before your Client
|
||||||
which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously
|
starts. Here we'll show, instead, how to unload and load again a previously registered plugin at runtime.
|
||||||
registered plugin at runtime.
|
|
||||||
|
|
||||||
Each function decorated with the usual ``on_message`` decorator (or any other decorator that deals with Telegram updates
|
Each function decorated with the usual ``on_message`` decorator (or any other decorator that deals with Telegram updates
|
||||||
) will be modified in such a way that, when you reference them later on, they will be actually pointing to a tuple of
|
) will be modified in such a way that, when you reference them later on, they will be actually pointing to a tuple of
|
||||||
@@ -318,7 +317,7 @@ Unloading
|
|||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the
|
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the
|
||||||
relevant module and call :meth:`remove_handler() <pyrogram.Client.remove_handler>` Client's method with your function
|
relevant module and call :meth:`~pyrogram.Client.remove_handler` Client's method with your function
|
||||||
name preceded by the star ``*`` operator as argument. Example:
|
name preceded by the star ``*`` operator as argument. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``main.py``
|
||||||
@@ -343,7 +342,7 @@ Loading
|
|||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
||||||
Similarly to the unloading process, in order to load again a previously unloaded plugin you do the same, but this time
|
Similarly to the unloading process, in order to load again a previously unloaded plugin you do the same, but this time
|
||||||
using :meth:`add_handler() <pyrogram.Client.add_handler>` instead. Example:
|
using :meth:`~pyrogram.Client.add_handler` instead. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``main.py``
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ Markdown Style
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
To use this mode, pass "markdown" in the *parse_mode* field when using
|
To use this mode, pass "markdown" in the *parse_mode* field when using
|
||||||
:obj:`send_message() <pyrogram.Client.send_message>`. Use the following syntax in your message:
|
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ To use this mode, pass "markdown" in the *parse_mode* field when using
|
|||||||
HTML Style
|
HTML Style
|
||||||
----------
|
----------
|
||||||
|
|
||||||
To use this mode, pass "html" in the *parse_mode* field when using :obj:`send_message() <pyrogram.Client.send_message>`.
|
To use this mode, pass "html" in the *parse_mode* field when using :meth:`~pyrogram.Client.send_message`.
|
||||||
The following tags are currently supported:
|
The following tags are currently supported:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
@@ -24,7 +24,7 @@ if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
|
|||||||
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
|
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
|
||||||
sys.modules["typing"] = typing
|
sys.modules["typing"] = typing
|
||||||
|
|
||||||
__version__ = "0.13.0.async"
|
__version__ = "0.13.0-asyncio"
|
||||||
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
||||||
__copyright__ = "Copyright (C) 2017-2019 Dan <https://github.com/delivrance>"
|
__copyright__ = "Copyright (C) 2017-2019 Dan <https://github.com/delivrance>"
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
from .future_salt import FutureSalt
|
from .future_salt import FutureSalt
|
||||||
from .future_salts import FutureSalts
|
from .future_salts import FutureSalts
|
||||||
from .gzip_packed import GzipPacked
|
from .gzip_packed import GzipPacked
|
||||||
|
from .list import List
|
||||||
from .message import Message
|
from .message import Message
|
||||||
from .msg_container import MsgContainer
|
from .msg_container import MsgContainer
|
||||||
from .object import Object
|
from .object import Object
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from .object import Object
|
from .object import Object
|
||||||
@@ -30,15 +29,15 @@ class FutureSalt(Object):
|
|||||||
|
|
||||||
QUALNAME = "FutureSalt"
|
QUALNAME = "FutureSalt"
|
||||||
|
|
||||||
def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int):
|
def __init__(self, valid_since: int, valid_until: int, salt: int):
|
||||||
self.valid_since = valid_since
|
self.valid_since = valid_since
|
||||||
self.valid_until = valid_until
|
self.valid_until = valid_until
|
||||||
self.salt = salt
|
self.salt = salt
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read(b: BytesIO, *args) -> "FutureSalt":
|
def read(b: BytesIO, *args) -> "FutureSalt":
|
||||||
valid_since = datetime.fromtimestamp(Int.read(b))
|
valid_since = Int.read(b)
|
||||||
valid_until = datetime.fromtimestamp(Int.read(b))
|
valid_until = Int.read(b)
|
||||||
salt = Long.read(b)
|
salt = Long.read(b)
|
||||||
|
|
||||||
return FutureSalt(valid_since, valid_until, salt)
|
return FutureSalt(valid_since, valid_until, salt)
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from . import FutureSalt
|
from . import FutureSalt
|
||||||
@@ -31,7 +30,7 @@ class FutureSalts(Object):
|
|||||||
|
|
||||||
QUALNAME = "FutureSalts"
|
QUALNAME = "FutureSalts"
|
||||||
|
|
||||||
def __init__(self, req_msg_id: int, now: int or datetime, salts: list):
|
def __init__(self, req_msg_id: int, now: int, salts: list):
|
||||||
self.req_msg_id = req_msg_id
|
self.req_msg_id = req_msg_id
|
||||||
self.now = now
|
self.now = now
|
||||||
self.salts = salts
|
self.salts = salts
|
||||||
@@ -39,7 +38,7 @@ class FutureSalts(Object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def read(b: BytesIO, *args) -> "FutureSalts":
|
def read(b: BytesIO, *args) -> "FutureSalts":
|
||||||
req_msg_id = Long.read(b)
|
req_msg_id = Long.read(b)
|
||||||
now = datetime.fromtimestamp(Int.read(b))
|
now = Int.read(b)
|
||||||
|
|
||||||
count = Int.read(b)
|
count = Int.read(b)
|
||||||
salts = [FutureSalt.read(b) for _ in range(count)]
|
salts = [FutureSalt.read(b) for _ in range(count)]
|
||||||
|
28
pyrogram/api/core/list.py
Normal file
28
pyrogram/api/core/list.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .object import Object
|
||||||
|
|
||||||
|
|
||||||
|
class List(list, Object):
|
||||||
|
__slots__ = []
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "pyrogram.api.core.List([{}])".format(
|
||||||
|
",".join(Object.__repr__(i) for i in self)
|
||||||
|
)
|
@@ -17,7 +17,6 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
|
||||||
@@ -36,32 +35,22 @@ class Object:
|
|||||||
def write(self, *args) -> bytes:
|
def write(self, *args) -> bytes:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __eq__(self, other: "Object") -> bool:
|
@staticmethod
|
||||||
for attr in self.__slots__:
|
def default(obj: "Object"):
|
||||||
try:
|
if isinstance(obj, bytes):
|
||||||
if getattr(self, attr) != getattr(other, attr):
|
return repr(obj)
|
||||||
return False
|
|
||||||
except AttributeError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return OrderedDict(
|
||||||
|
[("_", obj.QUALNAME)]
|
||||||
|
+ [
|
||||||
|
(attr, getattr(obj, attr))
|
||||||
|
for attr in obj.__slots__
|
||||||
|
if getattr(obj, attr) is not None
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
def default(obj: Object):
|
return dumps(self, indent=4, default=Object.default, ensure_ascii=False)
|
||||||
try:
|
|
||||||
return OrderedDict(
|
|
||||||
[("_", obj.QUALNAME)]
|
|
||||||
+ [(attr, getattr(obj, attr))
|
|
||||||
for attr in obj.__slots__
|
|
||||||
if getattr(obj, attr) is not None]
|
|
||||||
)
|
|
||||||
except AttributeError:
|
|
||||||
if isinstance(obj, datetime):
|
|
||||||
return obj.strftime("%d-%b-%Y %H:%M:%S")
|
|
||||||
else:
|
|
||||||
return repr(obj)
|
|
||||||
|
|
||||||
return dumps(self, indent=4, default=default, ensure_ascii=False)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "pyrogram.api.{}({})".format(
|
return "pyrogram.api.{}({})".format(
|
||||||
@@ -73,6 +62,16 @@ class Object:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __eq__(self, other: "Object") -> bool:
|
||||||
|
for attr in self.__slots__:
|
||||||
|
try:
|
||||||
|
if getattr(self, attr) != getattr(other, attr):
|
||||||
|
return False
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return len(self.write())
|
return len(self.write())
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from . import Int
|
from . import Int
|
||||||
|
from ..list import List
|
||||||
from ..object import Object
|
from ..object import Object
|
||||||
|
|
||||||
|
|
||||||
@@ -37,11 +38,11 @@ class Vector(Object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read(b: BytesIO, t: Object = None) -> list:
|
def read(b: BytesIO, t: Object = None) -> list:
|
||||||
return [
|
return List(
|
||||||
t.read(b) if t
|
t.read(b) if t
|
||||||
else Vector._read(b)
|
else Vector._read(b)
|
||||||
for _ in range(Int.read(b))
|
for _ in range(Int.read(b))
|
||||||
]
|
)
|
||||||
|
|
||||||
def __new__(cls, value: list, t: Object = None) -> bytes:
|
def __new__(cls, value: list, t: Object = None) -> bytes:
|
||||||
return b"".join(
|
return b"".join(
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
import binascii
|
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@@ -27,7 +26,6 @@ import mimetypes
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import struct
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
@@ -49,7 +47,7 @@ from pyrogram.errors import (
|
|||||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||||
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
|
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
|
||||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
VolumeLocNotFound, UserMigrate, ChannelPrivate, PhoneNumberOccupied,
|
||||||
PasswordRecoveryNa, PasswordEmpty
|
PasswordRecoveryNa, PasswordEmpty
|
||||||
)
|
)
|
||||||
from pyrogram.session import Auth, Session
|
from pyrogram.session import Auth, Session
|
||||||
@@ -320,7 +318,7 @@ class Client(Methods, BaseClient):
|
|||||||
await self.get_initial_dialogs()
|
await self.get_initial_dialogs()
|
||||||
await self.get_contacts()
|
await self.get_contacts()
|
||||||
else:
|
else:
|
||||||
await self.send(functions.messages.GetPinnedDialogs())
|
await self.send(functions.messages.GetPinnedDialogs(folder_id=0))
|
||||||
await self.get_initial_dialogs_chunk()
|
await self.get_initial_dialogs_chunk()
|
||||||
else:
|
else:
|
||||||
await self.send(functions.updates.GetState())
|
await self.send(functions.updates.GetState())
|
||||||
@@ -430,9 +428,9 @@ class Client(Methods, BaseClient):
|
|||||||
def run(self, coroutine=None):
|
def run(self, coroutine=None):
|
||||||
"""Start the Client and automatically idle the main script.
|
"""Start the Client and automatically idle the main script.
|
||||||
|
|
||||||
This is a convenience method that literally just calls :meth:`start` and :meth:`idle`. It makes running a client
|
This is a convenience method that literally just calls :meth:`~Client.start` and :meth:`~Client.idle`. It makes
|
||||||
less verbose, but is not suitable in case you want to run more than one client in a single main script,
|
running a client less verbose, but is not suitable in case you want to run more than one client in a single main
|
||||||
since :meth:`idle` will block.
|
script, since :meth:`~Client.idle` will block.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
coroutine: (``Coroutine``, *optional*):
|
coroutine: (``Coroutine``, *optional*):
|
||||||
@@ -484,7 +482,7 @@ class Client(Methods, BaseClient):
|
|||||||
"""Remove a previously-registered update handler.
|
"""Remove a previously-registered update handler.
|
||||||
|
|
||||||
Make sure to provide the right group that the handler was added in. You can use
|
Make sure to provide the right group that the handler was added in. You can use
|
||||||
the return value of the :meth:`add_handler` method, a tuple of (handler, group), and
|
the return value of the :meth:`~Client.add_handler` method, a tuple of (handler, group), and
|
||||||
pass it directly.
|
pass it directly.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@@ -777,7 +775,9 @@ class Client(Methods, BaseClient):
|
|||||||
types.Channel, types.ChannelForbidden
|
types.Channel, types.ChannelForbidden
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
):
|
) -> bool:
|
||||||
|
is_min = False
|
||||||
|
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if isinstance(entity, types.User):
|
if isinstance(entity, types.User):
|
||||||
user_id = entity.id
|
user_id = entity.id
|
||||||
@@ -785,6 +785,7 @@ class Client(Methods, BaseClient):
|
|||||||
access_hash = entity.access_hash
|
access_hash = entity.access_hash
|
||||||
|
|
||||||
if access_hash is None:
|
if access_hash is None:
|
||||||
|
is_min = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
username = entity.username
|
username = entity.username
|
||||||
@@ -820,6 +821,7 @@ class Client(Methods, BaseClient):
|
|||||||
access_hash = entity.access_hash
|
access_hash = entity.access_hash
|
||||||
|
|
||||||
if access_hash is None:
|
if access_hash is None:
|
||||||
|
is_min = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
username = getattr(entity, "username", None)
|
username = getattr(entity, "username", None)
|
||||||
@@ -834,87 +836,62 @@ class Client(Methods, BaseClient):
|
|||||||
if username is not None:
|
if username is not None:
|
||||||
self.peers_by_username[username.lower()] = input_peer
|
self.peers_by_username[username.lower()] = input_peer
|
||||||
|
|
||||||
|
return is_min
|
||||||
|
|
||||||
async def download_worker(self):
|
async def download_worker(self):
|
||||||
while True:
|
while True:
|
||||||
media = await self.download_queue.get()
|
packet = await self.download_queue.get()
|
||||||
|
|
||||||
if media is None:
|
if packet is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
temp_file_path = ""
|
temp_file_path = ""
|
||||||
final_file_path = ""
|
final_file_path = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
media, file_name, done, progress, progress_args, path = media
|
data, file_name, done, progress, progress_args, path = packet
|
||||||
|
|
||||||
file_id = media.file_id
|
|
||||||
size = media.file_size
|
|
||||||
|
|
||||||
directory, file_name = os.path.split(file_name)
|
directory, file_name = os.path.split(file_name)
|
||||||
directory = directory or "downloads"
|
directory = directory or "downloads"
|
||||||
|
|
||||||
try:
|
media_type_str = Client.MEDIA_TYPE_ID[data.media_type]
|
||||||
decoded = utils.decode(file_id)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
media_type = unpacked[0]
|
|
||||||
dc_id = unpacked[1]
|
|
||||||
id = unpacked[2]
|
|
||||||
access_hash = unpacked[3]
|
|
||||||
volume_id = None
|
|
||||||
secret = None
|
|
||||||
local_id = None
|
|
||||||
|
|
||||||
if len(decoded) > 24:
|
if not data.file_name:
|
||||||
volume_id = unpacked[4]
|
guessed_extension = self.guess_extension(data.mime_type)
|
||||||
secret = unpacked[5]
|
|
||||||
local_id = unpacked[6]
|
|
||||||
|
|
||||||
media_type_str = Client.MEDIA_TYPE_ID.get(media_type, None)
|
if data.media_type in (0, 1, 2, 14):
|
||||||
|
|
||||||
if media_type_str is None:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
file_name = file_name or getattr(media, "file_name", None)
|
|
||||||
|
|
||||||
if not file_name:
|
|
||||||
guessed_extension = self.guess_extension(media.mime_type)
|
|
||||||
|
|
||||||
if media_type in (0, 1, 2):
|
|
||||||
extension = ".jpg"
|
extension = ".jpg"
|
||||||
elif media_type == 3:
|
elif data.media_type == 3:
|
||||||
extension = guessed_extension or ".ogg"
|
extension = guessed_extension or ".ogg"
|
||||||
elif media_type in (4, 10, 13):
|
elif data.media_type in (4, 10, 13):
|
||||||
extension = guessed_extension or ".mp4"
|
extension = guessed_extension or ".mp4"
|
||||||
elif media_type == 5:
|
elif data.media_type == 5:
|
||||||
extension = guessed_extension or ".zip"
|
extension = guessed_extension or ".zip"
|
||||||
elif media_type == 8:
|
elif data.media_type == 8:
|
||||||
extension = guessed_extension or ".webp"
|
extension = guessed_extension or ".webp"
|
||||||
elif media_type == 9:
|
elif data.media_type == 9:
|
||||||
extension = guessed_extension or ".mp3"
|
extension = guessed_extension or ".mp3"
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
file_name = "{}_{}_{}{}".format(
|
file_name = "{}_{}_{}{}".format(
|
||||||
media_type_str,
|
media_type_str,
|
||||||
datetime.fromtimestamp(
|
datetime.fromtimestamp(data.date or time.time()).strftime("%Y-%m-%d_%H-%M-%S"),
|
||||||
getattr(media, "date", None) or time.time()
|
|
||||||
).strftime("%Y-%m-%d_%H-%M-%S"),
|
|
||||||
self.rnd_id(),
|
self.rnd_id(),
|
||||||
extension
|
extension
|
||||||
)
|
)
|
||||||
|
|
||||||
temp_file_path = await self.get_file(
|
temp_file_path = await self.get_file(
|
||||||
dc_id=dc_id,
|
media_type=data.media_type,
|
||||||
id=id,
|
dc_id=data.dc_id,
|
||||||
access_hash=access_hash,
|
file_id=data.file_id,
|
||||||
volume_id=volume_id,
|
access_hash=data.access_hash,
|
||||||
local_id=local_id,
|
thumb_size=data.thumb_size,
|
||||||
secret=secret,
|
peer_id=data.peer_id,
|
||||||
size=size,
|
volume_id=data.volume_id,
|
||||||
|
local_id=data.local_id,
|
||||||
|
file_size=data.file_size,
|
||||||
|
is_big=data.is_big,
|
||||||
progress=progress,
|
progress=progress,
|
||||||
progress_args=progress_args
|
progress_args=progress_args
|
||||||
)
|
)
|
||||||
@@ -949,8 +926,10 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(updates, (types.Update, types.UpdatesCombined)):
|
if isinstance(updates, (types.Update, types.UpdatesCombined)):
|
||||||
self.fetch_peers(updates.users)
|
is_min = self.fetch_peers(updates.users) or self.fetch_peers(updates.chats)
|
||||||
self.fetch_peers(updates.chats)
|
|
||||||
|
users = {u.id: u for u in updates.users}
|
||||||
|
chats = {c.id: c for c in updates.chats}
|
||||||
|
|
||||||
for update in updates.updates:
|
for update in updates.updates:
|
||||||
channel_id = getattr(
|
channel_id = getattr(
|
||||||
@@ -967,7 +946,7 @@ class Client(Methods, BaseClient):
|
|||||||
if isinstance(update, types.UpdateChannelTooLong):
|
if isinstance(update, types.UpdateChannelTooLong):
|
||||||
log.warning(update)
|
log.warning(update)
|
||||||
|
|
||||||
if isinstance(update, types.UpdateNewChannelMessage):
|
if isinstance(update, types.UpdateNewChannelMessage) and is_min:
|
||||||
message = update.message
|
message = update.message
|
||||||
|
|
||||||
if not isinstance(message, types.MessageEmpty):
|
if not isinstance(message, types.MessageEmpty):
|
||||||
@@ -989,22 +968,10 @@ class Client(Methods, BaseClient):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if not isinstance(diff, types.updates.ChannelDifferenceEmpty):
|
if not isinstance(diff, types.updates.ChannelDifferenceEmpty):
|
||||||
updates.users += diff.users
|
users.update({u.id: u for u in diff.users})
|
||||||
updates.chats += diff.chats
|
chats.update({c.id: c for c in diff.chats})
|
||||||
|
|
||||||
if channel_id and pts:
|
self.dispatcher.updates_queue.put_nowait((update, users, chats))
|
||||||
if channel_id not in self.channels_pts:
|
|
||||||
self.channels_pts[channel_id] = []
|
|
||||||
|
|
||||||
if pts in self.channels_pts[channel_id]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
self.channels_pts[channel_id].append(pts)
|
|
||||||
|
|
||||||
if len(self.channels_pts[channel_id]) > 50:
|
|
||||||
self.channels_pts[channel_id] = self.channels_pts[channel_id][25:]
|
|
||||||
|
|
||||||
self.dispatcher.updates_queue.put_nowait((update, updates.users, updates.chats))
|
|
||||||
elif isinstance(updates, (types.UpdateShortMessage, types.UpdateShortChatMessage)):
|
elif isinstance(updates, (types.UpdateShortMessage, types.UpdateShortChatMessage)):
|
||||||
diff = await self.send(
|
diff = await self.send(
|
||||||
functions.updates.GetDifference(
|
functions.updates.GetDifference(
|
||||||
@@ -1021,13 +988,13 @@ class Client(Methods, BaseClient):
|
|||||||
pts=updates.pts,
|
pts=updates.pts,
|
||||||
pts_count=updates.pts_count
|
pts_count=updates.pts_count
|
||||||
),
|
),
|
||||||
diff.users,
|
{u.id: u for u in diff.users},
|
||||||
diff.chats
|
{c.id: c for c in diff.chats}
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
self.dispatcher.updates_queue.put_nowait((diff.other_updates[0], [], []))
|
self.dispatcher.updates_queue.put_nowait((diff.other_updates[0], {}, {}))
|
||||||
elif isinstance(updates, types.UpdateShort):
|
elif isinstance(updates, types.UpdateShort):
|
||||||
self.dispatcher.updates_queue.put_nowait((updates.update, [], []))
|
self.dispatcher.updates_queue.put_nowait((updates.update, {}, {}))
|
||||||
elif isinstance(updates, types.UpdatesTooLong):
|
elif isinstance(updates, types.UpdatesTooLong):
|
||||||
log.warning(updates)
|
log.warning(updates)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -1333,7 +1300,7 @@ class Client(Methods, BaseClient):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
async def get_initial_dialogs(self):
|
async def get_initial_dialogs(self):
|
||||||
await self.send(functions.messages.GetPinnedDialogs())
|
await self.send(functions.messages.GetPinnedDialogs(folder_id=0))
|
||||||
|
|
||||||
dialogs = await self.get_initial_dialogs_chunk()
|
dialogs = await self.get_initial_dialogs_chunk()
|
||||||
offset_date = utils.get_offset_date(dialogs)
|
offset_date = utils.get_offset_date(dialogs)
|
||||||
@@ -1424,7 +1391,7 @@ class Client(Methods, BaseClient):
|
|||||||
file_part: int = 0,
|
file_part: int = 0,
|
||||||
progress: callable = None,
|
progress: callable = None,
|
||||||
progress_args: tuple = ()
|
progress_args: tuple = ()
|
||||||
):
|
):
|
||||||
"""Upload a file onto Telegram servers, without actually sending the message to anyone.
|
"""Upload a file onto Telegram servers, without actually sending the message to anyone.
|
||||||
Useful whenever an InputFile type is required.
|
Useful whenever an InputFile type is required.
|
||||||
|
|
||||||
@@ -1575,16 +1542,18 @@ class Client(Methods, BaseClient):
|
|||||||
for session in pool:
|
for session in pool:
|
||||||
await session.stop()
|
await session.stop()
|
||||||
|
|
||||||
async def get_file(self,
|
async def get_file(self, media_type: int,
|
||||||
dc_id: int,
|
dc_id: int,
|
||||||
id: int = None,
|
file_id: int,
|
||||||
access_hash: int = None,
|
access_hash: int,
|
||||||
volume_id: int = None,
|
thumb_size: str,
|
||||||
local_id: int = None,
|
peer_id: int,
|
||||||
secret: int = None,
|
volume_id: int,
|
||||||
|
local_id: int,
|
||||||
|
file_size: int,
|
||||||
|
|
||||||
size: int = None,
|
is_big: bool,
|
||||||
progress: callable = None,
|
progress: callable,
|
||||||
progress_args: tuple = ()) -> str:
|
progress_args: tuple = ()) -> str:
|
||||||
with await self.media_sessions_lock:
|
with await self.media_sessions_lock:
|
||||||
session = self.media_sessions.get(dc_id, None)
|
session = self.media_sessions.get(dc_id, None)
|
||||||
@@ -1626,18 +1595,33 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
self.media_sessions[dc_id] = session
|
self.media_sessions[dc_id] = session
|
||||||
|
|
||||||
if volume_id: # Photos are accessed by volume_id, local_id, secret
|
if media_type == 1:
|
||||||
location = types.InputFileLocation(
|
location = types.InputPeerPhotoFileLocation(
|
||||||
|
peer=self.resolve_peer(peer_id),
|
||||||
volume_id=volume_id,
|
volume_id=volume_id,
|
||||||
local_id=local_id,
|
local_id=local_id,
|
||||||
secret=secret,
|
big=is_big or None
|
||||||
file_reference=b""
|
|
||||||
)
|
)
|
||||||
else: # Any other file can be more easily accessed by id and access_hash
|
elif media_type in (0, 2):
|
||||||
location = types.InputDocumentFileLocation(
|
location = types.InputPhotoFileLocation(
|
||||||
id=id,
|
id=file_id,
|
||||||
access_hash=access_hash,
|
access_hash=access_hash,
|
||||||
file_reference=b""
|
file_reference=b"",
|
||||||
|
thumb_size=thumb_size
|
||||||
|
)
|
||||||
|
elif media_type == 14:
|
||||||
|
location = types.InputDocumentFileLocation(
|
||||||
|
id=file_id,
|
||||||
|
access_hash=access_hash,
|
||||||
|
file_reference=b"",
|
||||||
|
thumb_size=thumb_size
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
location = types.InputDocumentFileLocation(
|
||||||
|
id=file_id,
|
||||||
|
access_hash=access_hash,
|
||||||
|
file_reference=b"",
|
||||||
|
thumb_size=""
|
||||||
)
|
)
|
||||||
|
|
||||||
limit = 1024 * 1024
|
limit = 1024 * 1024
|
||||||
@@ -1668,7 +1652,14 @@ class Client(Methods, BaseClient):
|
|||||||
offset += limit
|
offset += limit
|
||||||
|
|
||||||
if progress:
|
if progress:
|
||||||
await progress(self, min(offset, size) if size != 0 else offset, size, *progress_args)
|
await progress(
|
||||||
|
self,
|
||||||
|
min(offset, file_size)
|
||||||
|
if file_size != 0
|
||||||
|
else offset,
|
||||||
|
file_size,
|
||||||
|
*progress_args
|
||||||
|
)
|
||||||
|
|
||||||
r = await session.send(
|
r = await session.send(
|
||||||
functions.upload.GetFile(
|
functions.upload.GetFile(
|
||||||
@@ -1750,7 +1741,14 @@ class Client(Methods, BaseClient):
|
|||||||
offset += limit
|
offset += limit
|
||||||
|
|
||||||
if progress:
|
if progress:
|
||||||
await progress(self, min(offset, size) if size != 0 else offset, size, *progress_args)
|
await progress(
|
||||||
|
self,
|
||||||
|
min(offset, file_size)
|
||||||
|
if file_size != 0
|
||||||
|
else offset,
|
||||||
|
file_size,
|
||||||
|
*progress_args
|
||||||
|
)
|
||||||
|
|
||||||
if len(chunk) < limit:
|
if len(chunk) < limit:
|
||||||
break
|
break
|
||||||
|
@@ -16,10 +16,11 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from pyrogram import __version__
|
from pyrogram import __version__
|
||||||
from ..style import Markdown, HTML
|
from ..style import Markdown, HTML
|
||||||
@@ -55,7 +56,7 @@ class BaseClient:
|
|||||||
CONFIG_FILE = "./config.ini"
|
CONFIG_FILE = "./config.ini"
|
||||||
|
|
||||||
MEDIA_TYPE_ID = {
|
MEDIA_TYPE_ID = {
|
||||||
0: "thumbnail",
|
0: "photo_thumbnail",
|
||||||
1: "chat_photo",
|
1: "chat_photo",
|
||||||
2: "photo",
|
2: "photo",
|
||||||
3: "voice",
|
3: "voice",
|
||||||
@@ -64,7 +65,8 @@ class BaseClient:
|
|||||||
8: "sticker",
|
8: "sticker",
|
||||||
9: "audio",
|
9: "audio",
|
||||||
10: "animation",
|
10: "animation",
|
||||||
13: "video_note"
|
13: "video_note",
|
||||||
|
14: "document_thumbnail"
|
||||||
}
|
}
|
||||||
|
|
||||||
mime_types_to_extensions = {}
|
mime_types_to_extensions = {}
|
||||||
@@ -81,6 +83,10 @@ class BaseClient:
|
|||||||
|
|
||||||
mime_types_to_extensions[mime_type] = " ".join(extensions)
|
mime_types_to_extensions[mime_type] = " ".join(extensions)
|
||||||
|
|
||||||
|
fields = ("media_type", "dc_id", "file_id", "access_hash", "thumb_size", "peer_id", "volume_id", "local_id",
|
||||||
|
"is_big", "file_size", "mime_type", "file_name", "date")
|
||||||
|
FileData = namedtuple("FileData", fields, defaults=(None,) * len(fields))
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.is_bot = None
|
self.is_bot = None
|
||||||
self.dc_id = None
|
self.dc_id = None
|
||||||
@@ -89,7 +95,6 @@ class BaseClient:
|
|||||||
self.date = None
|
self.date = None
|
||||||
|
|
||||||
self.rnd_id = MsgId
|
self.rnd_id = MsgId
|
||||||
self.channels_pts = {}
|
|
||||||
|
|
||||||
self.peers_by_id = {}
|
self.peers_by_id = {}
|
||||||
self.peers_by_username = {}
|
self.peers_by_username = {}
|
||||||
@@ -152,3 +157,6 @@ class BaseClient:
|
|||||||
|
|
||||||
def guess_extension(self, *args, **kwargs):
|
def guess_extension(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_profile_photos(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
@@ -124,16 +124,13 @@ class Dispatcher:
|
|||||||
|
|
||||||
async def update_worker(self):
|
async def update_worker(self):
|
||||||
while True:
|
while True:
|
||||||
update = await self.updates_queue.get()
|
packet = await self.updates_queue.get()
|
||||||
|
|
||||||
if update is None:
|
if packet is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
users = {i.id: i for i in update[1]}
|
update, users, chats = packet
|
||||||
chats = {i.id: i for i in update[2]}
|
|
||||||
update = update[0]
|
|
||||||
|
|
||||||
parser = self.update_parsers.get(type(update), None)
|
parser = self.update_parsers.get(type(update), None)
|
||||||
|
|
||||||
parsed_update, handler_type = (
|
parsed_update, handler_type = (
|
||||||
|
@@ -1852,4 +1852,7 @@ video/x-ms-wvx wvx
|
|||||||
video/x-msvideo avi
|
video/x-msvideo avi
|
||||||
video/x-sgi-movie movie
|
video/x-sgi-movie movie
|
||||||
video/x-smv smv
|
video/x-smv smv
|
||||||
x-conference/x-cooltalk ice
|
x-conference/x-cooltalk ice
|
||||||
|
|
||||||
|
# Telegram animated stickers
|
||||||
|
application/x-tgsticker tgs
|
@@ -92,7 +92,7 @@ class Syncer:
|
|||||||
auth_key=auth_key,
|
auth_key=auth_key,
|
||||||
user_id=client.user_id,
|
user_id=client.user_id,
|
||||||
date=int(time.time()),
|
date=int(time.time()),
|
||||||
is_bot=client.is_bot,
|
is_bot=bool(client.is_bot),
|
||||||
peers_by_id={
|
peers_by_id={
|
||||||
k: getattr(v, "access_hash", None)
|
k: getattr(v, "access_hash", None)
|
||||||
for k, v in client.peers_by_id.copy().items()
|
for k, v in client.peers_by_id.copy().items()
|
||||||
|
@@ -17,10 +17,13 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import struct
|
||||||
import sys
|
import sys
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from concurrent.futures.thread import ThreadPoolExecutor
|
from concurrent.futures.thread import ThreadPoolExecutor
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from . import BaseClient
|
||||||
from ...api import types
|
from ...api import types
|
||||||
|
|
||||||
|
|
||||||
@@ -94,3 +97,53 @@ def get_offset_date(dialogs):
|
|||||||
return m.date
|
return m.date
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def get_input_media_from_file_id(
|
||||||
|
file_id_str: str,
|
||||||
|
expected_media_type: int = None
|
||||||
|
) -> Union[types.InputMediaPhoto, types.InputMediaDocument]:
|
||||||
|
try:
|
||||||
|
decoded = decode(file_id_str)
|
||||||
|
except Exception:
|
||||||
|
raise ValueError("Failed to decode file_id: {}".format(file_id_str))
|
||||||
|
else:
|
||||||
|
media_type = decoded[0]
|
||||||
|
|
||||||
|
if expected_media_type is not None:
|
||||||
|
if media_type != expected_media_type:
|
||||||
|
media_type_str = BaseClient.MEDIA_TYPE_ID.get(media_type, None)
|
||||||
|
expected_media_type_str = BaseClient.MEDIA_TYPE_ID.get(expected_media_type, None)
|
||||||
|
|
||||||
|
raise ValueError(
|
||||||
|
'Expected: "{}", got "{}" file_id instead'.format(expected_media_type_str, media_type_str)
|
||||||
|
)
|
||||||
|
|
||||||
|
if media_type in (0, 1, 14):
|
||||||
|
raise ValueError("This file_id can only be used for download: {}".format(file_id_str))
|
||||||
|
|
||||||
|
if media_type == 2:
|
||||||
|
unpacked = struct.unpack("<iiqqc", decoded)
|
||||||
|
dc_id, file_id, access_hash, thumb_size = unpacked[1:]
|
||||||
|
|
||||||
|
return types.InputMediaPhoto(
|
||||||
|
id=types.InputPhoto(
|
||||||
|
id=file_id,
|
||||||
|
access_hash=access_hash,
|
||||||
|
file_reference=b""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if media_type in (3, 4, 5, 8, 9, 10, 13):
|
||||||
|
unpacked = struct.unpack("<iiqq", decoded)
|
||||||
|
dc_id, file_id, access_hash = unpacked[1:]
|
||||||
|
|
||||||
|
return types.InputMediaDocument(
|
||||||
|
id=types.InputDocument(
|
||||||
|
id=file_id,
|
||||||
|
access_hash=access_hash,
|
||||||
|
file_reference=b""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
raise ValueError("Unknown media type: {}".format(file_id_str))
|
||||||
|
@@ -42,7 +42,7 @@ def create(name: str, func: callable, **kwargs) -> type:
|
|||||||
|
|
||||||
**kwargs (``any``, *optional*):
|
**kwargs (``any``, *optional*):
|
||||||
Any keyword argument you would like to pass. Useful for custom filters that accept parameters (e.g.:
|
Any keyword argument you would like to pass. Useful for custom filters that accept parameters (e.g.:
|
||||||
:meth:`Filters.command`, :meth:`Filters.regex`).
|
:meth:`~Filters.command`, :meth:`~Filters.regex`).
|
||||||
"""
|
"""
|
||||||
# TODO: unpack kwargs using **kwargs into the dict itself. For Python 3.5+ only
|
# TODO: unpack kwargs using **kwargs into the dict itself. For Python 3.5+ only
|
||||||
d = {"__call__": func}
|
d = {"__call__": func}
|
||||||
@@ -56,7 +56,7 @@ class Filters:
|
|||||||
|
|
||||||
The Filters listed here are intended to be used with the :obj:`MessageHandler` only.
|
The Filters listed here are intended to be used with the :obj:`MessageHandler` only.
|
||||||
At the moment, if you want to filter updates coming from different `Handlers <Handlers.html>`_ you have to create
|
At the moment, if you want to filter updates coming from different `Handlers <Handlers.html>`_ you have to create
|
||||||
your own filters with :meth:`Filters.create` and use them in the same way.
|
your own filters with :meth:`~Filters.create` and use them in the same way.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
create = create
|
create = create
|
||||||
@@ -219,7 +219,7 @@ class Filters:
|
|||||||
The command or list of commands as string the filter should look for.
|
The command or list of commands as string the filter should look for.
|
||||||
Examples: "start", ["start", "help", "settings"]. When a message text containing
|
Examples: "start", ["start", "help", "settings"]. When a message text containing
|
||||||
a command arrives, the command itself and its arguments will be stored in the *command*
|
a command arrives, the command itself and its arguments will be stored in the *command*
|
||||||
field of the :class:`Message`.
|
field of the :obj:`Message`.
|
||||||
|
|
||||||
prefix (``str`` | ``list``, *optional*):
|
prefix (``str`` | ``list``, *optional*):
|
||||||
A prefix or a list of prefixes as string the filter should look for.
|
A prefix or a list of prefixes as string the filter should look for.
|
||||||
@@ -263,7 +263,7 @@ class Filters:
|
|||||||
pattern (``str``):
|
pattern (``str``):
|
||||||
The RegEx pattern as string, it will be applied to the text of a message. When a pattern matches,
|
The RegEx pattern as string, it will be applied to the text of a message. When a pattern matches,
|
||||||
all the `Match Objects <https://docs.python.org/3/library/re.html#match-objects>`_
|
all the `Match Objects <https://docs.python.org/3/library/re.html#match-objects>`_
|
||||||
are stored in the *matches* field of the :class:`Message` itself.
|
are stored in the *matches* field of the :obj:`Message` itself.
|
||||||
|
|
||||||
flags (``int``, *optional*):
|
flags (``int``, *optional*):
|
||||||
RegEx flags.
|
RegEx flags.
|
||||||
@@ -339,4 +339,15 @@ class Filters:
|
|||||||
and message.from_user.is_self
|
and message.from_user.is_self
|
||||||
and not message.outgoing)))
|
and not message.outgoing)))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def callback_data(data: str or bytes):
|
||||||
|
"""Filter callback queries for their data.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
data (``str`` | ``bytes``):
|
||||||
|
Pass the data you want to filter for.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return create("CallbackData", lambda flt, cb: cb.data == flt.data, data=data)
|
||||||
|
|
||||||
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
||||||
|
@@ -21,10 +21,10 @@ from .handler import Handler
|
|||||||
|
|
||||||
class CallbackQueryHandler(Handler):
|
class CallbackQueryHandler(Handler):
|
||||||
"""The CallbackQuery handler class. Used to handle callback queries coming from inline buttons.
|
"""The CallbackQuery handler class. Used to handle callback queries coming from inline buttons.
|
||||||
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
It is intended to be used with :meth:`~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_callback_query() <pyrogram.Client.on_callback_query>` decorator.
|
:meth:`~Client.on_callback_query` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
|
@@ -22,10 +22,10 @@ from .handler import Handler
|
|||||||
class DeletedMessagesHandler(Handler):
|
class DeletedMessagesHandler(Handler):
|
||||||
"""The deleted Messages handler class. Used to handle deleted messages coming from any chat
|
"""The deleted Messages handler class. Used to handle deleted messages coming from any chat
|
||||||
(private, group, channel). It is intended to be used with
|
(private, group, channel). It is intended to be used with
|
||||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
:meth:`~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_deleted_messages() <pyrogram.Client.on_deleted_messages>` decorator.
|
:meth:`~Client.on_deleted_messages` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
|
@@ -21,10 +21,10 @@ from .handler import Handler
|
|||||||
|
|
||||||
class DisconnectHandler(Handler):
|
class DisconnectHandler(Handler):
|
||||||
"""The Disconnect handler class. Used to handle disconnections. It is intended to be used with
|
"""The Disconnect handler class. Used to handle disconnections. It is intended to be used with
|
||||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
:meth:~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_disconnect() <pyrogram.Client.on_disconnect>` decorator.
|
:meth:`~Client.on_disconnect` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
|
@@ -21,10 +21,10 @@ from .handler import Handler
|
|||||||
|
|
||||||
class InlineQueryHandler(Handler):
|
class InlineQueryHandler(Handler):
|
||||||
"""The InlineQuery handler class. Used to handle inline queries.
|
"""The InlineQuery handler class. Used to handle inline queries.
|
||||||
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
It is intended to be used with :meth:`~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_inline_query() <pyrogram.Client.on_inline_query>` decorator.
|
:meth:`~Client.on_inline_query` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
|
@@ -21,11 +21,10 @@ from .handler import Handler
|
|||||||
|
|
||||||
class MessageHandler(Handler):
|
class MessageHandler(Handler):
|
||||||
"""The Message handler class. Used to handle text, media and service messages coming from
|
"""The Message handler class. Used to handle text, media and service messages coming from
|
||||||
any chat (private, group, channel). It is intended to be used with
|
any chat (private, group, channel). It is intended to be used with :meth:`~Client.add_handler`
|
||||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_message() <pyrogram.Client.on_message>` decorator.
|
:meth:`~Client.on_message` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
|
@@ -22,25 +22,25 @@ from .handler import Handler
|
|||||||
class PollHandler(Handler):
|
class PollHandler(Handler):
|
||||||
"""The Poll handler class. Used to handle polls updates.
|
"""The Poll handler class. Used to handle polls updates.
|
||||||
|
|
||||||
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
It is intended to be used with :meth:`~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_poll() <pyrogram.Client.on_poll>` decorator.
|
:meth:`~Client.on_poll` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
Pass a function that will be called when a new poll update arrives. It takes *(client, poll)*
|
Pass a function that will be called when a new poll update arrives. It takes *(client, poll)*
|
||||||
as positional arguments (look at the section below for a detailed description).
|
as positional arguments (look at the section below for a detailed description).
|
||||||
|
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters`):
|
||||||
Pass one or more filters to allow only a subset of polls to be passed
|
Pass one or more filters to allow only a subset of polls to be passed
|
||||||
in your callback function.
|
in your callback function.
|
||||||
|
|
||||||
Other parameters:
|
Other parameters:
|
||||||
client (:obj:`Client <pyrogram.Client>`):
|
client (:obj:`Client`):
|
||||||
The Client itself, useful when you want to call other API methods inside the poll handler.
|
The Client itself, useful when you want to call other API methods inside the poll handler.
|
||||||
|
|
||||||
poll (:obj:`Poll <pyrogram.Poll>`):
|
poll (:obj:`Poll`):
|
||||||
The received poll.
|
The received poll.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@@ -21,10 +21,10 @@ from .handler import Handler
|
|||||||
|
|
||||||
class RawUpdateHandler(Handler):
|
class RawUpdateHandler(Handler):
|
||||||
"""The Raw Update handler class. Used to handle raw updates. It is intended to be used with
|
"""The Raw Update handler class. Used to handle raw updates. It is intended to be used with
|
||||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
:meth:`~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_raw_update() <pyrogram.Client.on_raw_update>` decorator.
|
:meth:`~Client.on_raw_update` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
@@ -33,7 +33,7 @@ class RawUpdateHandler(Handler):
|
|||||||
a detailed description).
|
a detailed description).
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:class:`Client`):
|
client (:obj:`Client`):
|
||||||
The Client itself, useful when you want to call other API methods inside the update handler.
|
The Client itself, useful when you want to call other API methods inside the update handler.
|
||||||
|
|
||||||
update (``Update``):
|
update (``Update``):
|
||||||
|
@@ -21,10 +21,10 @@ from .handler import Handler
|
|||||||
|
|
||||||
class UserStatusHandler(Handler):
|
class UserStatusHandler(Handler):
|
||||||
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
|
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
|
||||||
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
It is intended to be used with :meth:`~Client.add_handler`
|
||||||
|
|
||||||
For a nicer way to register this handler, have a look at the
|
For a nicer way to register this handler, have a look at the
|
||||||
:meth:`on_user_status() <pyrogram.Client.on_user_status>` decorator.
|
:meth:`~Client.on_user_status` decorator.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
callback (``callable``):
|
callback (``callable``):
|
||||||
|
@@ -35,8 +35,8 @@ class ExportChatInviteLink(BaseClient):
|
|||||||
|
|
||||||
Each administrator in a chat generates their own invite links. Bots can't use invite links generated by
|
Each administrator in a chat generates their own invite links. Bots can't use invite links generated by
|
||||||
other administrators. If you want your bot to work with invite links, it will need to generate its own link
|
other administrators. If you want your bot to work with invite links, it will need to generate its own link
|
||||||
using this method – after this the link will become available to the bot via the :meth:`get_chat` method.
|
using this method – after this the link will become available to the bot via the :meth:`~Client.get_chat`
|
||||||
If your bot needs to generate a new invite link replacing its previous one, use this method again.
|
method. If your bot needs to generate a new invite link replacing its previous one, use this method again.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
|
@@ -51,7 +51,7 @@ class GetChatMembers(BaseClient):
|
|||||||
You can get up to 200 chat members at once.
|
You can get up to 200 chat members at once.
|
||||||
A chat can be either a basic group, a supergroup or a channel.
|
A chat can be either a basic group, a supergroup or a channel.
|
||||||
You must be admin to retrieve the members list of a channel (also known as "subscribers").
|
You must be admin to retrieve the members list of a channel (also known as "subscribers").
|
||||||
For a more convenient way of getting chat members see :meth:`iter_chat_members`.
|
For a more convenient way of getting chat members see :meth:`~Client.iter_chat_members`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
|
@@ -37,7 +37,7 @@ class GetDialogs(BaseClient):
|
|||||||
"""Get a chunk of the user's dialogs.
|
"""Get a chunk of the user's dialogs.
|
||||||
|
|
||||||
You can get up to 100 dialogs at once.
|
You can get up to 100 dialogs at once.
|
||||||
For a more convenient way of getting a user's dialogs see :meth:`iter_dialogs`.
|
For a more convenient way of getting a user's dialogs see :meth:`~Client.iter_dialogs`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
offset_date (``int``):
|
offset_date (``int``):
|
||||||
@@ -62,7 +62,7 @@ class GetDialogs(BaseClient):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
if pinned_only:
|
if pinned_only:
|
||||||
r = await self.send(functions.messages.GetPinnedDialogs())
|
r = await self.send(functions.messages.GetPinnedDialogs(folder_id=0))
|
||||||
else:
|
else:
|
||||||
r = await self.send(
|
r = await self.send(
|
||||||
functions.messages.GetDialogs(
|
functions.messages.GetDialogs(
|
||||||
|
@@ -36,7 +36,7 @@ class GetDialogsCount(BaseClient):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if pinned_only:
|
if pinned_only:
|
||||||
return len((await self.send(functions.messages.GetPinnedDialogs())).dialogs)
|
return len((await self.send(functions.messages.GetPinnedDialogs(folder_id=0))).dialogs)
|
||||||
else:
|
else:
|
||||||
r = await self.send(
|
r = await self.send(
|
||||||
functions.messages.GetDialogs(
|
functions.messages.GetDialogs(
|
||||||
|
@@ -50,7 +50,7 @@ class IterChatMembers(BaseClient):
|
|||||||
) -> Optional[AsyncGenerator["pyrogram.ChatMember", None]]:
|
) -> Optional[AsyncGenerator["pyrogram.ChatMember", None]]:
|
||||||
"""Iterate through the members of a chat sequentially.
|
"""Iterate through the members of a chat sequentially.
|
||||||
|
|
||||||
This convenience method does the same as repeatedly calling :meth:`get_chat_members` in a loop, thus saving you
|
This convenience method does the same as repeatedly calling :meth:`~Client.get_chat_members` in a loop, thus saving you
|
||||||
from the hassle of setting up boilerplate code. It is useful for getting the whole members list of a chat with
|
from the hassle of setting up boilerplate code. It is useful for getting the whole members list of a chat with
|
||||||
a single call.
|
a single call.
|
||||||
|
|
||||||
|
@@ -29,12 +29,13 @@ class IterDialogs(BaseClient):
|
|||||||
async def iter_dialogs(
|
async def iter_dialogs(
|
||||||
self,
|
self,
|
||||||
limit: int = 0,
|
limit: int = 0,
|
||||||
offset_date: int = 0
|
offset_date: int = None
|
||||||
) -> Optional[AsyncGenerator["pyrogram.Dialog", None]]:
|
) -> Optional[AsyncGenerator["pyrogram.Dialog", None]]:
|
||||||
"""Iterate through a user's dialogs sequentially.
|
"""Iterate through a user's dialogs sequentially.
|
||||||
|
|
||||||
This convenience method does the same as repeatedly calling :meth:`get_dialogs` in a loop, thus saving you from
|
This convenience method does the same as repeatedly calling :meth:`~Client.get_dialogs` in a loop, thus saving
|
||||||
the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a single call.
|
you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a
|
||||||
|
single call.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
limit (``str``, *optional*):
|
limit (``str``, *optional*):
|
||||||
|
@@ -44,14 +44,14 @@ class SetChatPhoto(BaseClient):
|
|||||||
Unique identifier (int) or username (str) of the target chat.
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
|
||||||
photo (``str``):
|
photo (``str``):
|
||||||
New chat photo. You can pass a :class:`Photo` id or a file path to upload a new photo.
|
New chat photo. You can pass a :obj:`Photo` id or a file path to upload a new photo.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
ValueError: if a chat_id belongs to user.
|
||||||
"""
|
"""
|
||||||
peer = await self.resolve_peer(chat_id)
|
peer = await self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ class UpdateChatUsername(BaseClient):
|
|||||||
) -> bool:
|
) -> bool:
|
||||||
"""Update a channel or a supergroup username.
|
"""Update a channel or a supergroup username.
|
||||||
|
|
||||||
To update your own username (for users only, not bots) you can use :meth:`update_username`.
|
To update your own username (for users only, not bots) you can use :meth:`~Client.update_username`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``)
|
chat_id (``int`` | ``str``)
|
||||||
|
@@ -32,7 +32,7 @@ class OnCallbackQuery(BaseClient):
|
|||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling callback queries.
|
"""Decorator for handling callback queries.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`CallbackQueryHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`CallbackQueryHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
filters (:obj:`Filters`):
|
filters (:obj:`Filters`):
|
||||||
|
@@ -32,7 +32,7 @@ class OnDeletedMessages(BaseClient):
|
|||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling deleted messages.
|
"""Decorator for handling deleted messages.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`DeletedMessagesHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`DeletedMessagesHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
filters (:obj:`Filters`):
|
filters (:obj:`Filters`):
|
||||||
|
@@ -25,7 +25,7 @@ class OnDisconnect(BaseClient):
|
|||||||
def on_disconnect(self=None) -> callable:
|
def on_disconnect(self=None) -> callable:
|
||||||
"""Decorator for handling disconnections.
|
"""Decorator for handling disconnections.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`DisconnectHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`DisconnectHandler`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func: callable) -> Handler:
|
def decorator(func: callable) -> Handler:
|
||||||
|
@@ -32,7 +32,7 @@ class OnInlineQuery(BaseClient):
|
|||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling inline queries.
|
"""Decorator for handling inline queries.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`InlineQueryHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`InlineQueryHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
@@ -32,7 +32,7 @@ class OnMessage(BaseClient):
|
|||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling messages.
|
"""Decorator for handling messages.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`MessageHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`MessageHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
filters (:obj:`Filters`):
|
filters (:obj:`Filters`):
|
||||||
|
@@ -32,10 +32,10 @@ class OnPoll(BaseClient):
|
|||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling poll updates.
|
"""Decorator for handling poll updates.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`PollHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`PollHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters`):
|
||||||
Pass one or more filters to allow only a subset of polls to be passed
|
Pass one or more filters to allow only a subset of polls to be passed
|
||||||
in your function.
|
in your function.
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ class OnRawUpdate(BaseClient):
|
|||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling raw updates.
|
"""Decorator for handling raw updates.
|
||||||
|
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`RawUpdateHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`RawUpdateHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
group (``int``, *optional*):
|
group (``int``, *optional*):
|
||||||
|
@@ -31,7 +31,7 @@ class OnUserStatus(BaseClient):
|
|||||||
group: int = 0
|
group: int = 0
|
||||||
) -> callable:
|
) -> callable:
|
||||||
"""Decorator for handling user status updates.
|
"""Decorator for handling user status updates.
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`UserStatusHandler`.
|
This does the same thing as :meth:`~Client.add_handler` using the :obj:`UserStatusHandler`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
filters (:obj:`Filters`):
|
filters (:obj:`Filters`):
|
||||||
|
@@ -28,6 +28,7 @@ from .get_history_count import GetHistoryCount
|
|||||||
from .get_messages import GetMessages
|
from .get_messages import GetMessages
|
||||||
from .iter_history import IterHistory
|
from .iter_history import IterHistory
|
||||||
from .retract_vote import RetractVote
|
from .retract_vote import RetractVote
|
||||||
|
from .send_animated_sticker import SendAnimatedSticker
|
||||||
from .send_animation import SendAnimation
|
from .send_animation import SendAnimation
|
||||||
from .send_audio import SendAudio
|
from .send_audio import SendAudio
|
||||||
from .send_cached_media import SendCachedMedia
|
from .send_cached_media import SendCachedMedia
|
||||||
@@ -78,6 +79,7 @@ class Messages(
|
|||||||
DownloadMedia,
|
DownloadMedia,
|
||||||
IterHistory,
|
IterHistory,
|
||||||
SendCachedMedia,
|
SendCachedMedia,
|
||||||
GetHistoryCount
|
GetHistoryCount,
|
||||||
|
SendAnimatedSticker
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@@ -17,10 +17,13 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import binascii
|
||||||
|
import struct
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.client.ext import BaseClient
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FileIdInvalid
|
||||||
|
|
||||||
|
|
||||||
class DownloadMedia(BaseClient):
|
class DownloadMedia(BaseClient):
|
||||||
@@ -74,74 +77,98 @@ class DownloadMedia(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``str`` | ``None``: On success, the absolute path of the downloaded file is returned, otherwise, in case
|
``str`` | ``None``: On success, the absolute path of the downloaded file is returned, otherwise, in case
|
||||||
the download failed or was deliberately stopped with :meth:`stop_transmission`, None is returned.
|
the download failed or was deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
``ValueError`` if the message doesn't contain any downloadable media
|
``ValueError`` if the message doesn't contain any downloadable media
|
||||||
"""
|
"""
|
||||||
error_message = "This message doesn't contain any downloadable media"
|
error_message = "This message doesn't contain any downloadable media"
|
||||||
|
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note")
|
||||||
|
|
||||||
|
file_size = None
|
||||||
|
mime_type = None
|
||||||
|
date = None
|
||||||
|
|
||||||
if isinstance(message, pyrogram.Message):
|
if isinstance(message, pyrogram.Message):
|
||||||
if message.photo:
|
for kind in available_media:
|
||||||
media = pyrogram.Document(
|
media = getattr(message, kind, None)
|
||||||
file_id=message.photo.sizes[-1].file_id,
|
|
||||||
file_size=message.photo.sizes[-1].file_size,
|
if media is not None:
|
||||||
mime_type="",
|
break
|
||||||
date=message.photo.date,
|
|
||||||
client=self
|
|
||||||
)
|
|
||||||
elif message.audio:
|
|
||||||
media = message.audio
|
|
||||||
elif message.document:
|
|
||||||
media = message.document
|
|
||||||
elif message.video:
|
|
||||||
media = message.video
|
|
||||||
elif message.voice:
|
|
||||||
media = message.voice
|
|
||||||
elif message.video_note:
|
|
||||||
media = message.video_note
|
|
||||||
elif message.sticker:
|
|
||||||
media = message.sticker
|
|
||||||
elif message.animation:
|
|
||||||
media = message.animation
|
|
||||||
else:
|
else:
|
||||||
raise ValueError(error_message)
|
raise ValueError(error_message)
|
||||||
elif isinstance(message, (
|
else:
|
||||||
pyrogram.Photo,
|
media = message
|
||||||
pyrogram.PhotoSize,
|
|
||||||
pyrogram.Audio,
|
if isinstance(media, str):
|
||||||
pyrogram.Document,
|
file_id_str = media
|
||||||
pyrogram.Video,
|
else:
|
||||||
pyrogram.Voice,
|
file_id_str = media.file_id
|
||||||
pyrogram.VideoNote,
|
file_name = getattr(media, "file_name", "")
|
||||||
pyrogram.Sticker,
|
file_size = getattr(media, "file_size", None)
|
||||||
pyrogram.Animation
|
mime_type = getattr(media, "mime_type", None)
|
||||||
)):
|
date = getattr(media, "date", None)
|
||||||
if isinstance(message, pyrogram.Photo):
|
|
||||||
media = pyrogram.Document(
|
data = self.FileData(
|
||||||
file_id=message.sizes[-1].file_id,
|
file_name=file_name,
|
||||||
file_size=message.sizes[-1].file_size,
|
file_size=file_size,
|
||||||
mime_type="",
|
mime_type=mime_type,
|
||||||
date=message.date,
|
date=date
|
||||||
client=self
|
)
|
||||||
|
|
||||||
|
def get_existing_attributes() -> dict:
|
||||||
|
return dict(filter(lambda x: x[1] is not None, data._asdict().items()))
|
||||||
|
|
||||||
|
try:
|
||||||
|
decoded = utils.decode(file_id_str)
|
||||||
|
media_type = decoded[0]
|
||||||
|
|
||||||
|
if media_type == 1:
|
||||||
|
unpacked = struct.unpack("<iiqqib", decoded)
|
||||||
|
dc_id, peer_id, volume_id, local_id, is_big = unpacked[1:]
|
||||||
|
|
||||||
|
data = self.FileData(
|
||||||
|
**get_existing_attributes(),
|
||||||
|
media_type=media_type,
|
||||||
|
dc_id=dc_id,
|
||||||
|
peer_id=peer_id,
|
||||||
|
volume_id=volume_id,
|
||||||
|
local_id=local_id,
|
||||||
|
is_big=bool(is_big)
|
||||||
|
)
|
||||||
|
elif media_type in (0, 2, 14):
|
||||||
|
unpacked = struct.unpack("<iiqqc", decoded)
|
||||||
|
dc_id, file_id, access_hash, thumb_size = unpacked[1:]
|
||||||
|
|
||||||
|
data = self.FileData(
|
||||||
|
**get_existing_attributes(),
|
||||||
|
media_type=media_type,
|
||||||
|
dc_id=dc_id,
|
||||||
|
file_id=file_id,
|
||||||
|
access_hash=access_hash,
|
||||||
|
thumb_size=thumb_size.decode()
|
||||||
|
)
|
||||||
|
elif media_type in (3, 4, 5, 8, 9, 10, 13):
|
||||||
|
unpacked = struct.unpack("<iiqq", decoded)
|
||||||
|
dc_id, file_id, access_hash = unpacked[1:]
|
||||||
|
|
||||||
|
data = self.FileData(
|
||||||
|
**get_existing_attributes(),
|
||||||
|
media_type=media_type,
|
||||||
|
dc_id=dc_id,
|
||||||
|
file_id=file_id,
|
||||||
|
access_hash=access_hash
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
media = message
|
raise ValueError("Unknown media type: {}".format(file_id_str))
|
||||||
elif isinstance(message, str):
|
except (AssertionError, binascii.Error, struct.error):
|
||||||
media = pyrogram.Document(
|
raise FileIdInvalid from None
|
||||||
file_id=message,
|
|
||||||
file_size=0,
|
|
||||||
mime_type="",
|
|
||||||
client=self
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise ValueError(error_message)
|
|
||||||
|
|
||||||
done = asyncio.Event()
|
done = asyncio.Event()
|
||||||
path = [None]
|
path = [None]
|
||||||
|
|
||||||
self.download_queue.put_nowait((media, file_name, done, progress, progress_args, path))
|
self.download_queue.put_nowait((data, file_name, done, progress, progress_args, path))
|
||||||
|
|
||||||
if block:
|
if block:
|
||||||
await done.wait()
|
await done.wait()
|
||||||
|
@@ -16,14 +16,11 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
from pyrogram.client.types import (
|
from pyrogram.client.types import (
|
||||||
InputMediaPhoto, InputMediaVideo, InputMediaAudio,
|
InputMediaPhoto, InputMediaVideo, InputMediaAudio,
|
||||||
@@ -94,28 +91,7 @@ class EditMessageMedia(BaseClient):
|
|||||||
url=media.media
|
url=media.media
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(media.media, 2)
|
||||||
decoded = utils.decode(media.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 2:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaPhoto(
|
|
||||||
id=types.InputPhoto(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(media, InputMediaVideo):
|
if isinstance(media, InputMediaVideo):
|
||||||
if os.path.exists(media.media):
|
if os.path.exists(media.media):
|
||||||
@@ -153,28 +129,7 @@ class EditMessageMedia(BaseClient):
|
|||||||
url=media.media
|
url=media.media
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(media.media, 4)
|
||||||
decoded = utils.decode(media.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 4:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(media, InputMediaAudio):
|
if isinstance(media, InputMediaAudio):
|
||||||
if os.path.exists(media.media):
|
if os.path.exists(media.media):
|
||||||
@@ -211,28 +166,7 @@ class EditMessageMedia(BaseClient):
|
|||||||
url=media.media
|
url=media.media
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(media.media, 9)
|
||||||
decoded = utils.decode(media.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 9:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(media, InputMediaAnimation):
|
if isinstance(media, InputMediaAnimation):
|
||||||
if os.path.exists(media.media):
|
if os.path.exists(media.media):
|
||||||
@@ -271,28 +205,7 @@ class EditMessageMedia(BaseClient):
|
|||||||
url=media.media
|
url=media.media
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(media.media, 10)
|
||||||
decoded = utils.decode(media.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 10:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(media, InputMediaDocument):
|
if isinstance(media, InputMediaDocument):
|
||||||
if os.path.exists(media.media):
|
if os.path.exists(media.media):
|
||||||
@@ -324,28 +237,7 @@ class EditMessageMedia(BaseClient):
|
|||||||
url=media.media
|
url=media.media
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(media.media, 5)
|
||||||
decoded = utils.decode(media.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] not in (5, 10):
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
r = await self.send(
|
r = await self.send(
|
||||||
functions.messages.EditMessage(
|
functions.messages.EditMessage(
|
||||||
|
@@ -41,7 +41,7 @@ class GetHistory(BaseClient):
|
|||||||
"""Retrieve a chunk of the history of a chat.
|
"""Retrieve a chunk of the history of a chat.
|
||||||
|
|
||||||
You can get up to 100 messages at once.
|
You can get up to 100 messages at once.
|
||||||
For a more convenient way of getting a chat history see :meth:`iter_history`.
|
For a more convenient way of getting a chat history see :meth:`~Client.iter_history`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
|
@@ -37,8 +37,9 @@ class IterHistory(BaseClient):
|
|||||||
) -> Optional[AsyncGenerator["pyrogram.Message", None]]:
|
) -> Optional[AsyncGenerator["pyrogram.Message", None]]:
|
||||||
"""Iterate through a chat history sequentially.
|
"""Iterate through a chat history sequentially.
|
||||||
|
|
||||||
This convenience method does the same as repeatedly calling :meth:`get_history` in a loop, thus saving you from
|
This convenience method does the same as repeatedly calling :meth:`~Client.get_history` in a loop, thus saving
|
||||||
the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a single call.
|
you from the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a
|
||||||
|
single call.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
|
141
pyrogram/client/methods/messages/send_animated_sticker.py
Normal file
141
pyrogram/client/methods/messages/send_animated_sticker.py
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
|
class SendAnimatedSticker(BaseClient):
|
||||||
|
def send_animated_sticker(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
animated_sticker: str,
|
||||||
|
disable_notification: bool = None,
|
||||||
|
reply_to_message_id: int = None,
|
||||||
|
reply_markup: Union[
|
||||||
|
"pyrogram.InlineKeyboardMarkup",
|
||||||
|
"pyrogram.ReplyKeyboardMarkup",
|
||||||
|
"pyrogram.ReplyKeyboardRemove",
|
||||||
|
"pyrogram.ForceReply"
|
||||||
|
] = None,
|
||||||
|
progress: callable = None,
|
||||||
|
progress_args: tuple = ()
|
||||||
|
) -> Union["pyrogram.Message", None]:
|
||||||
|
"""Send .tgs animated stickers.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||||
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
|
|
||||||
|
animated_sticker (``str``):
|
||||||
|
Animated sticker to send.
|
||||||
|
Pass a file_id as string to send a animated sticker that exists on the Telegram servers,
|
||||||
|
pass an HTTP URL as a string for Telegram to get a .webp animated sticker file from the Internet, or
|
||||||
|
pass a file path as string to upload a new animated sticker that exists on your local machine.
|
||||||
|
|
||||||
|
disable_notification (``bool``, *optional*):
|
||||||
|
Sends the message silently.
|
||||||
|
Users will receive a notification with no sound.
|
||||||
|
|
||||||
|
reply_to_message_id (``int``, *optional*):
|
||||||
|
If the message is a reply, ID of the original message.
|
||||||
|
|
||||||
|
reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
|
||||||
|
Additional interface options. An object for an inline keyboard, custom reply keyboard,
|
||||||
|
instructions to remove reply keyboard or to force a reply from the user.
|
||||||
|
|
||||||
|
progress (``callable``, *optional*):
|
||||||
|
Pass a callback function to view the upload progress.
|
||||||
|
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
||||||
|
below for a detailed description).
|
||||||
|
|
||||||
|
progress_args (``tuple``, *optional*):
|
||||||
|
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
||||||
|
a chat_id and a message_id in order to edit a message with the updated progress.
|
||||||
|
|
||||||
|
Other Parameters:
|
||||||
|
client (:obj:`Client`):
|
||||||
|
The Client itself, useful when you want to call other API methods inside the callback function.
|
||||||
|
|
||||||
|
current (``int``):
|
||||||
|
The amount of bytes uploaded so far.
|
||||||
|
|
||||||
|
total (``int``):
|
||||||
|
The size of the file.
|
||||||
|
|
||||||
|
*args (``tuple``, *optional*):
|
||||||
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
|
You can either keep *\*args* or add every single extra argument in your function signature.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Message` | ``None``: On success, the sent animated sticker message is returned, otherwise, in case the
|
||||||
|
upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
Raises:
|
||||||
|
RPCError: In case of a Telegram RPC error.
|
||||||
|
"""
|
||||||
|
file = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.path.exists(animated_sticker):
|
||||||
|
file = self.save_file(animated_sticker, progress=progress, progress_args=progress_args)
|
||||||
|
media = types.InputMediaUploadedDocument(
|
||||||
|
mime_type=self.guess_mime_type(animated_sticker) or "application/x-tgsticker",
|
||||||
|
file=file,
|
||||||
|
attributes=[
|
||||||
|
types.DocumentAttributeFilename(file_name=os.path.basename(animated_sticker))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
elif animated_sticker.startswith("http"):
|
||||||
|
media = types.InputMediaDocumentExternal(
|
||||||
|
url=animated_sticker
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
media = utils.get_input_media_from_file_id(animated_sticker, 5)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
r = self.send(
|
||||||
|
functions.messages.SendMedia(
|
||||||
|
peer=self.resolve_peer(chat_id),
|
||||||
|
media=media,
|
||||||
|
silent=disable_notification or None,
|
||||||
|
reply_to_msg_id=reply_to_message_id,
|
||||||
|
random_id=self.rnd_id(),
|
||||||
|
reply_markup=reply_markup.write() if reply_markup else None,
|
||||||
|
message=""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except FilePartMissing as e:
|
||||||
|
self.save_file(animated_sticker, file_id=file.id, file_part=e.x)
|
||||||
|
else:
|
||||||
|
for i in r.updates:
|
||||||
|
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
|
||||||
|
return pyrogram.Message._parse(
|
||||||
|
self, i.message,
|
||||||
|
{i.id: i for i in r.users},
|
||||||
|
{i.id: i for i in r.chats}
|
||||||
|
)
|
||||||
|
except BaseClient.StopTransmission:
|
||||||
|
return None
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendAnimation(BaseClient):
|
class SendAnimation(BaseClient):
|
||||||
@@ -121,7 +119,7 @@ class SendAnimation(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -153,28 +151,7 @@ class SendAnimation(BaseClient):
|
|||||||
url=animation
|
url=animation
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(animation, 10)
|
||||||
decoded = utils.decode(animation)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 10:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendAudio(BaseClient):
|
class SendAudio(BaseClient):
|
||||||
@@ -122,7 +120,7 @@ class SendAudio(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent audio message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent audio message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -152,28 +150,7 @@ class SendAudio(BaseClient):
|
|||||||
url=audio
|
url=audio
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(audio, 9)
|
||||||
decoded = utils.decode(audio)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 9:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,13 +16,10 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
|
||||||
|
|
||||||
@@ -84,39 +81,10 @@ class SendCachedMedia(BaseClient):
|
|||||||
"""
|
"""
|
||||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||||
|
|
||||||
try:
|
|
||||||
decoded = utils.decode(file_id)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if not media_type:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
if media_type == "photo":
|
|
||||||
media = types.InputMediaPhoto(
|
|
||||||
id=types.InputPhoto(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
r = await self.send(
|
r = await self.send(
|
||||||
functions.messages.SendMedia(
|
functions.messages.SendMedia(
|
||||||
peer=await self.resolve_peer(chat_id),
|
peer=await self.resolve_peer(chat_id),
|
||||||
media=media,
|
media=utils.get_input_media_from_file_id(file_id),
|
||||||
silent=disable_notification or None,
|
silent=disable_notification or None,
|
||||||
reply_to_msg_id=reply_to_message_id,
|
reply_to_msg_id=reply_to_message_id,
|
||||||
random_id=self.rnd_id(),
|
random_id=self.rnd_id(),
|
||||||
|
@@ -16,11 +16,11 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import json
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.client.ext import BaseClient
|
from pyrogram.client.ext import BaseClient
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
class ChatAction:
|
class ChatAction:
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendDocument(BaseClient):
|
class SendDocument(BaseClient):
|
||||||
@@ -108,7 +106,7 @@ class SendDocument(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent document message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent document message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -133,28 +131,7 @@ class SendDocument(BaseClient):
|
|||||||
url=document
|
url=document
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(document, 5)
|
||||||
decoded = utils.decode(document)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] not in (5, 10):
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,17 +16,15 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union, List
|
from typing import Union, List
|
||||||
import asyncio
|
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FloodWait
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FloodWait
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -96,28 +94,7 @@ class SendMediaGroup(BaseClient):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(i.media, 2)
|
||||||
decoded = utils.decode(i.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 2:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaPhoto(
|
|
||||||
id=types.InputPhoto(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif isinstance(i, pyrogram.InputMediaVideo):
|
elif isinstance(i, pyrogram.InputMediaVideo):
|
||||||
if os.path.exists(i.media):
|
if os.path.exists(i.media):
|
||||||
while True:
|
while True:
|
||||||
@@ -155,28 +132,7 @@ class SendMediaGroup(BaseClient):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(i.media, 4)
|
||||||
decoded = utils.decode(i.media)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 4:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
multi_media.append(
|
multi_media.append(
|
||||||
types.InputSingleMedia(
|
types.InputSingleMedia(
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendPhoto(BaseClient):
|
class SendPhoto(BaseClient):
|
||||||
@@ -108,7 +106,7 @@ class SendPhoto(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent photo message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent photo message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -129,29 +127,7 @@ class SendPhoto(BaseClient):
|
|||||||
ttl_seconds=ttl_seconds
|
ttl_seconds=ttl_seconds
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(photo, 2)
|
||||||
decoded = utils.decode(photo)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 2:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaPhoto(
|
|
||||||
id=types.InputPhoto(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
),
|
|
||||||
ttl_seconds=ttl_seconds
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendSticker(BaseClient):
|
class SendSticker(BaseClient):
|
||||||
@@ -93,7 +91,7 @@ class SendSticker(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent sticker message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent sticker message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
@@ -114,28 +112,7 @@ class SendSticker(BaseClient):
|
|||||||
url=sticker
|
url=sticker
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(sticker, 8)
|
||||||
decoded = utils.decode(sticker)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 8:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendVideo(BaseClient):
|
class SendVideo(BaseClient):
|
||||||
@@ -125,7 +123,7 @@ class SendVideo(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent video message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent video message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -156,28 +154,7 @@ class SendVideo(BaseClient):
|
|||||||
url=video
|
url=video
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(video, 4)
|
||||||
decoded = utils.decode(video)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 4:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendVideoNote(BaseClient):
|
class SendVideoNote(BaseClient):
|
||||||
@@ -108,7 +106,7 @@ class SendVideoNote(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent video note message is returned, otherwise, in case the
|
:obj:`Message` | ``None``: On success, the sent video note message is returned, otherwise, in case the
|
||||||
pload is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
pload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -133,28 +131,7 @@ class SendVideoNote(BaseClient):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(video_note, 13)
|
||||||
decoded = utils.decode(video_note)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 13:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,15 +16,13 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import binascii
|
|
||||||
import os
|
import os
|
||||||
import struct
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
from pyrogram.client.ext import BaseClient, utils
|
||||||
|
from pyrogram.errors import FilePartMissing
|
||||||
|
|
||||||
|
|
||||||
class SendVoice(BaseClient):
|
class SendVoice(BaseClient):
|
||||||
@@ -106,7 +104,7 @@ class SendVoice(BaseClient):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Message` | ``None``: On success, the sent voice message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent voice message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
@@ -132,28 +130,7 @@ class SendVoice(BaseClient):
|
|||||||
url=voice
|
url=voice
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
media = utils.get_input_media_from_file_id(voice, 3)
|
||||||
decoded = utils.decode(voice)
|
|
||||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
|
||||||
unpacked = struct.unpack(fmt, decoded)
|
|
||||||
except (AssertionError, binascii.Error, struct.error):
|
|
||||||
raise FileIdInvalid from None
|
|
||||||
else:
|
|
||||||
if unpacked[0] != 3:
|
|
||||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
|
||||||
|
|
||||||
if media_type:
|
|
||||||
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
|
|
||||||
else:
|
|
||||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
|
||||||
|
|
||||||
media = types.InputMediaDocument(
|
|
||||||
id=types.InputDocument(
|
|
||||||
id=unpacked[2],
|
|
||||||
access_hash=unpacked[3],
|
|
||||||
file_reference=b""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@@ -16,22 +16,26 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .delete_user_profile_photos import DeleteUserProfilePhotos
|
from .delete_profile_photos import DeleteProfilePhotos
|
||||||
from .get_me import GetMe
|
from .get_me import GetMe
|
||||||
from .get_user_profile_photos import GetUserProfilePhotos
|
from .get_profile_photos import GetProfilePhotos
|
||||||
from .get_user_profile_photos_count import GetUserProfilePhotosCount
|
from .get_profile_photos_count import GetProfilePhotosCount
|
||||||
|
from .get_user_dc import GetUserDC
|
||||||
from .get_users import GetUsers
|
from .get_users import GetUsers
|
||||||
from .set_user_profile_photo import SetUserProfilePhoto
|
from .iter_profile_photos import IterProfilePhotos
|
||||||
|
from .set_profile_photo import SetProfilePhoto
|
||||||
from .update_username import UpdateUsername
|
from .update_username import UpdateUsername
|
||||||
|
|
||||||
|
|
||||||
class Users(
|
class Users(
|
||||||
GetUserProfilePhotos,
|
GetProfilePhotos,
|
||||||
SetUserProfilePhoto,
|
SetProfilePhoto,
|
||||||
DeleteUserProfilePhotos,
|
DeleteProfilePhotos,
|
||||||
GetUsers,
|
GetUsers,
|
||||||
GetMe,
|
GetMe,
|
||||||
UpdateUsername,
|
UpdateUsername,
|
||||||
GetUserProfilePhotosCount
|
GetProfilePhotosCount,
|
||||||
|
GetUserDC,
|
||||||
|
IterProfilePhotos
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@@ -24,8 +24,8 @@ from pyrogram.api import functions, types
|
|||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class DeleteUserProfilePhotos(BaseClient):
|
class DeleteProfilePhotos(BaseClient):
|
||||||
async def delete_user_profile_photos(
|
async def delete_profile_photos(
|
||||||
self,
|
self,
|
||||||
id: Union[str, List[str]]
|
id: Union[str, List[str]]
|
||||||
) -> bool:
|
) -> bool:
|
92
pyrogram/client/methods/users/get_profile_photos.py
Normal file
92
pyrogram/client/methods/users/get_profile_photos.py
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class GetProfilePhotos(BaseClient):
|
||||||
|
async def get_profile_photos(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
offset: int = 0,
|
||||||
|
limit: int = 100
|
||||||
|
) -> "pyrogram.Photos":
|
||||||
|
"""Get a list of profile pictures for a user or a chat.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||||
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
|
|
||||||
|
offset (``int``, *optional*):
|
||||||
|
Sequential number of the first photo to be returned.
|
||||||
|
By default, all photos are returned.
|
||||||
|
|
||||||
|
limit (``int``, *optional*):
|
||||||
|
Limits the number of photos to be retrieved.
|
||||||
|
Values between 1—100 are accepted. Defaults to 100.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Photos`: On success, an object containing a list of the profile photos is returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RPCError: In case of a Telegram RPC error.
|
||||||
|
"""
|
||||||
|
peer_id = await self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
if isinstance(peer_id, types.InputPeerUser):
|
||||||
|
return pyrogram.Photos._parse(
|
||||||
|
self,
|
||||||
|
await self.send(
|
||||||
|
functions.photos.GetUserPhotos(
|
||||||
|
user_id=peer_id,
|
||||||
|
offset=offset,
|
||||||
|
max_id=0,
|
||||||
|
limit=limit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
new_chat_photos = pyrogram.Messages._parse(
|
||||||
|
self,
|
||||||
|
await self.send(
|
||||||
|
functions.messages.Search(
|
||||||
|
peer=peer_id,
|
||||||
|
q="",
|
||||||
|
filter=types.InputMessagesFilterChatPhotos(),
|
||||||
|
min_date=0,
|
||||||
|
max_date=0,
|
||||||
|
offset_id=0,
|
||||||
|
add_offset=offset,
|
||||||
|
limit=limit,
|
||||||
|
max_id=0,
|
||||||
|
min_id=0,
|
||||||
|
hash=0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Photos(
|
||||||
|
total_count=new_chat_photos.total_count,
|
||||||
|
photos=[m.new_chat_photo for m in new_chat_photos.messages][:limit]
|
||||||
|
)
|
@@ -18,16 +18,15 @@
|
|||||||
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class GetUserProfilePhotosCount(BaseClient):
|
class GetProfilePhotosCount(BaseClient):
|
||||||
async def get_user_profile_photos_count(self, user_id: Union[int, str]) -> int:
|
async def get_profile_photos_count(self, chat_id: Union[int, str]) -> int:
|
||||||
"""Get the total count of profile pictures for a user.
|
"""Get the total count of profile pictures for a user.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
user_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
Unique identifier (int) or username (str) of the target chat.
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
@@ -39,16 +38,4 @@ class GetUserProfilePhotosCount(BaseClient):
|
|||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
r = await self.send(
|
return await self.get_profile_photos(chat_id, limit=1).total_count
|
||||||
functions.photos.GetUserPhotos(
|
|
||||||
user_id=await self.resolve_peer(user_id),
|
|
||||||
offset=0,
|
|
||||||
max_id=0,
|
|
||||||
limit=1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(r, types.photos.Photos):
|
|
||||||
return len(r.photos)
|
|
||||||
else:
|
|
||||||
return r.count
|
|
@@ -18,19 +18,13 @@
|
|||||||
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.api import functions
|
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class GetUserProfilePhotos(BaseClient):
|
class GetUserDC(BaseClient):
|
||||||
async def get_user_profile_photos(
|
async def get_user_dc(self, user_id: Union[int, str]) -> Union[int, None]:
|
||||||
self,
|
"""Get the assigned data center (DC) of a user.
|
||||||
user_id: Union[int, str],
|
|
||||||
offset: int = 0,
|
|
||||||
limit: int = 100
|
|
||||||
) -> "pyrogram.UserProfilePhotos":
|
|
||||||
"""Get a list of profile pictures for a user.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
user_id (``int`` | ``str``):
|
user_id (``int`` | ``str``):
|
||||||
@@ -38,28 +32,20 @@ class GetUserProfilePhotos(BaseClient):
|
|||||||
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
|
|
||||||
offset (``int``, *optional*):
|
|
||||||
Sequential number of the first photo to be returned.
|
|
||||||
By default, all photos are returned.
|
|
||||||
|
|
||||||
limit (``int``, *optional*):
|
|
||||||
Limits the number of photos to be retrieved.
|
|
||||||
Values between 1—100 are accepted. Defaults to 100.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`UserProfilePhotos`: On success, an object containing a list of the profile photos is returned.
|
``int`` | ``None``: The DC identifier as integer, or None in case it wasn't possible to get it.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
RPCError: In case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
return pyrogram.UserProfilePhotos._parse(
|
|
||||||
self,
|
r = await self.send(functions.users.GetUsers(id=[await self.resolve_peer(user_id)]))
|
||||||
await self.send(
|
|
||||||
functions.photos.GetUserPhotos(
|
if r:
|
||||||
user_id=await self.resolve_peer(user_id),
|
r = r[0]
|
||||||
offset=offset,
|
|
||||||
max_id=0,
|
if r.photo:
|
||||||
limit=limit
|
if isinstance(r.photo, types.UserProfilePhoto):
|
||||||
)
|
return r.photo.dc_id
|
||||||
)
|
|
||||||
)
|
return None
|
82
pyrogram/client/methods/users/iter_profile_photos.py
Normal file
82
pyrogram/client/methods/users/iter_profile_photos.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from typing import Union, Generator
|
||||||
|
|
||||||
|
from async_generator import async_generator, yield_
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class IterProfilePhotos(BaseClient):
|
||||||
|
@async_generator
|
||||||
|
async def iter_profile_photos(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
offset: int = 0,
|
||||||
|
limit: int = 0,
|
||||||
|
) -> Generator["pyrogram.Photo", None, None]:
|
||||||
|
"""Iterate through a chat or a user profile photos sequentially.
|
||||||
|
|
||||||
|
This convenience method does the same as repeatedly calling :meth:`~Client.get_profile_photos` in a loop, thus
|
||||||
|
saving you from the hassle of setting up boilerplate code. It is useful for getting all the profile photos with
|
||||||
|
a single call.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
||||||
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
|
|
||||||
|
limit (``int``, *optional*):
|
||||||
|
Limits the number of profile photos to be retrieved.
|
||||||
|
By default, no limit is applied and all profile photos are returned.
|
||||||
|
|
||||||
|
offset (``int``, *optional*):
|
||||||
|
Sequential number of the first profile photo to be returned.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``Generator``: A generator yielding :obj:`Photo` objects.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RPCError: In case of a Telegram RPC error.
|
||||||
|
"""
|
||||||
|
current = 0
|
||||||
|
total = limit or (1 << 31)
|
||||||
|
limit = min(100, total)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
photos = self.get_profile_photos(
|
||||||
|
chat_id=chat_id,
|
||||||
|
offset=offset,
|
||||||
|
limit=limit
|
||||||
|
).photos
|
||||||
|
|
||||||
|
if not photos:
|
||||||
|
return
|
||||||
|
|
||||||
|
offset += len(photos)
|
||||||
|
|
||||||
|
for photo in photos:
|
||||||
|
await yield_(photo)
|
||||||
|
|
||||||
|
current += 1
|
||||||
|
|
||||||
|
if current >= total:
|
||||||
|
return
|
@@ -20,8 +20,8 @@ from pyrogram.api import functions
|
|||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class SetUserProfilePhoto(BaseClient):
|
class SetProfilePhoto(BaseClient):
|
||||||
async def set_user_profile_photo(
|
async def set_profile_photo(
|
||||||
self,
|
self,
|
||||||
photo: str
|
photo: str
|
||||||
) -> bool:
|
) -> bool:
|
@@ -31,7 +31,7 @@ class UpdateUsername(BaseClient):
|
|||||||
|
|
||||||
This method only works for users, not bots. Bot usernames must be changed via Bot Support or by recreating
|
This method only works for users, not bots. Bot usernames must be changed via Bot Support or by recreating
|
||||||
them from scratch using BotFather. To update a channel or supergroup username you can use
|
them from scratch using BotFather. To update a channel or supergroup username you can use
|
||||||
:meth:`update_chat_username`.
|
:meth:`~Client.update_chat_username`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
username (``str`` | ``None``):
|
username (``str`` | ``None``):
|
||||||
|
@@ -92,7 +92,7 @@ class InlineQuery(PyrogramType, Update):
|
|||||||
switch_pm_text: str = "",
|
switch_pm_text: str = "",
|
||||||
switch_pm_parameter: str = ""
|
switch_pm_parameter: str = ""
|
||||||
):
|
):
|
||||||
"""Bound method *answer* of :obj:`InlineQuery <pyrogram.InlineQuery>`.
|
"""Bound method *answer* of :obj:`InlineQuery`.
|
||||||
|
|
||||||
Use this method as a shortcut for:
|
Use this method as a shortcut for:
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ class InlineQuery(PyrogramType, Update):
|
|||||||
inline_query.answer([...])
|
inline_query.answer([...])
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
results (List of :obj:`InlineQueryResult <pyrogram.InlineQueryResult>`):
|
results (List of :obj:`InlineQueryResult`):
|
||||||
A list of results for the inline query.
|
A list of results for the inline query.
|
||||||
|
|
||||||
cache_time (``int``, *optional*):
|
cache_time (``int``, *optional*):
|
||||||
|
@@ -34,10 +34,10 @@ class InlineQueryResultArticle(InlineQueryResult):
|
|||||||
title (``str``):
|
title (``str``):
|
||||||
Title for the result.
|
Title for the result.
|
||||||
|
|
||||||
input_message_content (:obj:`InputMessageContent <pyrogram.InputMessageContent>`):
|
input_message_content (:obj:`InputMessageContent`):
|
||||||
Content of the message to be sent.
|
Content of the message to be sent.
|
||||||
|
|
||||||
reply_markup (:obj:`InlineKeyboardMarkup <pyrogram.InlineKeyboardMarkup>`, *optional*):
|
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
|
||||||
Inline keyboard attached to the message.
|
Inline keyboard attached to the message.
|
||||||
|
|
||||||
url (``str``, *optional*):
|
url (``str``, *optional*):
|
||||||
|
@@ -50,10 +50,10 @@ class InlineQueryResultAudio(PyrogramType):
|
|||||||
audio_duration (``int`` ``32-bit``, optional):
|
audio_duration (``int`` ``32-bit``, optional):
|
||||||
Audio duration in seconds.
|
Audio duration in seconds.
|
||||||
|
|
||||||
reply_markup (:obj:`InlineKeyboardMarkup <pyrogram.types.InlineKeyboardMarkup>`, optional):
|
reply_markup (:obj:`InlineKeyboardMarkup`, optional):
|
||||||
Inline keyboard attached to the message.
|
Inline keyboard attached to the message.
|
||||||
|
|
||||||
input_message_content (:obj:`InputMessageContent <pyrogram.types.InputMessageContent>`, optional):
|
input_message_content (:obj:`InputMessageContent`, optional):
|
||||||
Content of the message to be sent instead of the audio.
|
Content of the message to be sent instead of the audio.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@@ -47,10 +47,10 @@ class InlineQueryResultCachedDocument(PyrogramType):
|
|||||||
parse_mode (``str``, optional):
|
parse_mode (``str``, optional):
|
||||||
Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
|
Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
|
||||||
|
|
||||||
reply_markup (:obj:`InlineKeyboardMarkup <pyrogram.types.InlineKeyboardMarkup>`, optional):
|
reply_markup (:obj:`InlineKeyboardMarkup`, optional):
|
||||||
Inline keyboard attached to the message.
|
Inline keyboard attached to the message.
|
||||||
|
|
||||||
input_message_content (:obj:`InputMessageContent <pyrogram.types.InputMessageContent>`, optional):
|
input_message_content (:obj:`InputMessageContent`, optional):
|
||||||
Content of the message to be sent instead of the file.
|
Content of the message to be sent instead of the file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user