Merge develop -> asyncio
This commit is contained in:
commit
d4dbff3226
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 = "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":
|
||||
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;
|
||||
inputPeerUser#7b8e7de6 user_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;
|
||||
inputUserSelf#f7c1b13f = 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;
|
||||
|
||||
@ -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;
|
||||
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;
|
||||
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;
|
||||
peerChat#bad0e5bb chat_id:int = Peer;
|
||||
@ -79,14 +85,11 @@ storage.fileMov#4b09ebbc = storage.FileType;
|
||||
storage.fileMp4#b3cea0e4 = 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;
|
||||
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;
|
||||
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;
|
||||
userStatusOnline#edb93949 expires:int = UserStatus;
|
||||
@ -98,11 +101,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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#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;
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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 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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
messageActionCustomAction#fae69f56 message:string = MessageAction;
|
||||
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
||||
@ -155,10 +158,11 @@ messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:
|
||||
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = 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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
@ -221,7 +225,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
|
||||
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
||||
|
||||
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.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;
|
||||
updatePrivacy#ee3b272a key:PrivacyKey rules:Vector<PrivacyRule> = 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;
|
||||
updateWebPage#7f891213 webpage:WebPage 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;
|
||||
updateChannel#b6d45656 channel_id: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;
|
||||
updateChannelMessageViews#98a12b4b channel_id:int id:int views: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;
|
||||
updatePtsChanged#3354678f = Update;
|
||||
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
|
||||
updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update;
|
||||
updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector<DialogPeer> = Update;
|
||||
updateDialogPinned#6e6fe51c flags:# pinned:flags.0?true folder_id:flags.1?int peer:DialogPeer = Update;
|
||||
updatePinnedDialogs#fa0f3ca2 flags:# folder_id:flags.1?int order:flags.0?Vector<DialogPeer> = Update;
|
||||
updateBotWebhookJSON#8317c0c3 data:DataJSON = 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;
|
||||
@ -318,6 +322,7 @@ updateUserPinnedMessage#4c43da18 user_id:int id: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;
|
||||
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;
|
||||
|
||||
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
@ -413,6 +418,7 @@ inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
|
||||
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
||||
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
|
||||
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
|
||||
inputPrivacyKeyPhoneNumber#352dafa = InputPrivacyKey;
|
||||
|
||||
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
||||
@ -420,6 +426,7 @@ privacyKeyPhoneCall#3d662b7b = PrivacyKey;
|
||||
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
||||
privacyKeyForwards#69ec56a3 = PrivacyKey;
|
||||
privacyKeyProfilePhoto#96151fed = PrivacyKey;
|
||||
privacyKeyPhoneNumber#d19ae46d = PrivacyKey;
|
||||
|
||||
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||
@ -427,6 +434,8 @@ inputPrivacyValueAllowUsers#131cc67f users:Vector<InputUser> = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
|
||||
inputPrivacyValueAllowChatParticipants#4c81c1ba chats:Vector<int> = InputPrivacyRule;
|
||||
inputPrivacyValueDisallowChatParticipants#d82363af chats:Vector<int> = InputPrivacyRule;
|
||||
|
||||
privacyValueAllowContacts#fffe1bac = PrivacyRule;
|
||||
privacyValueAllowAll#65427b82 = PrivacyRule;
|
||||
@ -434,8 +443,10 @@ privacyValueAllowUsers#4d5bbe0c users:Vector<int> = PrivacyRule;
|
||||
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
|
||||
privacyValueDisallowAll#8b73e763 = 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;
|
||||
|
||||
@ -459,7 +470,6 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess
|
||||
|
||||
contactLinkUnknown#5f4f9247 = ContactLink;
|
||||
contactLinkNone#feedd3ad = ContactLink;
|
||||
contactLinkHasPhone#268f3f59 = ContactLink;
|
||||
contactLinkContact#d502c2d0 = ContactLink;
|
||||
|
||||
webPageEmpty#eb1477e8 id:long = WebPage;
|
||||
@ -485,13 +495,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
|
||||
chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
|
||||
|
||||
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;
|
||||
inputStickerSetID#9de7a269 id:long access_hash:long = 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;
|
||||
|
||||
@ -507,6 +517,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
|
||||
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
|
||||
keyboardButtonGame#50f41ccf 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;
|
||||
|
||||
@ -533,13 +545,14 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
|
||||
|
||||
inputChannelEmpty#ee8c1e86 = 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;
|
||||
|
||||
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.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;
|
||||
|
||||
channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
|
||||
@ -628,6 +641,8 @@ topPeerCategoryCorrespondents#637b7ed = TopPeerCategory;
|
||||
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
|
||||
topPeerCategoryChannels#161d9628 = TopPeerCategory;
|
||||
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
|
||||
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
|
||||
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
phoneCallRequested#83761ce4 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;
|
||||
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;
|
||||
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?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#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#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#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 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;
|
||||
|
||||
@ -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;
|
||||
channelAdminLogEventActionChangeAbout#55188a2e 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;
|
||||
channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction;
|
||||
@ -812,6 +827,7 @@ channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputSticker
|
||||
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
|
||||
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = 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;
|
||||
|
||||
@ -843,8 +859,10 @@ inputMessageReplyTo#bad88395 id:int = InputMessage;
|
||||
inputMessagePinned#86872538 = InputMessage;
|
||||
|
||||
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
|
||||
inputDialogPeerFolder#64600527 folder_id:int = InputDialogPeer;
|
||||
|
||||
dialogPeer#e56dbf05 peer:Peer = DialogPeer;
|
||||
dialogPeerFolder#514519e2 folder_id:int = DialogPeer;
|
||||
|
||||
messages.foundStickerSetsNotModified#d54b65d = 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;
|
||||
|
||||
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---
|
||||
|
||||
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.search#11f812d8 q:string limit:int = contacts.Found;
|
||||
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.resetSaved#879537f1 = Bool;
|
||||
contacts.getSaved#82f1e39f = Vector<SavedContact>;
|
||||
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
|
||||
|
||||
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.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;
|
||||
@ -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.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
||||
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.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
|
||||
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.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
||||
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
|
||||
messages.getPinnedDialogs#e254d64e = messages.PeerDialogs;
|
||||
messages.reorderPinnedDialogs#3b1adf37 flags:# force:flags.0?true folder_id:int order:Vector<InputDialogPeer> = Bool;
|
||||
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.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
|
||||
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.getEmojiKeywords#35a0e062 lang_code:string = 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.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.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.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
|
||||
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.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;
|
||||
|
||||
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.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||
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.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.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
|
||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
||||
// LAYER 100
|
@ -18,6 +18,7 @@
|
||||
|
||||
import ast
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
||||
HOME = "compiler/docs"
|
||||
@ -29,8 +30,10 @@ TYPES_PATH = "pyrogram/api/types"
|
||||
FUNCTIONS_BASE = "functions"
|
||||
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):
|
||||
@ -50,9 +53,11 @@ def generate(source_path, base):
|
||||
for node in ast.walk(p):
|
||||
if isinstance(node, ast.ClassDef):
|
||||
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) + "/" + name + ".rst"
|
||||
full_path = os.path.basename(path) + "/" + snek(name).replace("_", "-") + ".rst"
|
||||
|
||||
if level:
|
||||
full_path = base + "/" + full_path
|
||||
@ -65,7 +70,7 @@ def generate(source_path, base):
|
||||
title=name,
|
||||
title_markup="=" * len(name),
|
||||
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 = []
|
||||
|
||||
for i in v:
|
||||
entities.append(i)
|
||||
entities.append(snek(i).replace("_", "-"))
|
||||
|
||||
if k != base:
|
||||
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:
|
||||
if k == base:
|
||||
f.write(":tocdepth: 1\n\n")
|
||||
k = "Raw " + k
|
||||
|
||||
f.write(
|
||||
toctree.format(
|
||||
@ -115,6 +121,8 @@ def start():
|
||||
global page_template
|
||||
global toctree
|
||||
|
||||
shutil.rmtree(DESTINATION, ignore_errors=True)
|
||||
|
||||
with open(HOME + "/template/page.txt", encoding="utf-8") as f:
|
||||
page_template = f.read()
|
||||
|
||||
|
@ -99,3 +99,4 @@ RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
|
||||
ACCESS_TOKEN_INVALID The bot access token is invalid
|
||||
INVITE_HASH_EXPIRED The chat invite link is no longer valid
|
||||
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_INVALID The key is invalid
|
||||
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_EXPIRED The authorization has expired
|
||||
ACTIVE_USER_REQUIRED The method is only available to already activated users
|
||||
|
|
@ -23,11 +23,11 @@ canonical = "https://docs.pyrogram.org/"
|
||||
|
||||
dirs = {
|
||||
".": ("weekly", 1.0),
|
||||
"intro": ("weekly", 0.8),
|
||||
"start": ("weekly", 0.8),
|
||||
"api": ("weekly", 0.6),
|
||||
"topics": ("weekly", 0.6),
|
||||
"telegram": ("weekly", 0.4)
|
||||
"intro": ("weekly", 0.9),
|
||||
"start": ("weekly", 0.9),
|
||||
"api": ("weekly", 0.8),
|
||||
"topics": ("weekly", 0.8),
|
||||
"telegram": ("weekly", 0.6)
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,43 +22,65 @@ some of the required arguments.
|
||||
|
||||
.. currentmodule:: pyrogram
|
||||
|
||||
- Message_
|
||||
- CallbackQuery_
|
||||
- InlineQuery_
|
||||
|
||||
.. _Message:
|
||||
Index
|
||||
-----
|
||||
|
||||
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()`
|
||||
- :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()`
|
||||
|
||||
.. Message
|
||||
.. automethod:: Message.click()
|
||||
.. automethod:: Message.delete()
|
||||
.. automethod:: Message.download()
|
||||
@ -87,16 +109,8 @@ Message
|
||||
.. automethod:: Message.reply_video_note()
|
||||
.. automethod:: Message.reply_voice()
|
||||
|
||||
.. _CallbackQuery:
|
||||
|
||||
CallbackQuery
|
||||
-------------
|
||||
|
||||
.. CallbackQuery
|
||||
.. automethod:: CallbackQuery.answer()
|
||||
|
||||
.. _InlineQuery:
|
||||
|
||||
InlineQuery
|
||||
-----------
|
||||
|
||||
.. InlineQuery
|
||||
.. automethod:: InlineQuery.answer()
|
@ -1,13 +1,13 @@
|
||||
Decorators
|
||||
==========
|
||||
|
||||
While still being methods bound to the :obj:`Client <pyrogram.Client>` class, decorators are of a special kind and thus deserve a
|
||||
dedicated page.
|
||||
While still being methods bound to the :class:`~pyrogram.Client` class, decorators are of a special kind and thus
|
||||
deserve a dedicated page.
|
||||
|
||||
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
|
||||
:meth:`add_handler() <pyrogram.Client.add_handler>`, automatically. All you need to do is adding the decorators on top
|
||||
of your functions.
|
||||
:doc:`Handlers <handlers>`; they do so by instantiating the correct handler and calling
|
||||
:meth:`~pyrogram.Client.add_handler`, automatically. All you need to do is adding the decorators on top of your
|
||||
functions.
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 6
|
||||
@ -24,25 +24,34 @@ of your functions.
|
||||
|
||||
app.run()
|
||||
|
||||
.. currentmodule:: pyrogram.Client
|
||||
.. currentmodule:: pyrogram
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
Index
|
||||
-----
|
||||
|
||||
on_message
|
||||
on_callback_query
|
||||
on_inline_query
|
||||
on_deleted_messages
|
||||
on_user_status
|
||||
on_poll
|
||||
on_disconnect
|
||||
on_raw_update
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
.. automethod:: pyrogram.Client.on_message()
|
||||
.. automethod:: pyrogram.Client.on_callback_query()
|
||||
.. automethod:: pyrogram.Client.on_inline_query()
|
||||
.. automethod:: pyrogram.Client.on_deleted_messages()
|
||||
.. automethod:: pyrogram.Client.on_user_status()
|
||||
.. automethod:: pyrogram.Client.on_poll()
|
||||
.. automethod:: pyrogram.Client.on_disconnect()
|
||||
.. automethod:: pyrogram.Client.on_raw_update()
|
||||
- :meth:`~Client.on_message`
|
||||
- :meth:`~Client.on_callback_query`
|
||||
- :meth:`~Client.on_inline_query`
|
||||
- :meth:`~Client.on_deleted_messages`
|
||||
- :meth:`~Client.on_user_status`
|
||||
- :meth:`~Client.on_poll`
|
||||
- :meth:`~Client.on_disconnect`
|
||||
- :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.
|
||||
|
||||
For a much more convenient way of registering callback functions have a look at `Decorators <Decorators.html>`_ instead.
|
||||
In case you decided to manually create a handler, use :meth:`add_handler() <pyrogram.Client.add_handler>` to register
|
||||
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 :class:`~pyrogram.Client.add_handler` to register
|
||||
it.
|
||||
|
||||
.. code-block:: python
|
||||
@ -25,18 +25,27 @@ it.
|
||||
|
||||
.. currentmodule:: pyrogram
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
Index
|
||||
-----
|
||||
|
||||
MessageHandler
|
||||
DeletedMessagesHandler
|
||||
CallbackQueryHandler
|
||||
InlineQueryHandler
|
||||
UserStatusHandler
|
||||
PollHandler
|
||||
DisconnectHandler
|
||||
RawUpdateHandler
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
- :class:`MessageHandler`
|
||||
- :class:`DeletedMessagesHandler`
|
||||
- :class:`CallbackQueryHandler`
|
||||
- :class:`InlineQueryHandler`
|
||||
- :class:`UserStatusHandler`
|
||||
- :class:`PollHandler`
|
||||
- :class:`DisconnectHandler`
|
||||
- :class:`RawUpdateHandler`
|
||||
|
||||
-----
|
||||
|
||||
Details
|
||||
-------
|
||||
|
||||
.. Handlers
|
||||
.. autoclass:: MessageHandler()
|
||||
.. autoclass:: DeletedMessagesHandler()
|
||||
.. autoclass:: CallbackQueryHandler()
|
||||
|
@ -1,7 +1,7 @@
|
||||
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
|
||||
:emphasize-lines: 6
|
||||
@ -13,253 +13,253 @@ All Pyrogram methods listed here are bound to a :obj:`Client <pyrogram.Client>`
|
||||
with app:
|
||||
app.send_message("haskell", "hi")
|
||||
|
||||
.. currentmodule:: pyrogram.Client
|
||||
.. currentmodule:: pyrogram
|
||||
|
||||
Index
|
||||
-----
|
||||
|
||||
Utilities
|
||||
---------
|
||||
^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 4
|
||||
|
||||
start
|
||||
stop
|
||||
restart
|
||||
idle
|
||||
run
|
||||
add_handler
|
||||
remove_handler
|
||||
send
|
||||
resolve_peer
|
||||
save_file
|
||||
stop_transmission
|
||||
- :meth:`~Client.start`
|
||||
- :meth:`~Client.stop`
|
||||
- :meth:`~Client.restart`
|
||||
- :meth:`~Client.idle`
|
||||
- :meth:`~Client.run`
|
||||
- :meth:`~Client.add_handler`
|
||||
- :meth:`~Client.remove_handler`
|
||||
- :meth:`~Client.send`
|
||||
- :meth:`~Client.resolve_peer`
|
||||
- :meth:`~Client.save_file`
|
||||
- :meth:`~Client.stop_transmission`
|
||||
|
||||
Messages
|
||||
--------
|
||||
^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
send_message
|
||||
forward_messages
|
||||
send_photo
|
||||
send_audio
|
||||
send_document
|
||||
send_sticker
|
||||
send_video
|
||||
send_animation
|
||||
send_voice
|
||||
send_video_note
|
||||
send_media_group
|
||||
send_location
|
||||
send_venue
|
||||
send_contact
|
||||
send_cached_media
|
||||
send_chat_action
|
||||
edit_message_text
|
||||
edit_message_caption
|
||||
edit_message_reply_markup
|
||||
edit_message_media
|
||||
delete_messages
|
||||
get_messages
|
||||
get_history
|
||||
get_history_count
|
||||
iter_history
|
||||
send_poll
|
||||
vote_poll
|
||||
stop_poll
|
||||
retract_vote
|
||||
download_media
|
||||
- :meth:`~Client.send_message`
|
||||
- :meth:`~Client.forward_messages`
|
||||
- :meth:`~Client.send_photo`
|
||||
- :meth:`~Client.send_audio`
|
||||
- :meth:`~Client.send_document`
|
||||
- :meth:`~Client.send_sticker`
|
||||
- :meth:`~Client.send_animated_sticker`
|
||||
- :meth:`~Client.send_video`
|
||||
- :meth:`~Client.send_animation`
|
||||
- :meth:`~Client.send_voice`
|
||||
- :meth:`~Client.send_video_note`
|
||||
- :meth:`~Client.send_media_group`
|
||||
- :meth:`~Client.send_location`
|
||||
- :meth:`~Client.send_venue`
|
||||
- :meth:`~Client.send_contact`
|
||||
- :meth:`~Client.send_cached_media`
|
||||
- :meth:`~Client.send_chat_action`
|
||||
- :meth:`~Client.edit_message_text`
|
||||
- :meth:`~Client.edit_message_caption`
|
||||
- :meth:`~Client.edit_message_reply_markup`
|
||||
- :meth:`~Client.edit_message_media`
|
||||
- :meth:`~Client.delete_messages`
|
||||
- :meth:`~Client.get_messages`
|
||||
- :meth:`~Client.get_history`
|
||||
- :meth:`~Client.get_history_count`
|
||||
- :meth:`~Client.iter_history`
|
||||
- :meth:`~Client.send_poll`
|
||||
- :meth:`~Client.vote_poll`
|
||||
- :meth:`~Client.stop_poll`
|
||||
- :meth:`~Client.retract_vote`
|
||||
- :meth:`~Client.download_media`
|
||||
|
||||
Chats
|
||||
-----
|
||||
^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
join_chat
|
||||
leave_chat
|
||||
kick_chat_member
|
||||
unban_chat_member
|
||||
restrict_chat_member
|
||||
promote_chat_member
|
||||
export_chat_invite_link
|
||||
set_chat_photo
|
||||
delete_chat_photo
|
||||
set_chat_title
|
||||
set_chat_description
|
||||
pin_chat_message
|
||||
unpin_chat_message
|
||||
get_chat
|
||||
get_chat_member
|
||||
get_chat_members
|
||||
get_chat_members_count
|
||||
iter_chat_members
|
||||
get_dialogs
|
||||
iter_dialogs
|
||||
get_dialogs_count
|
||||
restrict_chat
|
||||
update_chat_username
|
||||
- :meth:`~Client.join_chat`
|
||||
- :meth:`~Client.leave_chat`
|
||||
- :meth:`~Client.kick_chat_member`
|
||||
- :meth:`~Client.unban_chat_member`
|
||||
- :meth:`~Client.restrict_chat_member`
|
||||
- :meth:`~Client.promote_chat_member`
|
||||
- :meth:`~Client.export_chat_invite_link`
|
||||
- :meth:`~Client.set_chat_photo`
|
||||
- :meth:`~Client.delete_chat_photo`
|
||||
- :meth:`~Client.set_chat_title`
|
||||
- :meth:`~Client.set_chat_description`
|
||||
- :meth:`~Client.pin_chat_message`
|
||||
- :meth:`~Client.unpin_chat_message`
|
||||
- :meth:`~Client.get_chat`
|
||||
- :meth:`~Client.get_chat_member`
|
||||
- :meth:`~Client.get_chat_members`
|
||||
- :meth:`~Client.get_chat_members_count`
|
||||
- :meth:`~Client.iter_chat_members`
|
||||
- :meth:`~Client.get_dialogs`
|
||||
- :meth:`~Client.iter_dialogs`
|
||||
- :meth:`~Client.get_dialogs_count`
|
||||
- :meth:`~Client.restrict_chat`
|
||||
- :meth:`~Client.update_chat_username`
|
||||
|
||||
Users
|
||||
-----
|
||||
^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
get_me
|
||||
get_users
|
||||
get_user_profile_photos
|
||||
get_user_profile_photos_count
|
||||
set_user_profile_photo
|
||||
delete_user_profile_photos
|
||||
update_username
|
||||
- :meth:`~Client.get_me`
|
||||
- :meth:`~Client.get_users`
|
||||
- :meth:`~Client.get_profile_photos`
|
||||
- :meth:`~Client.get_profile_photos_count`
|
||||
- :meth:`~Client.iter_profile_photos`
|
||||
- :meth:`~Client.set_profile_photo`
|
||||
- :meth:`~Client.delete_profile_photos`
|
||||
- :meth:`~Client.update_username`
|
||||
- :meth:`~Client.get_user_dc`
|
||||
|
||||
Contacts
|
||||
--------
|
||||
^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
add_contacts
|
||||
get_contacts
|
||||
get_contacts_count
|
||||
delete_contacts
|
||||
- :meth:`~Client.add_contacts`
|
||||
- :meth:`~Client.get_contacts`
|
||||
- :meth:`~Client.get_contacts_count`
|
||||
- :meth:`~Client.delete_contacts`
|
||||
|
||||
Password
|
||||
--------
|
||||
^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
enable_cloud_password
|
||||
change_cloud_password
|
||||
remove_cloud_password
|
||||
- :meth:`~Client.enable_cloud_password`
|
||||
- :meth:`~Client.change_cloud_password`
|
||||
- :meth:`~Client.remove_cloud_password`
|
||||
|
||||
Bots
|
||||
----
|
||||
^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
get_inline_bot_results
|
||||
send_inline_bot_result
|
||||
answer_callback_query
|
||||
answer_inline_query
|
||||
request_callback_answer
|
||||
send_game
|
||||
set_game_score
|
||||
get_game_high_scores
|
||||
- :meth:`~Client.get_inline_bot_results`
|
||||
- :meth:`~Client.send_inline_bot_result`
|
||||
- :meth:`~Client.answer_callback_query`
|
||||
- :meth:`~Client.answer_inline_query`
|
||||
- :meth:`~Client.request_callback_answer`
|
||||
- :meth:`~Client.send_game`
|
||||
- :meth:`~Client.set_game_score`
|
||||
- :meth:`~Client.get_game_high_scores`
|
||||
|
||||
-----
|
||||
|
||||
Details
|
||||
-------
|
||||
|
||||
.. Utilities
|
||||
---------
|
||||
|
||||
.. automethod:: pyrogram.Client.start()
|
||||
.. automethod:: pyrogram.Client.stop()
|
||||
.. automethod:: pyrogram.Client.restart()
|
||||
.. automethod:: pyrogram.Client.idle()
|
||||
.. automethod:: pyrogram.Client.run()
|
||||
.. automethod:: pyrogram.Client.add_handler()
|
||||
.. automethod:: pyrogram.Client.remove_handler()
|
||||
.. automethod:: pyrogram.Client.send()
|
||||
.. automethod:: pyrogram.Client.resolve_peer()
|
||||
.. automethod:: pyrogram.Client.save_file()
|
||||
.. automethod:: pyrogram.Client.stop_transmission()
|
||||
.. automethod:: Client.start()
|
||||
.. automethod:: Client.stop()
|
||||
.. automethod:: Client.restart()
|
||||
.. automethod:: Client.idle()
|
||||
.. automethod:: Client.run()
|
||||
.. automethod:: Client.add_handler()
|
||||
.. automethod:: Client.remove_handler()
|
||||
.. automethod:: Client.send()
|
||||
.. automethod:: Client.resolve_peer()
|
||||
.. automethod:: Client.save_file()
|
||||
.. automethod:: Client.stop_transmission()
|
||||
|
||||
.. Messages
|
||||
--------
|
||||
|
||||
.. automethod:: pyrogram.Client.send_message()
|
||||
.. automethod:: pyrogram.Client.forward_messages()
|
||||
.. automethod:: pyrogram.Client.send_photo()
|
||||
.. automethod:: pyrogram.Client.send_audio()
|
||||
.. automethod:: pyrogram.Client.send_document()
|
||||
.. automethod:: pyrogram.Client.send_sticker()
|
||||
.. automethod:: pyrogram.Client.send_video()
|
||||
.. automethod:: pyrogram.Client.send_animation()
|
||||
.. automethod:: pyrogram.Client.send_voice()
|
||||
.. automethod:: pyrogram.Client.send_video_note()
|
||||
.. automethod:: pyrogram.Client.send_media_group()
|
||||
.. automethod:: pyrogram.Client.send_location()
|
||||
.. automethod:: pyrogram.Client.send_venue()
|
||||
.. automethod:: pyrogram.Client.send_contact()
|
||||
.. automethod:: pyrogram.Client.send_cached_media()
|
||||
.. automethod:: pyrogram.Client.send_chat_action()
|
||||
.. automethod:: pyrogram.Client.edit_message_text()
|
||||
.. automethod:: pyrogram.Client.edit_message_caption()
|
||||
.. automethod:: pyrogram.Client.edit_message_reply_markup()
|
||||
.. automethod:: pyrogram.Client.edit_message_media()
|
||||
.. automethod:: pyrogram.Client.delete_messages()
|
||||
.. automethod:: pyrogram.Client.get_messages()
|
||||
.. automethod:: pyrogram.Client.get_history()
|
||||
.. automethod:: pyrogram.Client.get_history_count()
|
||||
.. automethod:: pyrogram.Client.iter_history()
|
||||
.. automethod:: pyrogram.Client.send_poll()
|
||||
.. automethod:: pyrogram.Client.vote_poll()
|
||||
.. automethod:: pyrogram.Client.stop_poll()
|
||||
.. automethod:: pyrogram.Client.retract_vote()
|
||||
.. automethod:: pyrogram.Client.download_media()
|
||||
.. automethod:: Client.send_message()
|
||||
.. automethod:: Client.forward_messages()
|
||||
.. automethod:: Client.send_photo()
|
||||
.. automethod:: Client.send_audio()
|
||||
.. automethod:: Client.send_document()
|
||||
.. automethod:: Client.send_sticker()
|
||||
.. automethod:: Client.send_animated_sticker()
|
||||
.. automethod:: Client.send_video()
|
||||
.. automethod:: Client.send_animation()
|
||||
.. automethod:: Client.send_voice()
|
||||
.. automethod:: Client.send_video_note()
|
||||
.. automethod:: Client.send_media_group()
|
||||
.. automethod:: Client.send_location()
|
||||
.. automethod:: Client.send_venue()
|
||||
.. automethod:: Client.send_contact()
|
||||
.. automethod:: Client.send_cached_media()
|
||||
.. automethod:: Client.send_chat_action()
|
||||
.. automethod:: Client.edit_message_text()
|
||||
.. automethod:: Client.edit_message_caption()
|
||||
.. automethod:: Client.edit_message_reply_markup()
|
||||
.. automethod:: Client.edit_message_media()
|
||||
.. automethod:: Client.delete_messages()
|
||||
.. automethod:: Client.get_messages()
|
||||
.. automethod:: Client.get_history()
|
||||
.. automethod:: Client.get_history_count()
|
||||
.. automethod:: Client.iter_history()
|
||||
.. automethod:: Client.send_poll()
|
||||
.. automethod:: Client.vote_poll()
|
||||
.. automethod:: Client.stop_poll()
|
||||
.. automethod:: Client.retract_vote()
|
||||
.. automethod:: Client.download_media()
|
||||
|
||||
.. Chats
|
||||
-----
|
||||
|
||||
.. automethod:: pyrogram.Client.join_chat()
|
||||
.. automethod:: pyrogram.Client.leave_chat()
|
||||
.. automethod:: pyrogram.Client.kick_chat_member()
|
||||
.. automethod:: pyrogram.Client.unban_chat_member()
|
||||
.. automethod:: pyrogram.Client.restrict_chat_member()
|
||||
.. automethod:: pyrogram.Client.promote_chat_member()
|
||||
.. automethod:: pyrogram.Client.export_chat_invite_link()
|
||||
.. automethod:: pyrogram.Client.set_chat_photo()
|
||||
.. automethod:: pyrogram.Client.delete_chat_photo()
|
||||
.. automethod:: pyrogram.Client.set_chat_title()
|
||||
.. automethod:: pyrogram.Client.set_chat_description()
|
||||
.. automethod:: pyrogram.Client.pin_chat_message()
|
||||
.. automethod:: pyrogram.Client.unpin_chat_message()
|
||||
.. automethod:: pyrogram.Client.get_chat()
|
||||
.. automethod:: pyrogram.Client.get_chat_member()
|
||||
.. automethod:: pyrogram.Client.get_chat_members()
|
||||
.. automethod:: pyrogram.Client.get_chat_members_count()
|
||||
.. automethod:: pyrogram.Client.iter_chat_members()
|
||||
.. automethod:: pyrogram.Client.get_dialogs()
|
||||
.. automethod:: pyrogram.Client.iter_dialogs()
|
||||
.. automethod:: pyrogram.Client.get_dialogs_count()
|
||||
.. automethod:: pyrogram.Client.restrict_chat()
|
||||
.. automethod:: pyrogram.Client.update_chat_username()
|
||||
.. automethod:: Client.join_chat()
|
||||
.. automethod:: Client.leave_chat()
|
||||
.. automethod:: Client.kick_chat_member()
|
||||
.. automethod:: Client.unban_chat_member()
|
||||
.. automethod:: Client.restrict_chat_member()
|
||||
.. automethod:: Client.promote_chat_member()
|
||||
.. automethod:: Client.export_chat_invite_link()
|
||||
.. automethod:: Client.set_chat_photo()
|
||||
.. automethod:: Client.delete_chat_photo()
|
||||
.. automethod:: Client.set_chat_title()
|
||||
.. automethod:: Client.set_chat_description()
|
||||
.. automethod:: Client.pin_chat_message()
|
||||
.. automethod:: Client.unpin_chat_message()
|
||||
.. automethod:: Client.get_chat()
|
||||
.. automethod:: Client.get_chat_member()
|
||||
.. automethod:: Client.get_chat_members()
|
||||
.. automethod:: Client.get_chat_members_count()
|
||||
.. automethod:: Client.iter_chat_members()
|
||||
.. automethod:: Client.get_dialogs()
|
||||
.. automethod:: Client.iter_dialogs()
|
||||
.. automethod:: Client.get_dialogs_count()
|
||||
.. automethod:: Client.restrict_chat()
|
||||
.. automethod:: Client.update_chat_username()
|
||||
|
||||
.. Users
|
||||
-----
|
||||
|
||||
.. automethod:: pyrogram.Client.get_me()
|
||||
.. automethod:: pyrogram.Client.get_users()
|
||||
.. automethod:: pyrogram.Client.get_user_profile_photos()
|
||||
.. automethod:: pyrogram.Client.get_user_profile_photos_count()
|
||||
.. automethod:: pyrogram.Client.set_user_profile_photo()
|
||||
.. automethod:: pyrogram.Client.delete_user_profile_photos()
|
||||
.. automethod:: pyrogram.Client.update_username()
|
||||
.. automethod:: Client.get_me()
|
||||
.. automethod:: Client.get_users()
|
||||
.. automethod:: Client.get_profile_photos()
|
||||
.. automethod:: Client.get_profile_photos_count()
|
||||
.. automethod:: Client.iter_profile_photos()
|
||||
.. automethod:: Client.set_profile_photo()
|
||||
.. automethod:: Client.delete_profile_photos()
|
||||
.. automethod:: Client.update_username()
|
||||
.. automethod:: Client.get_user_dc()
|
||||
|
||||
.. Contacts
|
||||
--------
|
||||
|
||||
.. automethod:: pyrogram.Client.add_contacts()
|
||||
.. automethod:: pyrogram.Client.get_contacts()
|
||||
.. automethod:: pyrogram.Client.get_contacts_count()
|
||||
.. automethod:: pyrogram.Client.delete_contacts()
|
||||
.. automethod:: Client.add_contacts()
|
||||
.. automethod:: Client.get_contacts()
|
||||
.. automethod:: Client.get_contacts_count()
|
||||
.. automethod:: Client.delete_contacts()
|
||||
|
||||
.. Password
|
||||
--------
|
||||
|
||||
.. automethod:: pyrogram.Client.enable_cloud_password()
|
||||
.. automethod:: pyrogram.Client.change_cloud_password()
|
||||
.. automethod:: pyrogram.Client.remove_cloud_password()
|
||||
.. automethod:: Client.enable_cloud_password()
|
||||
.. automethod:: Client.change_cloud_password()
|
||||
.. automethod:: Client.remove_cloud_password()
|
||||
|
||||
.. Bots
|
||||
----
|
||||
|
||||
.. automethod:: pyrogram.Client.get_inline_bot_results()
|
||||
.. automethod:: pyrogram.Client.send_inline_bot_result()
|
||||
.. automethod:: pyrogram.Client.answer_callback_query()
|
||||
.. automethod:: pyrogram.Client.answer_inline_query()
|
||||
.. automethod:: pyrogram.Client.request_callback_answer()
|
||||
.. automethod:: pyrogram.Client.send_game()
|
||||
.. automethod:: pyrogram.Client.set_game_score()
|
||||
.. automethod:: pyrogram.Client.get_game_high_scores()
|
||||
.. automethod:: Client.get_inline_bot_results()
|
||||
.. automethod:: Client.send_inline_bot_result()
|
||||
.. automethod:: Client.answer_callback_query()
|
||||
.. automethod:: Client.answer_inline_query()
|
||||
.. automethod:: Client.request_callback_answer()
|
||||
.. automethod:: Client.send_game()
|
||||
.. automethod:: Client.set_game_score()
|
||||
.. automethod:: Client.get_game_high_scores()
|
||||
|
@ -15,102 +15,108 @@ All Pyrogram types listed here are accessible through the main package directly.
|
||||
|
||||
.. currentmodule:: pyrogram
|
||||
|
||||
Index
|
||||
-----
|
||||
|
||||
Users & Chats
|
||||
-------------
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 5
|
||||
|
||||
User
|
||||
UserStatus
|
||||
Chat
|
||||
ChatPreview
|
||||
ChatPhoto
|
||||
ChatMember
|
||||
ChatMembers
|
||||
ChatPermissions
|
||||
Dialog
|
||||
Dialogs
|
||||
- :class:`User`
|
||||
- :class:`UserStatus`
|
||||
- :class:`Chat`
|
||||
- :class:`ChatPreview`
|
||||
- :class:`ChatPhoto`
|
||||
- :class:`ChatMember`
|
||||
- :class:`ChatMembers`
|
||||
- :class:`ChatPermissions`
|
||||
- :class:`Dialog`
|
||||
- :class:`Dialogs`
|
||||
|
||||
Messages & Media
|
||||
----------------
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 5
|
||||
|
||||
Message
|
||||
Messages
|
||||
MessageEntity
|
||||
Photo
|
||||
PhotoSize
|
||||
UserProfilePhotos
|
||||
Audio
|
||||
Document
|
||||
Animation
|
||||
Video
|
||||
Voice
|
||||
VideoNote
|
||||
Contact
|
||||
Location
|
||||
Venue
|
||||
Sticker
|
||||
Game
|
||||
Poll
|
||||
PollOption
|
||||
- :class:`Message`
|
||||
- :class:`Messages`
|
||||
- :class:`MessageEntity`
|
||||
- :class:`Photo`
|
||||
- :class:`Photos`
|
||||
- :class:`Thumbnail`
|
||||
- :class:`Audio`
|
||||
- :class:`Document`
|
||||
- :class:`Animation`
|
||||
- :class:`Video`
|
||||
- :class:`Voice`
|
||||
- :class:`VideoNote`
|
||||
- :class:`Contact`
|
||||
- :class:`Location`
|
||||
- :class:`Venue`
|
||||
- :class:`Sticker`
|
||||
- :class:`Game`
|
||||
- :class:`Poll`
|
||||
- :class:`PollOption`
|
||||
|
||||
Keyboards
|
||||
---------
|
||||
^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 4
|
||||
|
||||
ReplyKeyboardMarkup
|
||||
KeyboardButton
|
||||
ReplyKeyboardRemove
|
||||
InlineKeyboardMarkup
|
||||
InlineKeyboardButton
|
||||
ForceReply
|
||||
CallbackQuery
|
||||
GameHighScore
|
||||
GameHighScores
|
||||
CallbackGame
|
||||
- :class:`ReplyKeyboardMarkup`
|
||||
- :class:`KeyboardButton`
|
||||
- :class:`ReplyKeyboardRemove`
|
||||
- :class:`InlineKeyboardMarkup`
|
||||
- :class:`InlineKeyboardButton`
|
||||
- :class:`ForceReply`
|
||||
- :class:`CallbackQuery`
|
||||
- :class:`GameHighScore`
|
||||
- :class:`GameHighScores`
|
||||
- :class:`CallbackGame`
|
||||
|
||||
Input Media
|
||||
-----------
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 4
|
||||
|
||||
InputMedia
|
||||
InputMediaPhoto
|
||||
InputMediaVideo
|
||||
InputMediaAudio
|
||||
InputMediaAnimation
|
||||
InputMediaDocument
|
||||
InputPhoneContact
|
||||
- :class:`InputMedia`
|
||||
- :class:`InputMediaPhoto`
|
||||
- :class:`InputMediaVideo`
|
||||
- :class:`InputMediaAudio`
|
||||
- :class:`InputMediaAnimation`
|
||||
- :class:`InputMediaDocument`
|
||||
- :class:`InputPhoneContact`
|
||||
|
||||
Inline Mode
|
||||
------------
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
InlineQuery
|
||||
InlineQueryResult
|
||||
InlineQueryResultArticle
|
||||
- :class:`InlineQuery`
|
||||
- :class:`InlineQueryResult`
|
||||
- :class:`InlineQueryResultArticle`
|
||||
|
||||
InputMessageContent
|
||||
-------------------
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
InputMessageContent
|
||||
InputTextMessageContent
|
||||
- :class:`InputMessageContent`
|
||||
- :class:`InputTextMessageContent`
|
||||
|
||||
-----
|
||||
|
||||
Details
|
||||
-------
|
||||
|
||||
.. User & Chats
|
||||
------------
|
||||
|
||||
.. autoclass:: User()
|
||||
.. autoclass:: UserStatus()
|
||||
.. autoclass:: Chat()
|
||||
@ -123,14 +129,12 @@ InputMessageContent
|
||||
.. autoclass:: Dialogs()
|
||||
|
||||
.. Messages & Media
|
||||
----------------
|
||||
|
||||
.. autoclass:: Message()
|
||||
.. autoclass:: Messages()
|
||||
.. autoclass:: MessageEntity()
|
||||
.. autoclass:: Photo()
|
||||
.. autoclass:: PhotoSize()
|
||||
.. autoclass:: UserProfilePhotos()
|
||||
.. autoclass:: Photos()
|
||||
.. autoclass:: Thumbnail()
|
||||
.. autoclass:: Audio()
|
||||
.. autoclass:: Document()
|
||||
.. autoclass:: Animation()
|
||||
@ -146,8 +150,6 @@ InputMessageContent
|
||||
.. autoclass:: PollOption()
|
||||
|
||||
.. Keyboards
|
||||
---------
|
||||
|
||||
.. autoclass:: ReplyKeyboardMarkup()
|
||||
.. autoclass:: KeyboardButton()
|
||||
.. autoclass:: ReplyKeyboardRemove()
|
||||
@ -160,8 +162,6 @@ InputMessageContent
|
||||
.. autoclass:: CallbackGame()
|
||||
|
||||
.. Input Media
|
||||
-----------
|
||||
|
||||
.. autoclass:: InputMedia()
|
||||
.. autoclass:: InputMediaPhoto()
|
||||
.. autoclass:: InputMediaVideo()
|
||||
@ -171,14 +171,10 @@ InputMessageContent
|
||||
.. autoclass:: InputPhoneContact()
|
||||
|
||||
.. Inline Mode
|
||||
-----------
|
||||
|
||||
.. autoclass:: InlineQuery()
|
||||
.. autoclass:: InlineQueryResult()
|
||||
.. autoclass:: InlineQueryResultArticle()
|
||||
|
||||
.. InputMessageContent
|
||||
-------------------
|
||||
|
||||
.. autoclass:: InputMessageContent()
|
||||
.. autoclass:: InputTextMessageContent()
|
||||
|
@ -43,7 +43,6 @@ autodoc_member_order = "bysource"
|
||||
|
||||
version = __version__
|
||||
release = version
|
||||
version_rst = ".. |version| replace:: {}".format(version)
|
||||
|
||||
templates_path = ["_templates"]
|
||||
|
||||
@ -61,7 +60,8 @@ html_theme_options = {
|
||||
"collapse_navigation": True,
|
||||
"sticky_navigation": False,
|
||||
"logo_only": True,
|
||||
"display_version": True
|
||||
"display_version": True,
|
||||
"style_external_links": True
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
.. _MTProto API: topics/mtproto-vs-botapi#what-is-the-mtproto-api
|
||||
|
||||
Where does the name come from?
|
||||
------------------------------
|
||||
@ -47,19 +46,17 @@ Why Pyrogram?
|
||||
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
||||
- **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.
|
||||
- **Pluggable**: The `Smart Plugin`_ system allows to write components with minimal boilerplate code.
|
||||
- **Comprehensive**: Execute any `advanced action`_ an official client is able to do, and even more.
|
||||
- **Pluggable**: The :doc:`Smart Plugin <topics/smart-plugins>` system allows to write components with minimal
|
||||
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
|
||||
.. _Smart Plugin: topics/smart-plugins
|
||||
.. _advanced action: topics/advanced-usage
|
||||
|
||||
What can MTProto do more than the Bot API?
|
||||
------------------------------------------
|
||||
|
||||
For a detailed answer, please refer to the `MTProto vs. Bot API`_ page.
|
||||
|
||||
.. _MTProto vs. Bot API: topics/mtproto-vs-botapi
|
||||
For a detailed answer, please refer to the :doc:`MTProto vs. Bot API <topics/mtproto-vs-botapi>` page.
|
||||
|
||||
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
|
||||
losing the *persistence* feature.
|
||||
|
||||
This change will most likely affect the official `Bot API <topics/mtproto-vs-botapi#what-is-the-bot-api>`_ too
|
||||
(unless Telegram implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn
|
||||
make use of) and we can expect a proper notice from Telegram.
|
||||
This change will most likely affect the official :doc:`Bot API <topics/mtproto-vs-botapi>` too (unless Telegram
|
||||
implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn make use of) and
|
||||
we can expect a proper notice from Telegram.
|
||||
|
||||
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!
|
||||
---------------------------------------
|
||||
|
||||
If you are connecting from Russia, China or Iran `you need a proxy`_, because Telegram could be partially or
|
||||
totally blocked in those countries.
|
||||
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
|
||||
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
|
||||
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``
|
||||
- DC5: ``91.108.56.149``
|
||||
|
||||
.. _you need a proxy: topics/proxy
|
||||
|
||||
I keep getting PEER_ID_INVALID error!
|
||||
-------------------------------------------
|
||||
|
||||
@ -160,6 +155,15 @@ things:
|
||||
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)``.
|
||||
|
||||
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!
|
||||
----------------------------------------
|
||||
|
||||
@ -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
|
||||
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
|
||||
.. _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
|
||||
.. _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
|
||||
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.
|
||||
`More on API keys <intro/setup#api-keys>`_.
|
||||
:doc:`More on API keys <intro/setup>`.
|
||||
|
||||
DC
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
`More on MTProto API <topics/mtproto-vs-botapi#what-is-the-mtproto-api>`_.
|
||||
:doc:`More on MTProto API <topics/mtproto-vs-botapi>`.
|
||||
|
||||
Bot API
|
||||
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.
|
||||
`More on Bot API <topics/mtproto-vs-botapi#what-is-the-bot-api>`_.
|
||||
:doc:`More on Bot API <topics/mtproto-vs-botapi>`.
|
||||
|
||||
Pyrogrammer
|
||||
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
|
||||
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.
|
||||
`More on Handlers <start/updates>`_.
|
||||
:doc:`More on Handlers <start/updates>`.
|
||||
|
||||
Decorator
|
||||
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.
|
||||
`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
|
||||
|
@ -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
|
||||
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
|
||||
.. _MTProto API: topics/mtproto-vs-botapi#what-is-the-mtproto-api
|
||||
|
||||
How the Documentation is Organized
|
||||
----------------------------------
|
||||
@ -60,15 +59,10 @@ First Steps
|
||||
.. hlist::
|
||||
:columns: 2
|
||||
|
||||
- `Quick Start`_: Overview to get you started quickly.
|
||||
- `Calling Methods`_: How to call Pyrogram's methods.
|
||||
- `Handling Updates`_: How to handle Telegram updates.
|
||||
- `Error Handling`_: How to handle API errors correctly.
|
||||
|
||||
.. _Quick Start: intro/quickstart
|
||||
.. _Calling Methods: start/invoking
|
||||
.. _Handling Updates: start/updates
|
||||
.. _Error Handling: start/errors
|
||||
- :doc:`Quick Start <intro/quickstart>`: Overview to get you started quickly.
|
||||
- :doc:`Calling Methods <start/invoking>`: How to call Pyrogram's methods.
|
||||
- :doc:`Handling Updates <start/updates>`: How to handle Telegram updates.
|
||||
- :doc:`Error Handling <start/errors>`: How to handle API errors correctly.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
@ -76,15 +70,10 @@ API Reference
|
||||
.. hlist::
|
||||
:columns: 2
|
||||
|
||||
- `Pyrogram Client`_: Reference details about the Client class.
|
||||
- `Available Methods`_: List of available high-level methods.
|
||||
- `Available Types`_: List of available high-level types.
|
||||
- `Bound Methods`_: List of convenient bound methods.
|
||||
|
||||
.. _Pyrogram Client: ./api/client
|
||||
.. _Available Methods: api/methods
|
||||
.. _Available Types: api/types
|
||||
.. _Bound Methods: api/bound-methods
|
||||
- :doc:`Pyrogram Client <api/client>`: Reference details about the Client class.
|
||||
- :doc:`Available Methods <api/methods>`: List of available high-level methods.
|
||||
- :doc:`Available Types <api/types>`: List of available high-level types.
|
||||
- :doc:`Bound Methods <api/bound-methods>`: List of convenient bound methods.
|
||||
|
||||
Meta
|
||||
----
|
||||
@ -92,17 +81,12 @@ Meta
|
||||
.. hlist::
|
||||
:columns: 2
|
||||
|
||||
- `Pyrogram FAQ`_: Answers to common Pyrogram questions.
|
||||
- `Pyrogram Glossary`_: List of words with brief explanations.
|
||||
- `Release Notes`_: Release notes for Pyrogram releases.
|
||||
- `Powered by Pyrogram`_: Collection of Pyrogram Projects.
|
||||
- `Support Pyrogram`_: Ways to show your appreciation.
|
||||
|
||||
.. _Pyrogram FAQ: faq
|
||||
.. _Pyrogram Glossary: glossary
|
||||
.. _Release Notes: releases
|
||||
.. _Powered by Pyrogram: powered-by
|
||||
.. _Support Pyrogram: support-pyrogram
|
||||
- :doc:`Pyrogram FAQ <faq>`: Answers to common Pyrogram questions.
|
||||
- :doc:`Pyrogram Glossary <glossary>`: List of words with brief explanations.
|
||||
- :doc:`Release Notes <releases>`: Release notes for Pyrogram releases.
|
||||
- :doc:`Powered by Pyrogram <powered-by>`: Collection of Pyrogram Projects.
|
||||
- :doc:`Support Pyrogram <support-pyrogram>`: Ways to show your appreciation.
|
||||
- :doc:`About the License <license>`: Information about the Project license.
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
@ -163,6 +147,7 @@ Meta
|
||||
releases
|
||||
powered-by
|
||||
support-pyrogram
|
||||
license
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
@ -170,3 +155,5 @@ Meta
|
||||
|
||||
telegram/functions/index
|
||||
telegram/types/index
|
||||
|
||||
Last updated on |today|
|
@ -20,7 +20,7 @@ Install 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
|
||||
|
||||
@ -89,5 +89,4 @@ If no error shows up you are good to go.
|
||||
>>> pyrogram.__version__
|
||||
'|version|'
|
||||
|
||||
.. _TgCrypto: ../topics/tgcrypto
|
||||
.. _`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!
|
||||
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
|
||||
.. _Calling Methods: ../start/invoking
|
@ -1,8 +1,8 @@
|
||||
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
|
||||
the library. Let's see how it's done.
|
||||
We have just :doc:`installed Pyrogram <install>`. In this page we'll discuss what you need to do in order to set up a
|
||||
project with the library. Let's see how it's done.
|
||||
|
||||
API Keys
|
||||
--------
|
||||
@ -26,7 +26,7 @@ The very first step requires you to obtain a valid Telegram API key (API id/hash
|
||||
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:
|
||||
|
||||
- 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,
|
||||
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
|
||||
=============
|
||||
|
||||
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.
|
||||
|
||||
User Authorization
|
||||
@ -9,8 +9,8 @@ User Authorization
|
||||
|
||||
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
|
||||
:class:`Client <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:
|
||||
:class:`~pyrogram.Client` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
|
||||
the :meth:`~pyrogram.Client.run` method:
|
||||
|
||||
.. 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
|
||||
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,
|
||||
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()
|
||||
|
||||
.. _project is set up: ../intro/setup
|
||||
.. _Country Code: https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
||||
.. _Bot Father: https://t.me/botfather
|
@ -1,8 +1,8 @@
|
||||
Calling Methods
|
||||
===============
|
||||
|
||||
At this point, we have successfully `installed Pyrogram`_ and authorized_ our account; we are now aiming towards the
|
||||
core of the library. It's time to start playing with the API!
|
||||
At this point, we have successfully :doc:`installed Pyrogram <../intro/install>` and :doc:`authorized <auth>` our
|
||||
account; we are now aiming towards the core of the library. It's time to start playing with the API!
|
||||
|
||||
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
|
||||
:meth:`start() <pyrogram.Client.start>` and :meth:`stop() <pyrogram.Client.stop>` gracefully, even in case of unhandled
|
||||
exceptions in your code. The example above can be therefore rewritten in a much nicer way:
|
||||
:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop` gracefully, even in case of unhandled exceptions in
|
||||
your code. The example above can be therefore rewritten in a much nicer way:
|
||||
|
||||
.. 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")
|
||||
|
||||
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
|
||||
================
|
||||
|
||||
Calling `API methods`_ sequentially is cool, but how to react when, for example, a new message arrives? This page deals
|
||||
with updates and how to handle such events in Pyrogram. Let's have a look at how they work.
|
||||
Calling :doc:`API methods <invoking>` sequentially is cool, but how to react when, for example, a new message arrives?
|
||||
This page deals with updates and how to handle such events in Pyrogram. Let's have a look at how they work.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
---------------------
|
||||
|
||||
To explain how handlers work let's have a look at the most used one, the
|
||||
:obj:`MessageHandler <pyrogram.MessageHandler>`, which will be in charge for handling :obj:`Message <pyrogram.Message>`
|
||||
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
||||
settings them up once you learn from this section.
|
||||
To explain how handlers work let's have a look at the most used one, the :class:`~pyrogram.MessageHandler`, which will
|
||||
be in charge for handling :class:`~pyrogram.Message` updates coming from all around your chats. Every other handler shares
|
||||
the same setup logic; you should not have troubles settings them up once you learn from this section.
|
||||
|
||||
Using add_handler()
|
||||
-------------------
|
||||
|
||||
The :meth:`add_handler() <pyrogram.Client.add_handler>` method takes any handler instance that wraps around your defined
|
||||
callback function and registers it in your Client. Here's a full example that prints out the content of a message as
|
||||
soon as it arrives:
|
||||
The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback
|
||||
function and registers it in your Client. Here's a full example that prints out the content of a message as soon as it
|
||||
arrives:
|
||||
|
||||
.. 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):
|
||||
print(message)
|
||||
|
||||
Second one: the :obj:`MessageHandler <pyrogram.MessageHandler>`. This object tells Pyrogram the function we defined
|
||||
above must only handle updates that are in form of a :obj:`Message <pyrogram.Message>`:
|
||||
Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must only
|
||||
handle updates that are in form of a :class:`~pyrogram.Message`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
my_handler = MessageHandler(my_function)
|
||||
|
||||
Third: the method :meth:`add_handler() <pyrogram.Client.add_handler>`. This method is used to actually register the
|
||||
handler and let Pyrogram know it needs to be taken into consideration when new updates arrive and the internal
|
||||
dispatching phase begins.
|
||||
Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
|
||||
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase begins.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.add_handler(my_handler)
|
||||
|
||||
Last one, the :meth:`run() <pyrogram.Client.run>` method. What this does is simply call
|
||||
:meth:`start() <pyrogram.Client.start>` and a special method :meth:`idle() <pyrogram.Client.idle>` that keeps your main
|
||||
scripts alive until you press ``CTRL+C``; the client will be automatically stopped after that.
|
||||
Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and a
|
||||
special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the client
|
||||
will be automatically stopped after that.
|
||||
|
||||
.. 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
|
||||
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
|
||||
|
||||
@ -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
|
||||
``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]*.
|
||||
|
||||
.. _API methods: invoking
|
@ -1,8 +1,8 @@
|
||||
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
|
||||
be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated.
|
||||
Pyrogram is free and open source software, and thus powered by your love and support! If you like the project and have
|
||||
found it to be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@ -12,8 +12,9 @@ be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and
|
||||
Donate
|
||||
------
|
||||
|
||||
If you'd also like to donate in order to support Pyrogram -- or any of my `other works`_ -- you can use the PayPal
|
||||
button below. Thank you.
|
||||
As a developer, you probably understand that "open source" doesn't mean "free work". A lot of time and resources has
|
||||
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
|
||||
:target: https://paypal.me/delivrance
|
||||
|
@ -1,8 +1,9 @@
|
||||
Advanced Usage
|
||||
==============
|
||||
|
||||
Pyrogram's API, which consists of well documented convenience methods_ and facade types_, exists to provide a much
|
||||
easier interface to the undocumented and often confusing Telegram API.
|
||||
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods>` and facade
|
||||
: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"
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
|
||||
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API (yet much more
|
||||
powerful).
|
||||
Nothing stops you from using the raw functions only, but they are rather complex and
|
||||
:doc:`plenty of them <../api/methods>` are already re-implemented by providing a much simpler and cleaner interface
|
||||
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_!
|
||||
|
||||
Invoking Functions
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Unlike the methods_ found in Pyrogram's API, which can be called in the usual simple way, functions to be invoked from
|
||||
the raw Telegram API have a different way of usage and are more complex.
|
||||
Unlike the :doc:`methods <../api/methods>` found in Pyrogram's API, which can be called in the usual simple way,
|
||||
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):
|
||||
``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python 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.
|
||||
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>` live in their
|
||||
respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python
|
||||
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
|
||||
the Client class and pass the function object you created.
|
||||
Next, to actually invoke the raw function you have to use the :meth:`~pyrogram.Client.send` method provided by the
|
||||
Client class and pass the function object you created.
|
||||
|
||||
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.
|
||||
Whenever an InputPeer is needed you must pass one of these:
|
||||
|
||||
- :obj:`InputPeerUser <../telegram/types/InputPeerUser>` - Users
|
||||
- :obj:`InputPeerChat <../telegram/types/InputPeerChat>` - Basic Chats
|
||||
- :obj:`InputPeerChannel <../telegram/types/InputPeerChannel>` - Either Channels or Supergroups
|
||||
- :class:`~pyrogram.api.types.InputPeerUser` - Users
|
||||
- :class:`~pyrogram.api.types.InputPeerChat` - Basic Chats
|
||||
- :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
|
||||
: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.
|
||||
|
||||
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
|
||||
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
|
@ -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.
|
||||
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
|
||||
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
|
||||
:meth:`get_inline_bot_results() <pyrogram.Client.get_inline_bot_results>` to get the list of its inline results
|
||||
for a query:
|
||||
:meth:`~pyrogram.Client.get_inline_bot_results` to get the list of its inline results for a query:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@ -24,7 +23,7 @@ Inline Bots
|
||||
results list.
|
||||
|
||||
- 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
|
||||
|
||||
|
@ -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,
|
||||
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.
|
||||
|
||||
Single Filters
|
||||
@ -12,7 +12,7 @@ Single Filters
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: python
|
||||
@ -69,7 +69,7 @@ Here are some examples:
|
||||
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:
|
||||
|
||||
- Message is either a */start* or */help* **command**.
|
||||
@ -109,18 +109,18 @@ More handlers using different filters can also live together.
|
||||
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,
|
||||
for example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||
for example) you can use :meth:`~pyrogram.Filters.create`.
|
||||
|
||||
.. 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
|
||||
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by
|
||||
bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline
|
||||
keyboard to yourself. This allows you to test your filter by pressing the inline button:
|
||||
:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots; create and
|
||||
:doc:`authorize your bot <../start/auth>`, then send a message with an inline keyboard to yourself. This allows you to
|
||||
test your filter by pressing the inline button:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@ -137,7 +137,7 @@ keyboard to yourself. This allows you to test your filter by pressing the inline
|
||||
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
|
||||
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 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:
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
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
|
||||
--------------
|
||||
@ -44,7 +45,7 @@ Or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-
|
||||
def just_text(client, message):
|
||||
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
|
||||
|
||||
@ -217,6 +218,3 @@ The output of both (equivalent) examples will be:
|
||||
0
|
||||
1
|
||||
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
|
||||
`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
|
||||
|
||||
@ -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
|
||||
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)
|
||||
------------------------
|
||||
|
||||
|
@ -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.
|
||||
|
||||
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.
|
||||
|
||||
.. figure:: https://i.imgur.com/YaqtMLO.png
|
||||
|
@ -65,8 +65,8 @@ after importing your modules, like this:
|
||||
app.run()
|
||||
|
||||
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
|
||||
:obj:`MessageHandler <pyrogram.MessageHandler>` object because **you can't use those cool decorators** for your
|
||||
manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each
|
||||
: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.
|
||||
|
||||
Using Smart Plugins
|
||||
@ -80,7 +80,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
|
||||
|
||||
.. 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
|
||||
:emphasize-lines: 2, 3
|
||||
@ -156,7 +156,7 @@ found inside each module will be, instead, loaded in the order they are defined,
|
||||
.. note::
|
||||
|
||||
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
|
||||
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
|
||||
------------------------------
|
||||
|
||||
In the `previous section <#specifying-the-plugins-to-include>`_ we've explained how to specify which plugins to load and
|
||||
which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously
|
||||
registered plugin at runtime.
|
||||
In the previous section we've explained how to specify which plugins to load and which to ignore before your Client
|
||||
starts. Here we'll show, instead, how to unload and load again a previously registered plugin at runtime.
|
||||
|
||||
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
|
||||
@ -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
|
||||
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:
|
||||
|
||||
- ``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
|
||||
using :meth:`add_handler() <pyrogram.Client.add_handler>` instead. Example:
|
||||
using :meth:`~pyrogram.Client.add_handler` instead. Example:
|
||||
|
||||
- ``main.py``
|
||||
|
||||
|
@ -12,7 +12,7 @@ Markdown Style
|
||||
--------------
|
||||
|
||||
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
|
||||
|
||||
@ -34,7 +34,7 @@ To use this mode, pass "markdown" in the *parse_mode* field when using
|
||||
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:
|
||||
|
||||
.. 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.
|
||||
sys.modules["typing"] = typing
|
||||
|
||||
__version__ = "0.13.0.async"
|
||||
__version__ = "0.13.0-asyncio"
|
||||
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
||||
__copyright__ = "Copyright (C) 2017-2019 Dan <https://github.com/delivrance>"
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
from .future_salt import FutureSalt
|
||||
from .future_salts import FutureSalts
|
||||
from .gzip_packed import GzipPacked
|
||||
from .list import List
|
||||
from .message import Message
|
||||
from .msg_container import MsgContainer
|
||||
from .object import Object
|
||||
|
@ -16,7 +16,6 @@
|
||||
# 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 datetime import datetime
|
||||
from io import BytesIO
|
||||
|
||||
from .object import Object
|
||||
@ -30,15 +29,15 @@ class FutureSalt(Object):
|
||||
|
||||
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_until = valid_until
|
||||
self.salt = salt
|
||||
|
||||
@staticmethod
|
||||
def read(b: BytesIO, *args) -> "FutureSalt":
|
||||
valid_since = datetime.fromtimestamp(Int.read(b))
|
||||
valid_until = datetime.fromtimestamp(Int.read(b))
|
||||
valid_since = Int.read(b)
|
||||
valid_until = Int.read(b)
|
||||
salt = Long.read(b)
|
||||
|
||||
return FutureSalt(valid_since, valid_until, salt)
|
||||
|
@ -16,7 +16,6 @@
|
||||
# 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 datetime import datetime
|
||||
from io import BytesIO
|
||||
|
||||
from . import FutureSalt
|
||||
@ -31,7 +30,7 @@ class FutureSalts(Object):
|
||||
|
||||
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.now = now
|
||||
self.salts = salts
|
||||
@ -39,7 +38,7 @@ class FutureSalts(Object):
|
||||
@staticmethod
|
||||
def read(b: BytesIO, *args) -> "FutureSalts":
|
||||
req_msg_id = Long.read(b)
|
||||
now = datetime.fromtimestamp(Int.read(b))
|
||||
now = Int.read(b)
|
||||
|
||||
count = Int.read(b)
|
||||
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/>.
|
||||
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from json import dumps
|
||||
|
||||
@ -36,32 +35,22 @@ class Object:
|
||||
def write(self, *args) -> bytes:
|
||||
pass
|
||||
|
||||
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 __str__(self) -> str:
|
||||
def default(obj: Object):
|
||||
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:
|
||||
@staticmethod
|
||||
def default(obj: "Object"):
|
||||
if isinstance(obj, bytes):
|
||||
return repr(obj)
|
||||
|
||||
return dumps(self, indent=4, default=default, ensure_ascii=False)
|
||||
return OrderedDict(
|
||||
[("_", obj.QUALNAME)]
|
||||
+ [
|
||||
(attr, getattr(obj, attr))
|
||||
for attr in obj.__slots__
|
||||
if getattr(obj, attr) is not None
|
||||
]
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return dumps(self, indent=4, default=Object.default, ensure_ascii=False)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
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:
|
||||
return len(self.write())
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
from io import BytesIO
|
||||
|
||||
from . import Int
|
||||
from ..list import List
|
||||
from ..object import Object
|
||||
|
||||
|
||||
@ -37,11 +38,11 @@ class Vector(Object):
|
||||
|
||||
@staticmethod
|
||||
def read(b: BytesIO, t: Object = None) -> list:
|
||||
return [
|
||||
return List(
|
||||
t.read(b) if t
|
||||
else Vector._read(b)
|
||||
for _ in range(Int.read(b))
|
||||
]
|
||||
)
|
||||
|
||||
def __new__(cls, value: list, t: Object = None) -> bytes:
|
||||
return b"".join(
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
import asyncio
|
||||
import base64
|
||||
import binascii
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
@ -27,7 +26,6 @@ import mimetypes
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import struct
|
||||
import tempfile
|
||||
import time
|
||||
from configparser import ConfigParser
|
||||
@ -49,7 +47,7 @@ from pyrogram.errors import (
|
||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
|
||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
||||
VolumeLocNotFound, UserMigrate, ChannelPrivate, PhoneNumberOccupied,
|
||||
PasswordRecoveryNa, PasswordEmpty
|
||||
)
|
||||
from pyrogram.session import Auth, Session
|
||||
@ -320,7 +318,7 @@ class Client(Methods, BaseClient):
|
||||
await self.get_initial_dialogs()
|
||||
await self.get_contacts()
|
||||
else:
|
||||
await self.send(functions.messages.GetPinnedDialogs())
|
||||
await self.send(functions.messages.GetPinnedDialogs(folder_id=0))
|
||||
await self.get_initial_dialogs_chunk()
|
||||
else:
|
||||
await self.send(functions.updates.GetState())
|
||||
@ -430,9 +428,9 @@ class Client(Methods, BaseClient):
|
||||
def run(self, coroutine=None):
|
||||
"""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
|
||||
less verbose, but is not suitable in case you want to run more than one client in a single main script,
|
||||
since :meth:`idle` will block.
|
||||
This is a convenience method that literally just calls :meth:`~Client.start` and :meth:`~Client.idle`. It makes
|
||||
running a client less verbose, but is not suitable in case you want to run more than one client in a single main
|
||||
script, since :meth:`~Client.idle` will block.
|
||||
|
||||
Args:
|
||||
coroutine: (``Coroutine``, *optional*):
|
||||
@ -484,7 +482,7 @@ class Client(Methods, BaseClient):
|
||||
"""Remove a previously-registered update handler.
|
||||
|
||||
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.
|
||||
|
||||
Parameters:
|
||||
@ -777,7 +775,9 @@ class Client(Methods, BaseClient):
|
||||
types.Channel, types.ChannelForbidden
|
||||
]
|
||||
]
|
||||
):
|
||||
) -> bool:
|
||||
is_min = False
|
||||
|
||||
for entity in entities:
|
||||
if isinstance(entity, types.User):
|
||||
user_id = entity.id
|
||||
@ -785,6 +785,7 @@ class Client(Methods, BaseClient):
|
||||
access_hash = entity.access_hash
|
||||
|
||||
if access_hash is None:
|
||||
is_min = True
|
||||
continue
|
||||
|
||||
username = entity.username
|
||||
@ -820,6 +821,7 @@ class Client(Methods, BaseClient):
|
||||
access_hash = entity.access_hash
|
||||
|
||||
if access_hash is None:
|
||||
is_min = True
|
||||
continue
|
||||
|
||||
username = getattr(entity, "username", None)
|
||||
@ -834,87 +836,62 @@ class Client(Methods, BaseClient):
|
||||
if username is not None:
|
||||
self.peers_by_username[username.lower()] = input_peer
|
||||
|
||||
return is_min
|
||||
|
||||
async def download_worker(self):
|
||||
while True:
|
||||
media = await self.download_queue.get()
|
||||
packet = await self.download_queue.get()
|
||||
|
||||
if media is None:
|
||||
if packet is None:
|
||||
break
|
||||
|
||||
temp_file_path = ""
|
||||
final_file_path = ""
|
||||
|
||||
try:
|
||||
media, file_name, done, progress, progress_args, path = media
|
||||
|
||||
file_id = media.file_id
|
||||
size = media.file_size
|
||||
data, file_name, done, progress, progress_args, path = packet
|
||||
|
||||
directory, file_name = os.path.split(file_name)
|
||||
directory = directory or "downloads"
|
||||
|
||||
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 = unpacked[0]
|
||||
dc_id = unpacked[1]
|
||||
id = unpacked[2]
|
||||
access_hash = unpacked[3]
|
||||
volume_id = None
|
||||
secret = None
|
||||
local_id = None
|
||||
media_type_str = Client.MEDIA_TYPE_ID[data.media_type]
|
||||
|
||||
if len(decoded) > 24:
|
||||
volume_id = unpacked[4]
|
||||
secret = unpacked[5]
|
||||
local_id = unpacked[6]
|
||||
if not data.file_name:
|
||||
guessed_extension = self.guess_extension(data.mime_type)
|
||||
|
||||
media_type_str = Client.MEDIA_TYPE_ID.get(media_type, None)
|
||||
|
||||
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):
|
||||
if data.media_type in (0, 1, 2, 14):
|
||||
extension = ".jpg"
|
||||
elif media_type == 3:
|
||||
elif data.media_type == 3:
|
||||
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"
|
||||
elif media_type == 5:
|
||||
elif data.media_type == 5:
|
||||
extension = guessed_extension or ".zip"
|
||||
elif media_type == 8:
|
||||
elif data.media_type == 8:
|
||||
extension = guessed_extension or ".webp"
|
||||
elif media_type == 9:
|
||||
elif data.media_type == 9:
|
||||
extension = guessed_extension or ".mp3"
|
||||
else:
|
||||
continue
|
||||
|
||||
file_name = "{}_{}_{}{}".format(
|
||||
media_type_str,
|
||||
datetime.fromtimestamp(
|
||||
getattr(media, "date", None) or time.time()
|
||||
).strftime("%Y-%m-%d_%H-%M-%S"),
|
||||
datetime.fromtimestamp(data.date or time.time()).strftime("%Y-%m-%d_%H-%M-%S"),
|
||||
self.rnd_id(),
|
||||
extension
|
||||
)
|
||||
|
||||
temp_file_path = await self.get_file(
|
||||
dc_id=dc_id,
|
||||
id=id,
|
||||
access_hash=access_hash,
|
||||
volume_id=volume_id,
|
||||
local_id=local_id,
|
||||
secret=secret,
|
||||
size=size,
|
||||
media_type=data.media_type,
|
||||
dc_id=data.dc_id,
|
||||
file_id=data.file_id,
|
||||
access_hash=data.access_hash,
|
||||
thumb_size=data.thumb_size,
|
||||
peer_id=data.peer_id,
|
||||
volume_id=data.volume_id,
|
||||
local_id=data.local_id,
|
||||
file_size=data.file_size,
|
||||
is_big=data.is_big,
|
||||
progress=progress,
|
||||
progress_args=progress_args
|
||||
)
|
||||
@ -949,8 +926,10 @@ class Client(Methods, BaseClient):
|
||||
|
||||
try:
|
||||
if isinstance(updates, (types.Update, types.UpdatesCombined)):
|
||||
self.fetch_peers(updates.users)
|
||||
self.fetch_peers(updates.chats)
|
||||
is_min = self.fetch_peers(updates.users) or 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:
|
||||
channel_id = getattr(
|
||||
@ -967,7 +946,7 @@ class Client(Methods, BaseClient):
|
||||
if isinstance(update, types.UpdateChannelTooLong):
|
||||
log.warning(update)
|
||||
|
||||
if isinstance(update, types.UpdateNewChannelMessage):
|
||||
if isinstance(update, types.UpdateNewChannelMessage) and is_min:
|
||||
message = update.message
|
||||
|
||||
if not isinstance(message, types.MessageEmpty):
|
||||
@ -989,22 +968,10 @@ class Client(Methods, BaseClient):
|
||||
pass
|
||||
else:
|
||||
if not isinstance(diff, types.updates.ChannelDifferenceEmpty):
|
||||
updates.users += diff.users
|
||||
updates.chats += diff.chats
|
||||
users.update({u.id: u for u in diff.users})
|
||||
chats.update({c.id: c for c in diff.chats})
|
||||
|
||||
if channel_id and pts:
|
||||
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))
|
||||
self.dispatcher.updates_queue.put_nowait((update, users, chats))
|
||||
elif isinstance(updates, (types.UpdateShortMessage, types.UpdateShortChatMessage)):
|
||||
diff = await self.send(
|
||||
functions.updates.GetDifference(
|
||||
@ -1021,13 +988,13 @@ class Client(Methods, BaseClient):
|
||||
pts=updates.pts,
|
||||
pts_count=updates.pts_count
|
||||
),
|
||||
diff.users,
|
||||
diff.chats
|
||||
{u.id: u for u in diff.users},
|
||||
{c.id: c for c in diff.chats}
|
||||
))
|
||||
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):
|
||||
self.dispatcher.updates_queue.put_nowait((updates.update, [], []))
|
||||
self.dispatcher.updates_queue.put_nowait((updates.update, {}, {}))
|
||||
elif isinstance(updates, types.UpdatesTooLong):
|
||||
log.warning(updates)
|
||||
except Exception as e:
|
||||
@ -1333,7 +1300,7 @@ class Client(Methods, BaseClient):
|
||||
return r
|
||||
|
||||
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()
|
||||
offset_date = utils.get_offset_date(dialogs)
|
||||
@ -1575,16 +1542,18 @@ class Client(Methods, BaseClient):
|
||||
for session in pool:
|
||||
await session.stop()
|
||||
|
||||
async def get_file(self,
|
||||
async def get_file(self, media_type: int,
|
||||
dc_id: int,
|
||||
id: int = None,
|
||||
access_hash: int = None,
|
||||
volume_id: int = None,
|
||||
local_id: int = None,
|
||||
secret: int = None,
|
||||
file_id: int,
|
||||
access_hash: int,
|
||||
thumb_size: str,
|
||||
peer_id: int,
|
||||
volume_id: int,
|
||||
local_id: int,
|
||||
file_size: int,
|
||||
|
||||
size: int = None,
|
||||
progress: callable = None,
|
||||
is_big: bool,
|
||||
progress: callable,
|
||||
progress_args: tuple = ()) -> str:
|
||||
with await self.media_sessions_lock:
|
||||
session = self.media_sessions.get(dc_id, None)
|
||||
@ -1626,18 +1595,33 @@ class Client(Methods, BaseClient):
|
||||
|
||||
self.media_sessions[dc_id] = session
|
||||
|
||||
if volume_id: # Photos are accessed by volume_id, local_id, secret
|
||||
location = types.InputFileLocation(
|
||||
if media_type == 1:
|
||||
location = types.InputPeerPhotoFileLocation(
|
||||
peer=self.resolve_peer(peer_id),
|
||||
volume_id=volume_id,
|
||||
local_id=local_id,
|
||||
secret=secret,
|
||||
file_reference=b""
|
||||
big=is_big or None
|
||||
)
|
||||
else: # Any other file can be more easily accessed by id and access_hash
|
||||
location = types.InputDocumentFileLocation(
|
||||
id=id,
|
||||
elif media_type in (0, 2):
|
||||
location = types.InputPhotoFileLocation(
|
||||
id=file_id,
|
||||
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
|
||||
@ -1668,7 +1652,14 @@ class Client(Methods, BaseClient):
|
||||
offset += limit
|
||||
|
||||
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(
|
||||
functions.upload.GetFile(
|
||||
@ -1750,7 +1741,14 @@ class Client(Methods, BaseClient):
|
||||
offset += limit
|
||||
|
||||
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:
|
||||
break
|
||||
|
@ -16,10 +16,11 @@
|
||||
# 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
|
||||
import asyncio
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
from collections import namedtuple
|
||||
|
||||
from pyrogram import __version__
|
||||
from ..style import Markdown, HTML
|
||||
@ -55,7 +56,7 @@ class BaseClient:
|
||||
CONFIG_FILE = "./config.ini"
|
||||
|
||||
MEDIA_TYPE_ID = {
|
||||
0: "thumbnail",
|
||||
0: "photo_thumbnail",
|
||||
1: "chat_photo",
|
||||
2: "photo",
|
||||
3: "voice",
|
||||
@ -64,7 +65,8 @@ class BaseClient:
|
||||
8: "sticker",
|
||||
9: "audio",
|
||||
10: "animation",
|
||||
13: "video_note"
|
||||
13: "video_note",
|
||||
14: "document_thumbnail"
|
||||
}
|
||||
|
||||
mime_types_to_extensions = {}
|
||||
@ -81,6 +83,10 @@ class BaseClient:
|
||||
|
||||
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):
|
||||
self.is_bot = None
|
||||
self.dc_id = None
|
||||
@ -89,7 +95,6 @@ class BaseClient:
|
||||
self.date = None
|
||||
|
||||
self.rnd_id = MsgId
|
||||
self.channels_pts = {}
|
||||
|
||||
self.peers_by_id = {}
|
||||
self.peers_by_username = {}
|
||||
@ -152,3 +157,6 @@ class BaseClient:
|
||||
|
||||
def guess_extension(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def get_profile_photos(self, *args, **kwargs):
|
||||
pass
|
||||
|
@ -124,16 +124,13 @@ class Dispatcher:
|
||||
|
||||
async def update_worker(self):
|
||||
while True:
|
||||
update = await self.updates_queue.get()
|
||||
packet = await self.updates_queue.get()
|
||||
|
||||
if update is None:
|
||||
if packet is None:
|
||||
break
|
||||
|
||||
try:
|
||||
users = {i.id: i for i in update[1]}
|
||||
chats = {i.id: i for i in update[2]}
|
||||
update = update[0]
|
||||
|
||||
update, users, chats = packet
|
||||
parser = self.update_parsers.get(type(update), None)
|
||||
|
||||
parsed_update, handler_type = (
|
||||
|
@ -1853,3 +1853,6 @@ video/x-msvideo avi
|
||||
video/x-sgi-movie movie
|
||||
video/x-smv smv
|
||||
x-conference/x-cooltalk ice
|
||||
|
||||
# Telegram animated stickers
|
||||
application/x-tgsticker tgs
|
@ -92,7 +92,7 @@ class Syncer:
|
||||
auth_key=auth_key,
|
||||
user_id=client.user_id,
|
||||
date=int(time.time()),
|
||||
is_bot=client.is_bot,
|
||||
is_bot=bool(client.is_bot),
|
||||
peers_by_id={
|
||||
k: getattr(v, "access_hash", None)
|
||||
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/>.
|
||||
|
||||
import asyncio
|
||||
import struct
|
||||
import sys
|
||||
from base64 import b64decode, b64encode
|
||||
from concurrent.futures.thread import ThreadPoolExecutor
|
||||
from typing import Union
|
||||
|
||||
from . import BaseClient
|
||||
from ...api import types
|
||||
|
||||
|
||||
@ -94,3 +97,53 @@ def get_offset_date(dialogs):
|
||||
return m.date
|
||||
else:
|
||||
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*):
|
||||
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
|
||||
d = {"__call__": func}
|
||||
@ -56,7 +56,7 @@ class Filters:
|
||||
|
||||
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
|
||||
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
|
||||
@ -219,7 +219,7 @@ class Filters:
|
||||
The command or list of commands as string the filter should look for.
|
||||
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*
|
||||
field of the :class:`Message`.
|
||||
field of the :obj:`Message`.
|
||||
|
||||
prefix (``str`` | ``list``, *optional*):
|
||||
A prefix or a list of prefixes as string the filter should look for.
|
||||
@ -263,7 +263,7 @@ class Filters:
|
||||
pattern (``str``):
|
||||
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>`_
|
||||
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*):
|
||||
RegEx flags.
|
||||
@ -339,4 +339,15 @@ class Filters:
|
||||
and message.from_user.is_self
|
||||
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))
|
||||
|
@ -21,10 +21,10 @@ from .handler import Handler
|
||||
|
||||
class CallbackQueryHandler(Handler):
|
||||
"""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
|
||||
:meth:`on_callback_query() <pyrogram.Client.on_callback_query>` decorator.
|
||||
:meth:`~Client.on_callback_query` decorator.
|
||||
|
||||
Parameters:
|
||||
callback (``callable``):
|
||||
|
@ -22,10 +22,10 @@ from .handler import Handler
|
||||
class DeletedMessagesHandler(Handler):
|
||||
"""The deleted Messages handler class. Used to handle deleted messages coming from any chat
|
||||
(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
|
||||
:meth:`on_deleted_messages() <pyrogram.Client.on_deleted_messages>` decorator.
|
||||
:meth:`~Client.on_deleted_messages` decorator.
|
||||
|
||||
Parameters:
|
||||
callback (``callable``):
|
||||
|
@ -21,10 +21,10 @@ from .handler import Handler
|
||||
|
||||
class DisconnectHandler(Handler):
|
||||
"""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
|
||||
:meth:`on_disconnect() <pyrogram.Client.on_disconnect>` decorator.
|
||||
:meth:`~Client.on_disconnect` decorator.
|
||||
|
||||
Parameters:
|
||||
callback (``callable``):
|
||||
|
@ -21,10 +21,10 @@ from .handler import Handler
|
||||
|
||||
class InlineQueryHandler(Handler):
|
||||
"""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
|
||||
:meth:`on_inline_query() <pyrogram.Client.on_inline_query>` decorator.
|
||||
:meth:`~Client.on_inline_query` decorator.
|
||||
|
||||
Parameters:
|
||||
callback (``callable``):
|
||||
|
@ -21,11 +21,10 @@ from .handler import Handler
|
||||
|
||||
class MessageHandler(Handler):
|
||||
"""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
|
||||
:meth:`add_handler() <pyrogram.Client.add_handler>`
|
||||
any chat (private, group, channel). It is intended to be used with :meth:`~Client.add_handler`
|
||||
|
||||
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:
|
||||
callback (``callable``):
|
||||
|
@ -22,25 +22,25 @@ from .handler import Handler
|
||||
class PollHandler(Handler):
|
||||
"""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
|
||||
:meth:`on_poll() <pyrogram.Client.on_poll>` decorator.
|
||||
:meth:`~Client.on_poll` decorator.
|
||||
|
||||
Parameters:
|
||||
callback (``callable``):
|
||||
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).
|
||||
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
filters (:obj:`Filters`):
|
||||
Pass one or more filters to allow only a subset of polls to be passed
|
||||
in your callback function.
|
||||
|
||||
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.
|
||||
|
||||
poll (:obj:`Poll <pyrogram.Poll>`):
|
||||
poll (:obj:`Poll`):
|
||||
The received poll.
|
||||
"""
|
||||
|
||||
|
@ -21,10 +21,10 @@ from .handler import Handler
|
||||
|
||||
class RawUpdateHandler(Handler):
|
||||
"""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
|
||||
:meth:`on_raw_update() <pyrogram.Client.on_raw_update>` decorator.
|
||||
:meth:`~Client.on_raw_update` decorator.
|
||||
|
||||
Parameters:
|
||||
callback (``callable``):
|
||||
@ -33,7 +33,7 @@ class RawUpdateHandler(Handler):
|
||||
a detailed description).
|
||||
|
||||
Other Parameters:
|
||||
client (:class:`Client`):
|
||||
client (:obj:`Client`):
|
||||
The Client itself, useful when you want to call other API methods inside the update handler.
|
||||
|
||||
update (``Update``):
|
||||
|
@ -21,10 +21,10 @@ from .handler import Handler
|
||||
|
||||
class UserStatusHandler(Handler):
|
||||
"""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
|
||||
:meth:`on_user_status() <pyrogram.Client.on_user_status>` decorator.
|
||||
:meth:`~Client.on_user_status` decorator.
|
||||
|
||||
Parameters:
|
||||
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
|
||||
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.
|
||||
If your bot needs to generate a new invite link replacing its previous one, use this method again.
|
||||
using this method – after this the link will become available to the bot via the :meth:`~Client.get_chat`
|
||||
method. If your bot needs to generate a new invite link replacing its previous one, use this method again.
|
||||
|
||||
Parameters:
|
||||
chat_id (``int`` | ``str``):
|
||||
|
@ -51,7 +51,7 @@ class GetChatMembers(BaseClient):
|
||||
You can get up to 200 chat members at once.
|
||||
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").
|
||||
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:
|
||||
chat_id (``int`` | ``str``):
|
||||
|
@ -37,7 +37,7 @@ class GetDialogs(BaseClient):
|
||||
"""Get a chunk of the user's dialogs.
|
||||
|
||||
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:
|
||||
offset_date (``int``):
|
||||
@ -62,7 +62,7 @@ class GetDialogs(BaseClient):
|
||||
while True:
|
||||
try:
|
||||
if pinned_only:
|
||||
r = await self.send(functions.messages.GetPinnedDialogs())
|
||||
r = await self.send(functions.messages.GetPinnedDialogs(folder_id=0))
|
||||
else:
|
||||
r = await self.send(
|
||||
functions.messages.GetDialogs(
|
||||
|
@ -36,7 +36,7 @@ class GetDialogsCount(BaseClient):
|
||||
"""
|
||||
|
||||
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:
|
||||
r = await self.send(
|
||||
functions.messages.GetDialogs(
|
||||
|
@ -50,7 +50,7 @@ class IterChatMembers(BaseClient):
|
||||
) -> Optional[AsyncGenerator["pyrogram.ChatMember", None]]:
|
||||
"""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
|
||||
a single call.
|
||||
|
||||
|
@ -29,12 +29,13 @@ class IterDialogs(BaseClient):
|
||||
async def iter_dialogs(
|
||||
self,
|
||||
limit: int = 0,
|
||||
offset_date: int = 0
|
||||
offset_date: int = None
|
||||
) -> Optional[AsyncGenerator["pyrogram.Dialog", None]]:
|
||||
"""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
|
||||
the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a single call.
|
||||
This convenience method does the same as repeatedly calling :meth:`~Client.get_dialogs` in a loop, thus saving
|
||||
you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a
|
||||
single call.
|
||||
|
||||
Parameters:
|
||||
limit (``str``, *optional*):
|
||||
|
@ -44,14 +44,14 @@ class SetChatPhoto(BaseClient):
|
||||
Unique identifier (int) or username (str) of the target chat.
|
||||
|
||||
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:
|
||||
``bool``: True on success.
|
||||
|
||||
Raises:
|
||||
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)
|
||||
|
||||
|
@ -30,7 +30,7 @@ class UpdateChatUsername(BaseClient):
|
||||
) -> bool:
|
||||
"""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:
|
||||
chat_id (``int`` | ``str``)
|
||||
|
@ -32,7 +32,7 @@ class OnCallbackQuery(BaseClient):
|
||||
) -> callable:
|
||||
"""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:
|
||||
filters (:obj:`Filters`):
|
||||
|
@ -32,7 +32,7 @@ class OnDeletedMessages(BaseClient):
|
||||
) -> callable:
|
||||
"""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:
|
||||
filters (:obj:`Filters`):
|
||||
|
@ -25,7 +25,7 @@ class OnDisconnect(BaseClient):
|
||||
def on_disconnect(self=None) -> callable:
|
||||
"""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:
|
||||
|
@ -32,7 +32,7 @@ class OnInlineQuery(BaseClient):
|
||||
) -> callable:
|
||||
"""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:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
|
@ -32,7 +32,7 @@ class OnMessage(BaseClient):
|
||||
) -> callable:
|
||||
"""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:
|
||||
filters (:obj:`Filters`):
|
||||
|
@ -32,10 +32,10 @@ class OnPoll(BaseClient):
|
||||
) -> callable:
|
||||
"""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:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
filters (:obj:`Filters`):
|
||||
Pass one or more filters to allow only a subset of polls to be passed
|
||||
in your function.
|
||||
|
||||
|
@ -30,7 +30,7 @@ class OnRawUpdate(BaseClient):
|
||||
) -> callable:
|
||||
"""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:
|
||||
group (``int``, *optional*):
|
||||
|
@ -31,7 +31,7 @@ class OnUserStatus(BaseClient):
|
||||
group: int = 0
|
||||
) -> callable:
|
||||
"""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:
|
||||
filters (:obj:`Filters`):
|
||||
|
@ -28,6 +28,7 @@ from .get_history_count import GetHistoryCount
|
||||
from .get_messages import GetMessages
|
||||
from .iter_history import IterHistory
|
||||
from .retract_vote import RetractVote
|
||||
from .send_animated_sticker import SendAnimatedSticker
|
||||
from .send_animation import SendAnimation
|
||||
from .send_audio import SendAudio
|
||||
from .send_cached_media import SendCachedMedia
|
||||
@ -78,6 +79,7 @@ class Messages(
|
||||
DownloadMedia,
|
||||
IterHistory,
|
||||
SendCachedMedia,
|
||||
GetHistoryCount
|
||||
GetHistoryCount,
|
||||
SendAnimatedSticker
|
||||
):
|
||||
pass
|
||||
|
@ -17,10 +17,13 @@
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import binascii
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.client.ext import BaseClient
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FileIdInvalid
|
||||
|
||||
|
||||
class DownloadMedia(BaseClient):
|
||||
@ -74,74 +77,98 @@ class DownloadMedia(BaseClient):
|
||||
|
||||
Returns:
|
||||
``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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
``ValueError`` if the 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 message.photo:
|
||||
media = pyrogram.Document(
|
||||
file_id=message.photo.sizes[-1].file_id,
|
||||
file_size=message.photo.sizes[-1].file_size,
|
||||
mime_type="",
|
||||
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
|
||||
for kind in available_media:
|
||||
media = getattr(message, kind, None)
|
||||
|
||||
if media is not None:
|
||||
break
|
||||
else:
|
||||
raise ValueError(error_message)
|
||||
elif isinstance(message, (
|
||||
pyrogram.Photo,
|
||||
pyrogram.PhotoSize,
|
||||
pyrogram.Audio,
|
||||
pyrogram.Document,
|
||||
pyrogram.Video,
|
||||
pyrogram.Voice,
|
||||
pyrogram.VideoNote,
|
||||
pyrogram.Sticker,
|
||||
pyrogram.Animation
|
||||
)):
|
||||
if isinstance(message, pyrogram.Photo):
|
||||
media = pyrogram.Document(
|
||||
file_id=message.sizes[-1].file_id,
|
||||
file_size=message.sizes[-1].file_size,
|
||||
mime_type="",
|
||||
date=message.date,
|
||||
client=self
|
||||
)
|
||||
else:
|
||||
media = message
|
||||
elif isinstance(message, str):
|
||||
media = pyrogram.Document(
|
||||
file_id=message,
|
||||
file_size=0,
|
||||
mime_type="",
|
||||
client=self
|
||||
|
||||
if isinstance(media, str):
|
||||
file_id_str = media
|
||||
else:
|
||||
file_id_str = media.file_id
|
||||
file_name = getattr(media, "file_name", "")
|
||||
file_size = getattr(media, "file_size", None)
|
||||
mime_type = getattr(media, "mime_type", None)
|
||||
date = getattr(media, "date", None)
|
||||
|
||||
data = self.FileData(
|
||||
file_name=file_name,
|
||||
file_size=file_size,
|
||||
mime_type=mime_type,
|
||||
date=date
|
||||
)
|
||||
|
||||
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:
|
||||
raise ValueError(error_message)
|
||||
raise ValueError("Unknown media type: {}".format(file_id_str))
|
||||
except (AssertionError, binascii.Error, struct.error):
|
||||
raise FileIdInvalid from None
|
||||
|
||||
done = asyncio.Event()
|
||||
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:
|
||||
await done.wait()
|
||||
|
@ -16,14 +16,11 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.client.types import (
|
||||
InputMediaPhoto, InputMediaVideo, InputMediaAudio,
|
||||
@ -94,28 +91,7 @@ class EditMessageMedia(BaseClient):
|
||||
url=media.media
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(media.media, 2)
|
||||
|
||||
if isinstance(media, InputMediaVideo):
|
||||
if os.path.exists(media.media):
|
||||
@ -153,28 +129,7 @@ class EditMessageMedia(BaseClient):
|
||||
url=media.media
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(media.media, 4)
|
||||
|
||||
if isinstance(media, InputMediaAudio):
|
||||
if os.path.exists(media.media):
|
||||
@ -211,28 +166,7 @@ class EditMessageMedia(BaseClient):
|
||||
url=media.media
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(media.media, 9)
|
||||
|
||||
if isinstance(media, InputMediaAnimation):
|
||||
if os.path.exists(media.media):
|
||||
@ -271,28 +205,7 @@ class EditMessageMedia(BaseClient):
|
||||
url=media.media
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(media.media, 10)
|
||||
|
||||
if isinstance(media, InputMediaDocument):
|
||||
if os.path.exists(media.media):
|
||||
@ -324,28 +237,7 @@ class EditMessageMedia(BaseClient):
|
||||
url=media.media
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(media.media, 5)
|
||||
|
||||
r = await self.send(
|
||||
functions.messages.EditMessage(
|
||||
|
@ -41,7 +41,7 @@ class GetHistory(BaseClient):
|
||||
"""Retrieve a chunk of the history of a chat.
|
||||
|
||||
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:
|
||||
chat_id (``int`` | ``str``):
|
||||
|
@ -37,8 +37,9 @@ class IterHistory(BaseClient):
|
||||
) -> Optional[AsyncGenerator["pyrogram.Message", None]]:
|
||||
"""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
|
||||
the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a single call.
|
||||
This convenience method does the same as repeatedly calling :meth:`~Client.get_history` in a loop, thus saving
|
||||
you from the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a
|
||||
single call.
|
||||
|
||||
Parameters:
|
||||
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
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendAnimation(BaseClient):
|
||||
@ -121,7 +119,7 @@ class SendAnimation(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -153,28 +151,7 @@ class SendAnimation(BaseClient):
|
||||
url=animation
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(animation, 10)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendAudio(BaseClient):
|
||||
@ -122,7 +120,7 @@ class SendAudio(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -152,28 +150,7 @@ class SendAudio(BaseClient):
|
||||
url=audio
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(audio, 9)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,13 +16,10 @@
|
||||
# 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 binascii
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid
|
||||
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
|
||||
|
||||
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(
|
||||
functions.messages.SendMedia(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
media=media,
|
||||
media=utils.get_input_media_from_file_id(file_id),
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
random_id=self.rnd_id(),
|
||||
|
@ -16,11 +16,11 @@
|
||||
# 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 json
|
||||
from typing import Union
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.client.ext import BaseClient
|
||||
import json
|
||||
|
||||
|
||||
class ChatAction:
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendDocument(BaseClient):
|
||||
@ -108,7 +106,7 @@ class SendDocument(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -133,28 +131,7 @@ class SendDocument(BaseClient):
|
||||
url=document
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(document, 5)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,17 +16,15 @@
|
||||
# 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 binascii
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import struct
|
||||
from typing import Union, List
|
||||
import asyncio
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FloodWait
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FloodWait
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -96,28 +94,7 @@ class SendMediaGroup(BaseClient):
|
||||
)
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(i.media, 2)
|
||||
elif isinstance(i, pyrogram.InputMediaVideo):
|
||||
if os.path.exists(i.media):
|
||||
while True:
|
||||
@ -155,28 +132,7 @@ class SendMediaGroup(BaseClient):
|
||||
)
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(i.media, 4)
|
||||
|
||||
multi_media.append(
|
||||
types.InputSingleMedia(
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendPhoto(BaseClient):
|
||||
@ -108,7 +106,7 @@ class SendPhoto(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -129,29 +127,7 @@ class SendPhoto(BaseClient):
|
||||
ttl_seconds=ttl_seconds
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(photo, 2)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendSticker(BaseClient):
|
||||
@ -93,7 +91,7 @@ class SendSticker(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
"""
|
||||
@ -114,28 +112,7 @@ class SendSticker(BaseClient):
|
||||
url=sticker
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(sticker, 8)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendVideo(BaseClient):
|
||||
@ -125,7 +123,7 @@ class SendVideo(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -156,28 +154,7 @@ class SendVideo(BaseClient):
|
||||
url=video
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(video, 4)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendVideoNote(BaseClient):
|
||||
@ -108,7 +106,7 @@ class SendVideoNote(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -133,28 +131,7 @@ class SendVideoNote(BaseClient):
|
||||
]
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(video_note, 13)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,15 +16,13 @@
|
||||
# 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 binascii
|
||||
import os
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.errors import FilePartMissing
|
||||
|
||||
|
||||
class SendVoice(BaseClient):
|
||||
@ -106,7 +104,7 @@ class SendVoice(BaseClient):
|
||||
|
||||
Returns:
|
||||
: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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
@ -132,28 +130,7 @@ class SendVoice(BaseClient):
|
||||
url=voice
|
||||
)
|
||||
else:
|
||||
try:
|
||||
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""
|
||||
)
|
||||
)
|
||||
media = utils.get_input_media_from_file_id(voice, 3)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
@ -16,22 +16,26 @@
|
||||
# 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 .delete_user_profile_photos import DeleteUserProfilePhotos
|
||||
from .delete_profile_photos import DeleteProfilePhotos
|
||||
from .get_me import GetMe
|
||||
from .get_user_profile_photos import GetUserProfilePhotos
|
||||
from .get_user_profile_photos_count import GetUserProfilePhotosCount
|
||||
from .get_profile_photos import GetProfilePhotos
|
||||
from .get_profile_photos_count import GetProfilePhotosCount
|
||||
from .get_user_dc import GetUserDC
|
||||
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
|
||||
|
||||
|
||||
class Users(
|
||||
GetUserProfilePhotos,
|
||||
SetUserProfilePhoto,
|
||||
DeleteUserProfilePhotos,
|
||||
GetProfilePhotos,
|
||||
SetProfilePhoto,
|
||||
DeleteProfilePhotos,
|
||||
GetUsers,
|
||||
GetMe,
|
||||
UpdateUsername,
|
||||
GetUserProfilePhotosCount
|
||||
GetProfilePhotosCount,
|
||||
GetUserDC,
|
||||
IterProfilePhotos
|
||||
):
|
||||
pass
|
||||
|
@ -24,8 +24,8 @@ from pyrogram.api import functions, types
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class DeleteUserProfilePhotos(BaseClient):
|
||||
async def delete_user_profile_photos(
|
||||
class DeleteProfilePhotos(BaseClient):
|
||||
async def delete_profile_photos(
|
||||
self,
|
||||
id: Union[str, List[str]]
|
||||
) -> 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 pyrogram.api import functions, types
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetUserProfilePhotosCount(BaseClient):
|
||||
async def get_user_profile_photos_count(self, user_id: Union[int, str]) -> int:
|
||||
class GetProfilePhotosCount(BaseClient):
|
||||
async def get_profile_photos_count(self, chat_id: Union[int, str]) -> int:
|
||||
"""Get the total count of profile pictures for a user.
|
||||
|
||||
Parameters:
|
||||
user_id (``int`` | ``str``):
|
||||
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).
|
||||
@ -39,16 +38,4 @@ class GetUserProfilePhotosCount(BaseClient):
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
"""
|
||||
|
||||
r = await self.send(
|
||||
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
|
||||
return await self.get_profile_photos(chat_id, limit=1).total_count
|
@ -18,19 +18,13 @@
|
||||
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions
|
||||
from pyrogram.api import functions, types
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetUserProfilePhotos(BaseClient):
|
||||
async def get_user_profile_photos(
|
||||
self,
|
||||
user_id: Union[int, str],
|
||||
offset: int = 0,
|
||||
limit: int = 100
|
||||
) -> "pyrogram.UserProfilePhotos":
|
||||
"""Get a list of profile pictures for a user.
|
||||
class GetUserDC(BaseClient):
|
||||
async def get_user_dc(self, user_id: Union[int, str]) -> Union[int, None]:
|
||||
"""Get the assigned data center (DC) of a user.
|
||||
|
||||
Parameters:
|
||||
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 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:`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:
|
||||
RPCError: In case of a Telegram RPC error.
|
||||
"""
|
||||
return pyrogram.UserProfilePhotos._parse(
|
||||
self,
|
||||
await self.send(
|
||||
functions.photos.GetUserPhotos(
|
||||
user_id=await self.resolve_peer(user_id),
|
||||
offset=offset,
|
||||
max_id=0,
|
||||
limit=limit
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
r = await self.send(functions.users.GetUsers(id=[await self.resolve_peer(user_id)]))
|
||||
|
||||
if r:
|
||||
r = r[0]
|
||||
|
||||
if r.photo:
|
||||
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
|
||||
|
||||
|
||||
class SetUserProfilePhoto(BaseClient):
|
||||
async def set_user_profile_photo(
|
||||
class SetProfilePhoto(BaseClient):
|
||||
async def set_profile_photo(
|
||||
self,
|
||||
photo: str
|
||||
) -> 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
|
||||
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:
|
||||
username (``str`` | ``None``):
|
||||
|
@ -92,7 +92,7 @@ class InlineQuery(PyrogramType, Update):
|
||||
switch_pm_text: 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:
|
||||
|
||||
@ -109,7 +109,7 @@ class InlineQuery(PyrogramType, Update):
|
||||
inline_query.answer([...])
|
||||
|
||||
Parameters:
|
||||
results (List of :obj:`InlineQueryResult <pyrogram.InlineQueryResult>`):
|
||||
results (List of :obj:`InlineQueryResult`):
|
||||
A list of results for the inline query.
|
||||
|
||||
cache_time (``int``, *optional*):
|
||||
|
@ -34,10 +34,10 @@ class InlineQueryResultArticle(InlineQueryResult):
|
||||
title (``str``):
|
||||
Title for the result.
|
||||
|
||||
input_message_content (:obj:`InputMessageContent <pyrogram.InputMessageContent>`):
|
||||
input_message_content (:obj:`InputMessageContent`):
|
||||
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.
|
||||
|
||||
url (``str``, *optional*):
|
||||
|
@ -50,10 +50,10 @@ class InlineQueryResultAudio(PyrogramType):
|
||||
audio_duration (``int`` ``32-bit``, optional):
|
||||
Audio duration in seconds.
|
||||
|
||||
reply_markup (:obj:`InlineKeyboardMarkup <pyrogram.types.InlineKeyboardMarkup>`, optional):
|
||||
reply_markup (:obj:`InlineKeyboardMarkup`, optional):
|
||||
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.
|
||||
|
||||
"""
|
||||
|
@ -47,10 +47,10 @@ class InlineQueryResultCachedDocument(PyrogramType):
|
||||
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.
|
||||
|
||||
reply_markup (:obj:`InlineKeyboardMarkup <pyrogram.types.InlineKeyboardMarkup>`, optional):
|
||||
reply_markup (:obj:`InlineKeyboardMarkup`, optional):
|
||||
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.
|
||||
|
||||
"""
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user