mirror of
https://github.com/pyrogram/pyrogram
synced 2025-09-03 07:45:14 +00:00
Merge branch 'develop' into asyncio
# Conflicts: # pyrogram/__init__.py # pyrogram/client/client.py # pyrogram/client/methods/bots/send_inline_bot_result.py # pyrogram/client/methods/chats/pin_chat_message.py # pyrogram/client/methods/chats/unpin_chat_message.py # pyrogram/client/methods/password/change_cloud_password.py # pyrogram/client/methods/password/enable_cloud_password.py # pyrogram/client/methods/password/remove_cloud_password.py
This commit is contained in:
12
README.rst
12
README.rst
@@ -17,8 +17,8 @@ Pyrogram
|
||||
|
||||
app.run()
|
||||
|
||||
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for building
|
||||
custom Telegram applications that interact with the MTProto API as both User and Bot.
|
||||
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for
|
||||
building custom Telegram applications that interact with the MTProto API as both User and Bot.
|
||||
|
||||
Features
|
||||
--------
|
||||
@@ -26,7 +26,7 @@ Features
|
||||
- **Easy to use**: You can easily install Pyrogram using pip and start building your app right away.
|
||||
- **High-level**: The low-level details of MTProto are abstracted and automatically handled.
|
||||
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
||||
- **Updated** to the latest Telegram API version, currently Layer 82 on top of MTProto 2.0.
|
||||
- **Updated** to the latest Telegram API version, currently Layer 91 on top of MTProto 2.0.
|
||||
- **Documented**: The Pyrogram API is well documented and resembles the Telegram Bot API.
|
||||
- **Full API**, allowing to execute any advanced action an official client is able to do, and more.
|
||||
|
||||
@@ -99,7 +99,7 @@ Copyright & License
|
||||
</a>
|
||||
<br>
|
||||
<a href="compiler/api/source/main_api.tl">
|
||||
<img src="https://img.shields.io/badge/schema-layer%2082-eda738.svg?longCache=true&colorA=262b30"
|
||||
<img src="https://img.shields.io/badge/schema-layer%2091-eda738.svg?longCache=true&colorA=262b30"
|
||||
alt="Schema Layer">
|
||||
</a>
|
||||
<a href="https://github.com/pyrogram/tgcrypto">
|
||||
@@ -114,10 +114,10 @@ Copyright & License
|
||||
|
||||
.. |description| replace:: **Telegram MTProto API Client Library for Python**
|
||||
|
||||
.. |scheme| image:: "https://img.shields.io/badge/SCHEME-LAYER%2082-eda738.svg?longCache=true&style=for-the-badge&colorA=262b30"
|
||||
.. |scheme| image:: "https://img.shields.io/badge/schema-layer%2091-eda738.svg?longCache=true&colorA=262b30"
|
||||
:target: compiler/api/source/main_api.tl
|
||||
:alt: Scheme Layer
|
||||
|
||||
.. |tgcrypto| image:: "https://img.shields.io/badge/TGCRYPTO-V1.1.1-eda738.svg?longCache=true&style=for-the-badge&colorA=262b30"
|
||||
.. |tgcrypto| image:: "https://img.shields.io/badge/tgcrypto-v1.1.1-eda738.svg?longCache=true&colorA=262b30"
|
||||
:target: https://github.com/pyrogram/tgcrypto
|
||||
:alt: TgCrypto
|
||||
|
@@ -45,7 +45,8 @@ inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = In
|
||||
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
||||
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
|
||||
inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
|
||||
inputMediaGeoLive#7b1a118f geo_point:InputGeoPoint period:int = InputMedia;
|
||||
inputMediaGeoLive#ce4e82fd flags:# stopped:flags.0?true geo_point:InputGeoPoint period:flags.1?int = InputMedia;
|
||||
inputMediaPoll#6b3765b poll:Poll = InputMedia;
|
||||
|
||||
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
|
||||
inputChatUploadedPhoto#927c55b4 file:InputFile = InputChatPhoto;
|
||||
@@ -55,16 +56,14 @@ inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
|
||||
inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
|
||||
|
||||
inputPhotoEmpty#1cd7bf0d = InputPhoto;
|
||||
inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
|
||||
inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
|
||||
|
||||
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
|
||||
inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
|
||||
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
|
||||
inputDocumentFileLocation#430f0724 id:long access_hash:long version:int = InputFileLocation;
|
||||
inputDocumentFileLocation#196683d9 id:long access_hash:long file_reference:bytes = InputFileLocation;
|
||||
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
|
||||
inputTakeoutFileLocation#29be5899 = InputFileLocation;
|
||||
|
||||
inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent;
|
||||
|
||||
peerUser#9db1bc6d user_id:int = Peer;
|
||||
peerChat#bad0e5bb chat_id:int = Peer;
|
||||
peerChannel#bddde532 channel_id:int = Peer;
|
||||
@@ -81,7 +80,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
|
||||
storage.fileWebp#1081464c = storage.FileType;
|
||||
|
||||
fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
|
||||
fileLocation#53d69076 dc_id:int 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 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;
|
||||
@@ -102,8 +101,8 @@ chatForbidden#7328bdb id:int title:string = Chat;
|
||||
channel#c88974ac flags:# creator:flags.0?true left:flags.2?true editor:flags.3?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true democracy:flags.10?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?ChannelAdminRights banned_rights:flags.15?ChannelBannedRights 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#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> = ChatFull;
|
||||
channelFull#76af5481 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?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 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#edd2a791 flags:# id:int 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;
|
||||
|
||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
||||
@@ -116,7 +115,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = 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 id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
|
||||
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true 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;
|
||||
|
||||
messageMediaEmpty#3ded6320 = MessageMedia;
|
||||
@@ -130,6 +129,7 @@ messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:str
|
||||
messageMediaGame#fdb19008 game:Game = MessageMedia;
|
||||
messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
|
||||
messageMediaGeoLive#7c3c2609 geo:GeoPoint period:int = MessageMedia;
|
||||
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
|
||||
|
||||
messageActionEmpty#b6aef7b0 = MessageAction;
|
||||
messageActionChatCreate#a6638b9a title:string users:Vector<int> = MessageAction;
|
||||
@@ -153,11 +153,12 @@ messageActionCustomAction#fae69f56 message:string = MessageAction;
|
||||
messageActionBotAllowed#abe9affe domain:string = MessageAction;
|
||||
messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:SecureCredentialsEncrypted = MessageAction;
|
||||
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;
|
||||
|
||||
photoEmpty#2331b22d id:long = Photo;
|
||||
photo#9288dd29 flags:# has_stickers:flags.0?true id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
|
||||
photo#9c477dd8 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> = Photo;
|
||||
|
||||
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
||||
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
||||
@@ -177,6 +178,7 @@ auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorizat
|
||||
inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
|
||||
inputNotifyUsers#193b4417 = InputNotifyPeer;
|
||||
inputNotifyChats#4a95e84e = InputNotifyPeer;
|
||||
inputNotifyBroadcasts#b1db7c7e = InputNotifyPeer;
|
||||
|
||||
inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = InputPeerNotifySettings;
|
||||
|
||||
@@ -190,9 +192,11 @@ wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper;
|
||||
inputReportReasonSpam#58dbcab8 = ReportReason;
|
||||
inputReportReasonViolence#1e22c78d = ReportReason;
|
||||
inputReportReasonPornography#2e59d922 = ReportReason;
|
||||
inputReportReasonChildAbuse#adf44ee3 = ReportReason;
|
||||
inputReportReasonOther#e1746d0a text:string = ReportReason;
|
||||
inputReportReasonCopyright#9b89f93a = ReportReason;
|
||||
|
||||
userFull#f220f3f flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo common_chats_count:int = UserFull;
|
||||
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;
|
||||
|
||||
contact#f911c994 user_id:int mutual:Bool = Contact;
|
||||
|
||||
@@ -218,7 +222,7 @@ messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
||||
|
||||
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.channelMessages#99262e37 flags:# pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
||||
|
||||
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
|
||||
@@ -254,7 +258,6 @@ updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
||||
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
||||
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
||||
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
|
||||
updateContactRegistered#2575bbb9 user_id:int date:int = Update;
|
||||
updateContactLink#9d2e67c5 user_id:int my_link:ContactLink foreign_link:ContactLink = Update;
|
||||
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
|
||||
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
|
||||
@@ -305,13 +308,16 @@ updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Upd
|
||||
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
|
||||
updateBotPrecheckoutQuery#5d2f3aa9 flags:# query_id:long user_id:int payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string currency:string total_amount:long = Update;
|
||||
updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
|
||||
updateLangPackTooLong#10c2404b = Update;
|
||||
updateLangPackTooLong#46560264 lang_code:string = Update;
|
||||
updateLangPack#56022f4d difference:LangPackDifference = Update;
|
||||
updateFavedStickers#e511996d = Update;
|
||||
updateChannelReadMessagesContents#89893b45 channel_id:int messages:Vector<int> = Update;
|
||||
updateContactsReset#7084a7be = Update;
|
||||
updateChannelAvailableMessages#70db6837 channel_id:int available_min_id:int = Update;
|
||||
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
||||
updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
|
||||
updateChatPinnedMessage#22893b26 chat_id:int id:int = Update;
|
||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@@ -338,11 +344,11 @@ 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#3213dbba 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 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 = Config;
|
||||
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;
|
||||
|
||||
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
|
||||
|
||||
help.appUpdate#8987f311 id:int critical:Bool url:string text:string = help.AppUpdate;
|
||||
help.appUpdate#1da7158f flags:# popup:flags.0?true id:int version:string text:string entities:Vector<MessageEntity> document:flags.1?Document url:flags.2?string = help.AppUpdate;
|
||||
help.noAppUpdate#c45a6536 = help.AppUpdate;
|
||||
|
||||
help.inviteText#18cb9f78 message:string = help.InviteText;
|
||||
@@ -373,16 +379,17 @@ messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage;
|
||||
messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage;
|
||||
|
||||
inputDocumentEmpty#72f0eaae = InputDocument;
|
||||
inputDocument#18798952 id:long access_hash:long = InputDocument;
|
||||
inputDocument#1abfb575 id:long access_hash:long file_reference:bytes = InputDocument;
|
||||
|
||||
documentEmpty#36f8c871 id:long = Document;
|
||||
document#87232bc7 id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int version:int attributes:Vector<DocumentAttribute> = Document;
|
||||
document#59534e4c id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
|
||||
|
||||
help.support#17c6b5f6 phone_number:string user:User = help.Support;
|
||||
|
||||
notifyPeer#9fd40bd8 peer:Peer = NotifyPeer;
|
||||
notifyUsers#b4c83b4c = NotifyPeer;
|
||||
notifyChats#c007cec3 = NotifyPeer;
|
||||
notifyBroadcasts#d612e8ef = NotifyPeer;
|
||||
|
||||
sendMessageTypingAction#16bf744e = SendMessageAction;
|
||||
sendMessageCancelAction#fd5ec8f5 = SendMessageAction;
|
||||
@@ -403,10 +410,12 @@ contacts.found#b3134d9d my_results:Vector<Peer> results:Vector<Peer> chats:Vecto
|
||||
inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
|
||||
inputPrivacyKeyChatInvite#bdfb0426 = InputPrivacyKey;
|
||||
inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
|
||||
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
||||
|
||||
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
||||
privacyKeyPhoneCall#3d662b7b = PrivacyKey;
|
||||
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
||||
|
||||
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||
@@ -454,16 +463,15 @@ webPagePending#c586da1c id:long date:int = WebPage;
|
||||
webPage#5f07b4bc flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page = WebPage;
|
||||
webPageNotModified#85849473 = WebPage;
|
||||
|
||||
authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
|
||||
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
|
||||
|
||||
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
|
||||
|
||||
account.noPassword#5ea182f6 new_salt:bytes new_secure_salt:bytes secure_random:bytes email_unconfirmed_pattern:string = account.Password;
|
||||
account.password#ca39b447 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true current_salt:bytes new_salt:bytes new_secure_salt:bytes secure_random:bytes hint:string email_unconfirmed_pattern:string = account.Password;
|
||||
account.password#ad2641f8 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes = account.Password;
|
||||
|
||||
account.passwordSettings#7bd9c3f1 email:string secure_salt:bytes secure_secret:bytes secure_secret_id:long = account.PasswordSettings;
|
||||
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
|
||||
|
||||
account.passwordInputSettings#21ffa60d flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_salt:flags.2?bytes new_secure_secret:flags.2?bytes new_secure_secret_id:flags.2?long = account.PasswordInputSettings;
|
||||
account.passwordInputSettings#c23727c9 flags:# new_algo:flags.0?PasswordKdfAlgo new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_settings:flags.2?SecureSecretSettings = account.PasswordInputSettings;
|
||||
|
||||
auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
|
||||
|
||||
@@ -663,6 +671,12 @@ textFixed#6c3f19b9 text:RichText = RichText;
|
||||
textUrl#3c2884c1 text:RichText url:string webpage_id:long = RichText;
|
||||
textEmail#de5a0dd6 text:RichText email:string = RichText;
|
||||
textConcat#7e6260d7 texts:Vector<RichText> = RichText;
|
||||
textSubscript#ed6a8504 text:RichText = RichText;
|
||||
textSuperscript#c7fb5e01 text:RichText = RichText;
|
||||
textMarked#34b8621 text:RichText = RichText;
|
||||
textPhone#1ccb966a text:RichText phone:string = RichText;
|
||||
textImage#81ccf4f document_id:long w:int h:int = RichText;
|
||||
textAnchor#35553762 text:RichText name:string = RichText;
|
||||
|
||||
pageBlockUnsupported#13567e8a = PageBlock;
|
||||
pageBlockTitle#70abc3fd text:RichText = PageBlock;
|
||||
@@ -675,21 +689,24 @@ pageBlockPreformatted#c070d93e text:RichText language:string = PageBlock;
|
||||
pageBlockFooter#48870999 text:RichText = PageBlock;
|
||||
pageBlockDivider#db20b188 = PageBlock;
|
||||
pageBlockAnchor#ce0d37b0 name:string = PageBlock;
|
||||
pageBlockList#3a58c7f4 ordered:Bool items:Vector<RichText> = PageBlock;
|
||||
pageBlockList#e4e88011 items:Vector<PageListItem> = PageBlock;
|
||||
pageBlockBlockquote#263d7c26 text:RichText caption:RichText = PageBlock;
|
||||
pageBlockPullquote#4f4456d3 text:RichText caption:RichText = PageBlock;
|
||||
pageBlockPhoto#e9c69982 photo_id:long caption:RichText = PageBlock;
|
||||
pageBlockVideo#d9d71866 flags:# autoplay:flags.0?true loop:flags.1?true video_id:long caption:RichText = PageBlock;
|
||||
pageBlockPhoto#1759c560 flags:# photo_id:long caption:PageCaption url:flags.0?string webpage_id:flags.0?long = PageBlock;
|
||||
pageBlockVideo#7c8fe7b6 flags:# autoplay:flags.0?true loop:flags.1?true video_id:long caption:PageCaption = PageBlock;
|
||||
pageBlockCover#39f23300 cover:PageBlock = PageBlock;
|
||||
pageBlockEmbed#cde200d1 flags:# full_width:flags.0?true allow_scrolling:flags.3?true url:flags.1?string html:flags.2?string poster_photo_id:flags.4?long w:int h:int caption:RichText = PageBlock;
|
||||
pageBlockEmbedPost#292c7be9 url:string webpage_id:long author_photo_id:long author:string date:int blocks:Vector<PageBlock> caption:RichText = PageBlock;
|
||||
pageBlockCollage#8b31c4f items:Vector<PageBlock> caption:RichText = PageBlock;
|
||||
pageBlockSlideshow#130c8963 items:Vector<PageBlock> caption:RichText = PageBlock;
|
||||
pageBlockEmbed#a8718dc5 flags:# full_width:flags.0?true allow_scrolling:flags.3?true url:flags.1?string html:flags.2?string poster_photo_id:flags.4?long w:flags.5?int h:flags.5?int caption:PageCaption = PageBlock;
|
||||
pageBlockEmbedPost#f259a80b url:string webpage_id:long author_photo_id:long author:string date:int blocks:Vector<PageBlock> caption:PageCaption = PageBlock;
|
||||
pageBlockCollage#65a0fa4d items:Vector<PageBlock> caption:PageCaption = PageBlock;
|
||||
pageBlockSlideshow#31f9590 items:Vector<PageBlock> caption:PageCaption = PageBlock;
|
||||
pageBlockChannel#ef1751b5 channel:Chat = PageBlock;
|
||||
pageBlockAudio#31b81a7f audio_id:long caption:RichText = PageBlock;
|
||||
|
||||
pagePart#8e3f9ebe blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
|
||||
pageFull#556ec7aa blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
|
||||
pageBlockAudio#804361ea audio_id:long caption:PageCaption = PageBlock;
|
||||
pageBlockKicker#1e148390 text:RichText = PageBlock;
|
||||
pageBlockTable#bf4dea82 flags:# bordered:flags.0?true striped:flags.1?true title:RichText rows:Vector<PageTableRow> = PageBlock;
|
||||
pageBlockOrderedList#9a8ae1e1 items:Vector<PageListOrderedItem> = PageBlock;
|
||||
pageBlockDetails#76768bed flags:# open:flags.0?true blocks:Vector<PageBlock> title:RichText = PageBlock;
|
||||
pageBlockRelatedArticles#16115a96 title:RichText articles:Vector<PageRelatedArticle> = PageBlock;
|
||||
pageBlockMap#a44f3ef6 geo:GeoPoint zoom:int w:int h:int caption:PageCaption = PageBlock;
|
||||
|
||||
phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason;
|
||||
phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason;
|
||||
@@ -748,7 +765,7 @@ 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#ffe6ab67 id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connection:PhoneConnection alternative_connections:Vector<PhoneConnection> start_date:int = PhoneCall;
|
||||
phoneCall#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;
|
||||
|
||||
phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
|
||||
@@ -770,7 +787,7 @@ langPackStringDeleted#2979eeb2 key:string = LangPackString;
|
||||
|
||||
langPackDifference#f385c1f6 lang_code:string from_version:int version:int strings:Vector<LangPackString> = LangPackDifference;
|
||||
|
||||
langPackLanguage#117698f1 name:string native_name:string lang_code:string = LangPackLanguage;
|
||||
langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:flags.3?true name:string native_name:string lang_code:string base_lang_code:flags.1?string plural_code:string strings_count:int translated_count:int translations_url:string = LangPackLanguage;
|
||||
|
||||
channelAdminRights#5d7ceba5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true invite_link:flags.6?true pin_messages:flags.7?true add_admins:flags.9?true manage_call:flags.10?true = ChannelAdminRights;
|
||||
|
||||
@@ -864,9 +881,9 @@ secureValueTypeTemporaryRegistration#ea02ec33 = SecureValueType;
|
||||
secureValueTypePhone#b320aadb = SecureValueType;
|
||||
secureValueTypeEmail#8e3ca7ee = SecureValueType;
|
||||
|
||||
secureValue#b4b4b699 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;
|
||||
secureValue#187fa0ca flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile translation:flags.6?Vector<SecureFile> files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;
|
||||
|
||||
inputSecureValue#67872e8 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;
|
||||
inputSecureValue#db21d0a7 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile translation:flags.6?Vector<InputSecureFile> files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;
|
||||
|
||||
secureValueHash#ed1ecdb0 type:SecureValueType hash:bytes = SecureValueHash;
|
||||
|
||||
@@ -876,10 +893,13 @@ secureValueErrorReverseSide#868a2aa5 type:SecureValueType file_hash:bytes text:s
|
||||
secureValueErrorSelfie#e537ced6 type:SecureValueType file_hash:bytes text:string = SecureValueError;
|
||||
secureValueErrorFile#7a700873 type:SecureValueType file_hash:bytes text:string = SecureValueError;
|
||||
secureValueErrorFiles#666220e9 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
|
||||
secureValueError#869d758f type:SecureValueType hash:bytes text:string = SecureValueError;
|
||||
secureValueErrorTranslationFile#a1144770 type:SecureValueType file_hash:bytes text:string = SecureValueError;
|
||||
secureValueErrorTranslationFiles#34636dd8 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
|
||||
|
||||
secureCredentialsEncrypted#33f0ea47 data:bytes hash:bytes secret:bytes = SecureCredentialsEncrypted;
|
||||
|
||||
account.authorizationForm#cb976d53 flags:# selfie_required:flags.1?true required_types:Vector<SecureValueType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
|
||||
account.authorizationForm#ad2e1cd8 flags:# required_types:Vector<SecureRequiredType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
|
||||
|
||||
account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEmailCode;
|
||||
|
||||
@@ -890,6 +910,68 @@ savedPhoneContact#1142bd56 phone:string first_name:string last_name:string date:
|
||||
|
||||
account.takeout#4dba4501 id:long = account.Takeout;
|
||||
|
||||
passwordKdfAlgoUnknown#d45ab096 = PasswordKdfAlgo;
|
||||
passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow#3a912d4a salt1:bytes salt2:bytes g:int p:bytes = PasswordKdfAlgo;
|
||||
|
||||
securePasswordKdfAlgoUnknown#4a8537 = SecurePasswordKdfAlgo;
|
||||
securePasswordKdfAlgoPBKDF2HMACSHA512iter100000#bbf2dda0 salt:bytes = SecurePasswordKdfAlgo;
|
||||
securePasswordKdfAlgoSHA512#86471d92 salt:bytes = SecurePasswordKdfAlgo;
|
||||
|
||||
secureSecretSettings#1527bcac secure_algo:SecurePasswordKdfAlgo secure_secret:bytes secure_secret_id:long = SecureSecretSettings;
|
||||
|
||||
inputCheckPasswordEmpty#9880f658 = InputCheckPasswordSRP;
|
||||
inputCheckPasswordSRP#d27ff082 srp_id:long A:bytes M1:bytes = InputCheckPasswordSRP;
|
||||
|
||||
secureRequiredType#829d99da flags:# native_names:flags.0?true selfie_required:flags.1?true translation_required:flags.2?true type:SecureValueType = SecureRequiredType;
|
||||
secureRequiredTypeOneOf#27477b4 types:Vector<SecureRequiredType> = SecureRequiredType;
|
||||
|
||||
help.passportConfigNotModified#bfb9f457 = help.PassportConfig;
|
||||
help.passportConfig#a098d6af hash:int countries_langs:DataJSON = help.PassportConfig;
|
||||
|
||||
inputAppEvent#1d1b1245 time:double type:string peer:long data:JSONValue = InputAppEvent;
|
||||
|
||||
jsonObjectValue#c0de1bd9 key:string value:JSONValue = JSONObjectValue;
|
||||
|
||||
jsonNull#3f6d7b68 = JSONValue;
|
||||
jsonBool#c7345e6a value:Bool = JSONValue;
|
||||
jsonNumber#2be0dfa4 value:double = JSONValue;
|
||||
jsonString#b71e767a value:string = JSONValue;
|
||||
jsonArray#f7444763 value:Vector<JSONValue> = JSONValue;
|
||||
jsonObject#99c1d49d value:Vector<JSONObjectValue> = JSONValue;
|
||||
|
||||
pageTableCell#34566b6a flags:# header:flags.0?true align_center:flags.3?true align_right:flags.4?true valign_middle:flags.5?true valign_bottom:flags.6?true text:flags.7?RichText colspan:flags.1?int rowspan:flags.2?int = PageTableCell;
|
||||
|
||||
pageTableRow#e0c0c5e5 cells:Vector<PageTableCell> = PageTableRow;
|
||||
|
||||
pageCaption#6f747657 text:RichText credit:RichText = PageCaption;
|
||||
|
||||
pageListItemText#b92fb6cd text:RichText = PageListItem;
|
||||
pageListItemBlocks#25e073fc blocks:Vector<PageBlock> = PageListItem;
|
||||
|
||||
pageListOrderedItemText#5e068047 num:string text:RichText = PageListOrderedItem;
|
||||
pageListOrderedItemBlocks#98dd8936 num:string blocks:Vector<PageBlock> = PageListOrderedItem;
|
||||
|
||||
pageRelatedArticle#b390dc08 flags:# url:string webpage_id:long title:flags.0?string description:flags.1?string photo_id:flags.2?long author:flags.3?string published_date:flags.4?int = PageRelatedArticle;
|
||||
|
||||
page#ae891bec flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
|
||||
|
||||
help.supportName#8c05f1c9 name:string = help.SupportName;
|
||||
|
||||
help.userInfoEmpty#f3ae2eed = help.UserInfo;
|
||||
help.userInfo#1eb3758 message:string entities:Vector<MessageEntity> author:string date:int = help.UserInfo;
|
||||
|
||||
pollAnswer#6ca9c2e9 text:string option:bytes = PollAnswer;
|
||||
|
||||
poll#d5529d06 id:long flags:# closed:flags.0?true question:string answers:Vector<PollAnswer> = Poll;
|
||||
|
||||
pollAnswerVoters#3b6ddad2 flags:# chosen:flags.0?true option:bytes voters:int = PollAnswerVoters;
|
||||
|
||||
pollResults#5755785a flags:# min:flags.0?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int = PollResults;
|
||||
|
||||
chatOnlines#f041e250 onlines:int = ChatOnlines;
|
||||
|
||||
statsURL#47a971e0 url:string = StatsURL;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@@ -909,7 +991,7 @@ auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
|
||||
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
|
||||
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
|
||||
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
|
||||
auth.checkPassword#a63011e password_hash:bytes = auth.Authorization;
|
||||
auth.checkPassword#d18b4d16 password:InputCheckPasswordSRP = auth.Authorization;
|
||||
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
|
||||
auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
|
||||
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
|
||||
@@ -938,11 +1020,11 @@ account.updateDeviceLocked#38df3532 period:int = Bool;
|
||||
account.getAuthorizations#e320c158 = account.Authorizations;
|
||||
account.resetAuthorization#df77f3bc hash:long = Bool;
|
||||
account.getPassword#548a30f5 = account.Password;
|
||||
account.getPasswordSettings#bc8d11bb current_password_hash:bytes = account.PasswordSettings;
|
||||
account.updatePasswordSettings#fa7c4b86 current_password_hash:bytes new_settings:account.PasswordInputSettings = Bool;
|
||||
account.getPasswordSettings#9cd4eaf9 password:InputCheckPasswordSRP = account.PasswordSettings;
|
||||
account.updatePasswordSettings#a59b102f password:InputCheckPasswordSRP new_settings:account.PasswordInputSettings = Bool;
|
||||
account.sendConfirmPhoneCode#1516d7bd flags:# allow_flashcall:flags.0?true hash:string current_number:flags.0?Bool = auth.SentCode;
|
||||
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
|
||||
account.getTmpPassword#4a82327e password_hash:bytes period:int = account.TmpPassword;
|
||||
account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
|
||||
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
|
||||
account.resetWebAuthorization#2d01b9ef hash:long = Bool;
|
||||
account.resetWebAuthorizations#682d2594 = Bool;
|
||||
@@ -958,21 +1040,27 @@ account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
|
||||
account.verifyEmail#ecba39db email:string code:string = Bool;
|
||||
account.initTakeoutSession#f05b4804 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?int = account.Takeout;
|
||||
account.finishTakeoutSession#1d2652ee flags:# success:flags.0?true = Bool;
|
||||
account.confirmPasswordEmail#8fdf1920 code:string = Bool;
|
||||
account.resendPasswordEmail#7a7f2a15 = Bool;
|
||||
account.cancelPasswordEmail#c1cbd5b6 = Bool;
|
||||
account.getContactSignUpNotification#9f07c728 = Bool;
|
||||
account.setContactSignUpNotification#cff43f61 silent:Bool = Bool;
|
||||
account.getNotifyExceptions#53577479 flags:# compare_sound:flags.1?true peer:flags.0?InputNotifyPeer = Updates;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
|
||||
|
||||
contacts.getContactIDs#2caa4a42 hash:int = Vector<int>;
|
||||
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
|
||||
contacts.getContacts#c023849f hash:int = contacts.Contacts;
|
||||
contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts;
|
||||
contacts.deleteContact#8e953744 id:InputUser = contacts.Link;
|
||||
contacts.deleteContacts#59ab389e id:Vector<InputUser> = Bool;
|
||||
contacts.deleteByPhones#1013fd9e phones:Vector<string> = Bool;
|
||||
contacts.block#332b49fc id:InputUser = Bool;
|
||||
contacts.unblock#e54100bd id:InputUser = Bool;
|
||||
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
|
||||
contacts.exportCard#84e53737 = Vector<int>;
|
||||
contacts.importCard#4fe196fe export_card:Vector<int> = User;
|
||||
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;
|
||||
@@ -1038,10 +1126,10 @@ messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs;
|
||||
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
|
||||
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
|
||||
messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool;
|
||||
messages.sendInlineBotResult#b16e06fe flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates;
|
||||
messages.sendInlineBotResult#b16e06fe flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates;
|
||||
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
|
||||
messages.editMessage#c000e4c8 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Updates;
|
||||
messages.editInlineBotMessage#adc3e828 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Bool;
|
||||
messages.editMessage#d116f31e flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Updates;
|
||||
messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
|
||||
messages.getBotCallbackAnswer#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer;
|
||||
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
|
||||
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
|
||||
@@ -1080,6 +1168,12 @@ messages.searchStickerSets#c2b7d08b flags:# exclude_featured:flags.0?true q:stri
|
||||
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
|
||||
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
|
||||
messages.clearAllDrafts#7e58ee9c = Bool;
|
||||
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true peer:InputPeer id:int = Updates;
|
||||
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
||||
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
|
||||
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
|
||||
messages.getStatsURL#83f6c0cd peer:InputPeer = StatsURL;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||
@@ -1101,8 +1195,7 @@ upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<Fil
|
||||
|
||||
help.getConfig#c4f9186b = Config;
|
||||
help.getNearestDc#1fb33026 = NearestDc;
|
||||
help.getAppUpdate#ae2de196 = help.AppUpdate;
|
||||
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
|
||||
help.getAppUpdate#522d5a7d source:string = help.AppUpdate;
|
||||
help.getInviteText#4d392343 = help.InviteText;
|
||||
help.getSupport#9cdf08cd = help.Support;
|
||||
help.getAppChangelog#9010ef6f prev_app_version:string = Updates;
|
||||
@@ -1113,6 +1206,12 @@ help.getProxyData#3d7758e1 = help.ProxyData;
|
||||
help.getTermsOfServiceUpdate#2ca51fd1 = help.TermsOfServiceUpdate;
|
||||
help.acceptTermsOfService#ee72f79a id:DataJSON = Bool;
|
||||
help.getDeepLinkInfo#3fedc75f path:string = help.DeepLinkInfo;
|
||||
help.getAppConfig#98914110 = JSONValue;
|
||||
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
|
||||
help.getPassportConfig#c661ad08 hash:int = help.PassportConfig;
|
||||
help.getSupportName#d360e72c = help.SupportName;
|
||||
help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
|
||||
help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
|
||||
|
||||
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
|
||||
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
|
||||
@@ -1138,7 +1237,6 @@ channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
||||
channels.toggleInvites#49609307 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.exportMessageLink#ceb77163 channel:InputChannel id:int grouped:Bool = ExportedMessageLink;
|
||||
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
|
||||
channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
|
||||
channels.editBanned#bfd915cd channel:InputChannel user_id:InputUser banned_rights:ChannelBannedRights = Updates;
|
||||
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
||||
@@ -1172,9 +1270,10 @@ phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDisc
|
||||
phone.setCallRating#1c536a34 peer:InputPhoneCall rating:int comment:string = Updates;
|
||||
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
||||
|
||||
langpack.getLangPack#9ab5c58e lang_code:string = LangPackDifference;
|
||||
langpack.getStrings#2e1ee318 lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
||||
langpack.getDifference#b2e4d7d from_version:int = LangPackDifference;
|
||||
langpack.getLanguages#800fd57d = Vector<LangPackLanguage>;
|
||||
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
|
||||
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
||||
langpack.getDifference#9d51e814 lang_code:string from_version:int = LangPackDifference;
|
||||
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
|
||||
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
|
||||
|
||||
// LAYER 82
|
||||
// LAYER 91
|
||||
|
@@ -76,4 +76,7 @@ USER_IS_BLOCKED The user blocked you
|
||||
YOU_BLOCKED_USER You blocked this user
|
||||
ADMINS_TOO_MUCH The chat has too many administrators
|
||||
BOTS_TOO_MUCH The chat has too many bots
|
||||
USER_ADMIN_INVALID The action requires admin privileges
|
||||
USER_ADMIN_INVALID The action requires admin privileges
|
||||
INPUT_USER_DEACTIVATED The target user has been deactivated
|
||||
PASSWORD_RECOVERY_NA The password recovery e-mail is not available
|
||||
PASSWORD_EMPTY The password entered is empty
|
|
@@ -1,2 +1,3 @@
|
||||
id message
|
||||
AUTH_KEY_DUPLICATED Authorization error. You must log out and log in again with your phone number. We apologize for the inconvenience.
|
||||
AUTH_KEY_DUPLICATED Authorization error - you must delete your session file and log in again with your phone number
|
||||
FILEREF_UPGRADE_NEEDED The file reference has expired - you must obtain the original media message
|
|
@@ -62,6 +62,9 @@ Messages
|
||||
delete_messages
|
||||
get_messages
|
||||
get_history
|
||||
send_poll
|
||||
vote_poll
|
||||
retract_vote
|
||||
|
||||
Chats
|
||||
-----
|
||||
|
@@ -40,6 +40,8 @@ Messages & Media
|
||||
Location
|
||||
Venue
|
||||
Sticker
|
||||
Poll
|
||||
PollOption
|
||||
|
||||
Bots
|
||||
----
|
||||
@@ -146,6 +148,12 @@ Input Media
|
||||
.. autoclass:: Sticker
|
||||
:members:
|
||||
|
||||
.. autoclass:: Poll
|
||||
:members:
|
||||
|
||||
.. autoclass:: PollOption
|
||||
:members:
|
||||
|
||||
.. Bots
|
||||
----
|
||||
|
||||
|
@@ -82,7 +82,7 @@ If no error shows up you are good to go.
|
||||
|
||||
>>> import pyrogram
|
||||
>>> pyrogram.__version__
|
||||
'0.9.3'
|
||||
'0.9.4'
|
||||
|
||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
||||
.. _develop: http://github.com/pyrogram/pyrogram
|
||||
|
@@ -39,7 +39,8 @@ from .client.types import (
|
||||
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
|
||||
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus,
|
||||
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
|
||||
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
||||
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove,
|
||||
Poll, PollOption
|
||||
)
|
||||
from .client import (
|
||||
Client, ChatAction, ParseMode, Emoji,
|
||||
|
@@ -45,8 +45,12 @@ from pyrogram.api.errors import (
|
||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
|
||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied)
|
||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
||||
PasswordRecoveryNa, PasswordEmpty
|
||||
)
|
||||
from pyrogram.client.handlers import DisconnectHandler
|
||||
from pyrogram.client.handlers.handler import Handler
|
||||
from pyrogram.client.methods.password.utils import compute_check
|
||||
from pyrogram.crypto import AES
|
||||
from pyrogram.session import Auth, Session
|
||||
from .dispatcher import Dispatcher
|
||||
@@ -578,21 +582,47 @@ class Client(Methods, BaseClient):
|
||||
self.first_name = None
|
||||
except SessionPasswordNeeded as e:
|
||||
print(e.MESSAGE)
|
||||
r = await self.send(functions.account.GetPassword())
|
||||
|
||||
while True:
|
||||
try:
|
||||
r = await self.send(functions.account.GetPassword())
|
||||
|
||||
if self.password is None:
|
||||
print("Hint: {}".format(r.hint))
|
||||
self.password = await ainput("Enter password: ")
|
||||
|
||||
if type(self.password) is str:
|
||||
self.password = r.current_salt + self.password.encode() + r.current_salt
|
||||
self.password = await ainput("Enter password (empty to recover): ")
|
||||
|
||||
password_hash = sha256(self.password).digest()
|
||||
if self.password == "":
|
||||
r = await self.send(functions.auth.RequestPasswordRecovery())
|
||||
|
||||
r = await self.send(functions.auth.CheckPassword(password_hash))
|
||||
print("An e-mail containing the recovery code has been sent to {}".format(
|
||||
r.email_pattern
|
||||
))
|
||||
|
||||
r = await self.send(
|
||||
functions.auth.RecoverPassword(
|
||||
code=await ainput("Enter password recovery code: ")
|
||||
)
|
||||
)
|
||||
else:
|
||||
r = await self.send(
|
||||
functions.auth.CheckPassword(
|
||||
password=compute_check(r, self.password)
|
||||
)
|
||||
)
|
||||
except PasswordEmpty as e:
|
||||
if password_hash_invalid_raises:
|
||||
raise
|
||||
else:
|
||||
print(e.MESSAGE)
|
||||
self.password = None
|
||||
except PasswordRecoveryNa as e:
|
||||
if password_hash_invalid_raises:
|
||||
raise
|
||||
else:
|
||||
print(e.MESSAGE)
|
||||
self.password = None
|
||||
except PasswordHashInvalid as e:
|
||||
if password_hash_invalid_raises:
|
||||
raise
|
||||
@@ -605,6 +635,7 @@ class Client(Methods, BaseClient):
|
||||
else:
|
||||
print(e.MESSAGE.format(x=e.x))
|
||||
time.sleep(e.x)
|
||||
self.password = None
|
||||
except Exception as e:
|
||||
log.error(e, exc_info=True)
|
||||
else:
|
||||
@@ -1263,7 +1294,7 @@ class Client(Methods, BaseClient):
|
||||
volume_id: int = None,
|
||||
local_id: int = None,
|
||||
secret: int = None,
|
||||
version: int = 0,
|
||||
|
||||
size: int = None,
|
||||
progress: callable = None,
|
||||
progress_args: tuple = ()) -> str:
|
||||
@@ -1311,13 +1342,14 @@ class Client(Methods, BaseClient):
|
||||
location = types.InputFileLocation(
|
||||
volume_id=volume_id,
|
||||
local_id=local_id,
|
||||
secret=secret
|
||||
secret=secret,
|
||||
file_reference=b""
|
||||
)
|
||||
else: # Any other file can be more easily accessed by id and access_hash
|
||||
location = types.InputDocumentFileLocation(
|
||||
id=id,
|
||||
access_hash=access_hash,
|
||||
version=version
|
||||
file_reference=b""
|
||||
)
|
||||
|
||||
limit = 1024 * 1024
|
||||
|
@@ -121,6 +121,9 @@ class Filters:
|
||||
web_page = create("WebPage", lambda _, m: m.web_page)
|
||||
"""Filter messages sent with a webpage preview."""
|
||||
|
||||
poll = create("Poll", lambda _, m: m.poll)
|
||||
"""Filter messages that contain :obj:`Poll <pyrogram.Poll>` objects."""
|
||||
|
||||
private = create("Private", lambda _, m: bool(m.chat and m.chat.type == "private"))
|
||||
"""Filter messages sent in private chats."""
|
||||
|
||||
|
@@ -28,7 +28,8 @@ class SendInlineBotResult(BaseClient):
|
||||
query_id: int,
|
||||
result_id: str,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None):
|
||||
reply_to_message_id: int = None,
|
||||
hide_via: bool = None):
|
||||
"""Use this method to send an inline bot result.
|
||||
Bot results can be retrieved using :obj:`get_inline_bot_results <pyrogram.Client.get_inline_bot_results>`
|
||||
|
||||
@@ -51,6 +52,9 @@ class SendInlineBotResult(BaseClient):
|
||||
reply_to_message_id (``bool``, *optional*):
|
||||
If the message is a reply, ID of the original message.
|
||||
|
||||
hide_via (``bool``):
|
||||
Sends the message with *via @bot* hidden.
|
||||
|
||||
Returns:
|
||||
On success, the sent Message is returned.
|
||||
|
||||
@@ -64,6 +68,7 @@ class SendInlineBotResult(BaseClient):
|
||||
id=result_id,
|
||||
random_id=self.rnd_id(),
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
hide_via=hide_via or None
|
||||
)
|
||||
)
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
from typing import Union
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api import functions
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class PinChatMessage(BaseClient):
|
||||
chat_id: Union[int, str],
|
||||
message_id: int,
|
||||
disable_notification: bool = None) -> bool:
|
||||
"""Use this method to pin a message in a supergroup or a channel.
|
||||
"""Use this method to pin a message in a group, channel or your own chat.
|
||||
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin right in
|
||||
the supergroup or "can_edit_messages" admin right in the channel.
|
||||
|
||||
@@ -49,19 +49,10 @@ class PinChatMessage(BaseClient):
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
|
||||
"""
|
||||
peer = await self.resolve_peer(chat_id)
|
||||
|
||||
if isinstance(peer, types.InputPeerChannel):
|
||||
await self.send(
|
||||
functions.channels.UpdatePinnedMessage(
|
||||
channel=peer,
|
||||
id=message_id,
|
||||
silent=disable_notification or None
|
||||
)
|
||||
await self.send(
|
||||
functions.messages.UpdatePinnedMessage(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
id=message_id,
|
||||
silent=disable_notification or None
|
||||
)
|
||||
elif isinstance(peer, types.InputPeerChat):
|
||||
raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
|
||||
else:
|
||||
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
||||
|
||||
return True
|
||||
)
|
||||
|
@@ -61,7 +61,8 @@ class SetChatPhoto(BaseClient):
|
||||
photo = types.InputChatPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=s[0],
|
||||
access_hash=s[1]
|
||||
access_hash=s[1],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -18,14 +18,14 @@
|
||||
|
||||
from typing import Union
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api import functions
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class UnpinChatMessage(BaseClient):
|
||||
async def unpin_chat_message(self,
|
||||
chat_id: Union[int, str]) -> bool:
|
||||
"""Use this method to unpin a message in a supergroup or a channel.
|
||||
"""Use this method to unpin a message in a group, channel or your own chat.
|
||||
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin
|
||||
right in the supergroup or "can_edit_messages" admin right in the channel.
|
||||
|
||||
@@ -40,18 +40,11 @@ class UnpinChatMessage(BaseClient):
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
|
||||
"""
|
||||
peer = await self.resolve_peer(chat_id)
|
||||
|
||||
if isinstance(peer, types.InputPeerChannel):
|
||||
await self.send(
|
||||
functions.channels.UpdatePinnedMessage(
|
||||
channel=peer,
|
||||
id=0
|
||||
)
|
||||
await self.send(
|
||||
functions.messages.UpdatePinnedMessage(
|
||||
peer=await self.resolve_peer(chat_id),
|
||||
id=0
|
||||
)
|
||||
elif isinstance(peer, types.InputPeerChat):
|
||||
raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
|
||||
else:
|
||||
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
||||
)
|
||||
|
||||
return True
|
||||
|
@@ -24,6 +24,7 @@ from .edit_message_text import EditMessageText
|
||||
from .forward_messages import ForwardMessages
|
||||
from .get_history import GetHistory
|
||||
from .get_messages import GetMessages
|
||||
from .retract_vote import RetractVote
|
||||
from .send_animation import SendAnimation
|
||||
from .send_audio import SendAudio
|
||||
from .send_chat_action import SendChatAction
|
||||
@@ -33,11 +34,13 @@ from .send_location import SendLocation
|
||||
from .send_media_group import SendMediaGroup
|
||||
from .send_message import SendMessage
|
||||
from .send_photo import SendPhoto
|
||||
from .send_poll import SendPoll
|
||||
from .send_sticker import SendSticker
|
||||
from .send_venue import SendVenue
|
||||
from .send_video import SendVideo
|
||||
from .send_video_note import SendVideoNote
|
||||
from .send_voice import SendVoice
|
||||
from .vote_poll import VotePoll
|
||||
|
||||
|
||||
class Messages(
|
||||
@@ -62,6 +65,9 @@ class Messages(
|
||||
SendVenue,
|
||||
SendVideo,
|
||||
SendVideoNote,
|
||||
SendVoice
|
||||
SendVoice,
|
||||
SendPoll,
|
||||
VotePoll,
|
||||
RetractVote
|
||||
):
|
||||
pass
|
||||
|
@@ -84,7 +84,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=media.photo.id,
|
||||
access_hash=media.photo.access_hash
|
||||
access_hash=media.photo.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
elif media.media.startswith("http"):
|
||||
@@ -110,7 +111,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
@@ -138,7 +140,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
elif media.media.startswith("http"):
|
||||
@@ -164,7 +167,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
@@ -191,7 +195,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
elif media.media.startswith("http"):
|
||||
@@ -217,7 +222,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
@@ -246,7 +252,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
elif media.media.startswith("http"):
|
||||
@@ -272,7 +279,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
@@ -294,7 +302,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
elif media.media.startswith("http"):
|
||||
@@ -320,7 +329,8 @@ class EditMessageMedia(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
54
pyrogram/client/methods/messages/retract_vote.py
Normal file
54
pyrogram/client/methods/messages/retract_vote.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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
|
||||
|
||||
from pyrogram.api import functions
|
||||
from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class RetractVote(BaseClient):
|
||||
def retract_vote(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id) -> bool:
|
||||
"""Use this method to retract your vote in a poll.
|
||||
|
||||
Args:
|
||||
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).
|
||||
|
||||
message_id (``int``):
|
||||
Unique poll message identifier inside this chat.
|
||||
|
||||
Returns:
|
||||
On success, True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
"""
|
||||
self.send(
|
||||
functions.messages.SendVote(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
msg_id=message_id,
|
||||
options=[]
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
@@ -167,7 +167,8 @@ class SendAnimation(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -166,7 +166,8 @@ class SendAudio(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -147,7 +147,8 @@ class SendDocument(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -77,7 +77,8 @@ class SendMediaGroup(BaseClient):
|
||||
media = types.InputMediaPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=media.photo.id,
|
||||
access_hash=media.photo.access_hash
|
||||
access_hash=media.photo.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -99,7 +100,8 @@ class SendMediaGroup(BaseClient):
|
||||
media = types.InputMediaPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
elif isinstance(i, pyrogram.InputMediaVideo):
|
||||
@@ -127,7 +129,8 @@ class SendMediaGroup(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=media.document.id,
|
||||
access_hash=media.document.access_hash
|
||||
access_hash=media.document.access_hash,
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -149,7 +152,8 @@ class SendMediaGroup(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -142,7 +142,8 @@ class SendPhoto(BaseClient):
|
||||
media = types.InputMediaPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
),
|
||||
ttl_seconds=ttl_seconds
|
||||
)
|
||||
|
95
pyrogram/client/methods/messages/send_poll.py
Normal file
95
pyrogram/client/methods/messages/send_poll.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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, List
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class SendPoll(BaseClient):
|
||||
def send_poll(self,
|
||||
chat_id: Union[int, str],
|
||||
question: str,
|
||||
options: List[str],
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union["pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"] = None) -> "pyrogram.Message":
|
||||
"""Use this method to send a new poll.
|
||||
|
||||
Args:
|
||||
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).
|
||||
|
||||
question (``str``):
|
||||
The poll question, as string.
|
||||
|
||||
options (List of ``str``):
|
||||
The poll options, as list of strings (2 to 10 options are allowed).
|
||||
|
||||
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.
|
||||
|
||||
Returns:
|
||||
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
"""
|
||||
r = self.send(
|
||||
functions.messages.SendMedia(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
media=types.InputMediaPoll(
|
||||
poll=types.Poll(
|
||||
id=0,
|
||||
question=question,
|
||||
answers=[
|
||||
types.PollAnswer(text=o, option=bytes([i]))
|
||||
for i, o in enumerate(options)
|
||||
]
|
||||
)
|
||||
),
|
||||
message="",
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
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}
|
||||
)
|
@@ -127,7 +127,8 @@ class SendSticker(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -170,7 +170,8 @@ class SendVideo(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -145,7 +145,8 @@ class SendVideoNote(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -146,7 +146,8 @@ class SendVoice(BaseClient):
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3]
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
60
pyrogram/client/methods/messages/vote_poll.py
Normal file
60
pyrogram/client/methods/messages/vote_poll.py
Normal file
@@ -0,0 +1,60 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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
|
||||
|
||||
from pyrogram.api import functions
|
||||
from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class VotePoll(BaseClient):
|
||||
def vote_poll(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id,
|
||||
option: int) -> bool:
|
||||
"""Use this method to vote a poll.
|
||||
|
||||
Args:
|
||||
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).
|
||||
|
||||
message_id (``int``):
|
||||
Unique poll message identifier inside this chat.
|
||||
|
||||
option (``int``):
|
||||
Index of the poll option you want to vote for (0 to 9).
|
||||
|
||||
Returns:
|
||||
On success, True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
"""
|
||||
poll = self.get_messages(chat_id, message_id).poll
|
||||
|
||||
self.send(
|
||||
functions.messages.SendVote(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
msg_id=message_id,
|
||||
options=[poll.options[option].data]
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
@@ -17,17 +17,17 @@
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from hashlib import sha256
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from .utils import compute_hash, compute_check, btoi, itob
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class ChangeCloudPassword(BaseClient):
|
||||
async def change_cloud_password(self,
|
||||
current_password: str,
|
||||
new_password: str,
|
||||
new_hint: str = "") -> bool:
|
||||
current_password: str,
|
||||
new_password: str,
|
||||
new_hint: str = "") -> bool:
|
||||
"""Use this method to change your Two-Step Verification password (Cloud Password) with a new one.
|
||||
|
||||
Args:
|
||||
@@ -41,28 +41,30 @@ class ChangeCloudPassword(BaseClient):
|
||||
A new password hint.
|
||||
|
||||
Returns:
|
||||
True on success, False otherwise.
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case there is no cloud password to change.
|
||||
"""
|
||||
r = await self.send(functions.account.GetPassword())
|
||||
|
||||
if isinstance(r, types.account.Password):
|
||||
current_password_hash = sha256(r.current_salt + current_password.encode() + r.current_salt).digest()
|
||||
if not r.has_password:
|
||||
raise ValueError("There is no cloud password to change")
|
||||
|
||||
new_salt = r.new_salt + os.urandom(8)
|
||||
new_password_hash = sha256(new_salt + new_password.encode() + new_salt).digest()
|
||||
r.new_algo.salt1 += os.urandom(32)
|
||||
new_hash = btoi(compute_hash(r.new_algo, new_password))
|
||||
new_hash = itob(pow(r.new_algo.g, new_hash, btoi(r.new_algo.p)))
|
||||
|
||||
return await self.send(
|
||||
functions.account.UpdatePasswordSettings(
|
||||
current_password_hash=current_password_hash,
|
||||
new_settings=types.account.PasswordInputSettings(
|
||||
new_salt=new_salt,
|
||||
new_password_hash=new_password_hash,
|
||||
hint=new_hint
|
||||
)
|
||||
await self.send(
|
||||
functions.account.UpdatePasswordSettings(
|
||||
password=compute_check(r, current_password),
|
||||
new_settings=types.account.PasswordInputSettings(
|
||||
new_algo=r.new_algo,
|
||||
new_password_hash=new_hash,
|
||||
hint=new_hint
|
||||
)
|
||||
)
|
||||
else:
|
||||
return False
|
||||
)
|
||||
|
||||
return True
|
||||
|
@@ -17,9 +17,9 @@
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from hashlib import sha256
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from .utils import compute_hash, btoi, itob
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
@@ -27,10 +27,10 @@ class EnableCloudPassword(BaseClient):
|
||||
async def enable_cloud_password(self,
|
||||
password: str,
|
||||
hint: str = "",
|
||||
email: str = "") -> bool:
|
||||
email: str = None) -> bool:
|
||||
"""Use this method to enable the Two-Step Verification security feature (Cloud Password) on your account.
|
||||
|
||||
This password will be asked when you log in on a new device in addition to the SMS code.
|
||||
This password will be asked when you log-in on a new device in addition to the SMS code.
|
||||
|
||||
Args:
|
||||
password (``str``):
|
||||
@@ -43,27 +43,31 @@ class EnableCloudPassword(BaseClient):
|
||||
Recovery e-mail.
|
||||
|
||||
Returns:
|
||||
True on success, False otherwise.
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case there is already a cloud password enabled.
|
||||
"""
|
||||
r = await self.send(functions.account.GetPassword())
|
||||
|
||||
if isinstance(r, types.account.NoPassword):
|
||||
salt = r.new_salt + os.urandom(8)
|
||||
password_hash = sha256(salt + password.encode() + salt).digest()
|
||||
if r.has_password:
|
||||
raise ValueError("There is already a cloud password enabled")
|
||||
|
||||
return await self.send(
|
||||
functions.account.UpdatePasswordSettings(
|
||||
current_password_hash=salt,
|
||||
new_settings=types.account.PasswordInputSettings(
|
||||
new_salt=salt,
|
||||
new_password_hash=password_hash,
|
||||
hint=hint,
|
||||
email=email
|
||||
)
|
||||
r.new_algo.salt1 += os.urandom(32)
|
||||
new_hash = btoi(compute_hash(r.new_algo, password))
|
||||
new_hash = itob(pow(r.new_algo.g, new_hash, btoi(r.new_algo.p)))
|
||||
|
||||
await self.send(
|
||||
functions.account.UpdatePasswordSettings(
|
||||
password=types.InputCheckPasswordEmpty(),
|
||||
new_settings=types.account.PasswordInputSettings(
|
||||
new_algo=r.new_algo,
|
||||
new_password_hash=new_hash,
|
||||
hint=hint,
|
||||
email=email
|
||||
)
|
||||
)
|
||||
else:
|
||||
return False
|
||||
)
|
||||
|
||||
return True
|
||||
|
@@ -16,9 +16,8 @@
|
||||
# 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 hashlib import sha256
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from .utils import compute_check
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
@@ -32,25 +31,26 @@ class RemoveCloudPassword(BaseClient):
|
||||
Your current password.
|
||||
|
||||
Returns:
|
||||
True on success, False otherwise.
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case there is no cloud password to remove.
|
||||
"""
|
||||
r = await self.send(functions.account.GetPassword())
|
||||
|
||||
if isinstance(r, types.account.Password):
|
||||
password_hash = sha256(r.current_salt + password.encode() + r.current_salt).digest()
|
||||
if not r.has_password:
|
||||
raise ValueError("There is no cloud password to remove")
|
||||
|
||||
return await self.send(
|
||||
functions.account.UpdatePasswordSettings(
|
||||
current_password_hash=password_hash,
|
||||
new_settings=types.account.PasswordInputSettings(
|
||||
new_salt=b"",
|
||||
new_password_hash=b"",
|
||||
hint=""
|
||||
)
|
||||
await self.send(
|
||||
functions.account.UpdatePasswordSettings(
|
||||
password=compute_check(r, password),
|
||||
new_settings=types.account.PasswordInputSettings(
|
||||
new_algo=types.PasswordKdfAlgoUnknown(),
|
||||
new_password_hash=b"",
|
||||
hint=""
|
||||
)
|
||||
)
|
||||
else:
|
||||
return False
|
||||
)
|
||||
|
||||
return True
|
||||
|
104
pyrogram/client/methods/password/utils.py
Normal file
104
pyrogram/client/methods/password/utils.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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 hashlib
|
||||
import os
|
||||
|
||||
from pyrogram.api import types
|
||||
|
||||
|
||||
def btoi(b: bytes) -> int:
|
||||
return int.from_bytes(b, "big")
|
||||
|
||||
|
||||
def itob(i: int) -> bytes:
|
||||
return i.to_bytes(256, "big")
|
||||
|
||||
|
||||
def sha256(data: bytes) -> bytes:
|
||||
return hashlib.sha256(data).digest()
|
||||
|
||||
|
||||
def xor(a: bytes, b: bytes) -> bytes:
|
||||
return bytes(i ^ j for i, j in zip(a, b))
|
||||
|
||||
|
||||
def compute_hash(algo: types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow, password: str) -> bytes:
|
||||
hash1 = sha256(algo.salt1 + password.encode() + algo.salt1)
|
||||
hash2 = sha256(algo.salt2 + hash1 + algo.salt2)
|
||||
hash3 = hashlib.pbkdf2_hmac("sha512", hash2, algo.salt1, 100000)
|
||||
|
||||
return sha256(algo.salt2 + hash3 + algo.salt2)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def compute_check(r: types.account.Password, password: str) -> types.InputCheckPasswordSRP:
|
||||
algo = r.current_algo
|
||||
|
||||
p_bytes = algo.p
|
||||
p = btoi(algo.p)
|
||||
|
||||
g_bytes = itob(algo.g)
|
||||
g = algo.g
|
||||
|
||||
B_bytes = r.srp_B
|
||||
B = btoi(B_bytes)
|
||||
|
||||
srp_id = r.srp_id
|
||||
|
||||
x_bytes = compute_hash(algo, password)
|
||||
x = btoi(x_bytes)
|
||||
|
||||
g_x = pow(g, x, p)
|
||||
|
||||
k_bytes = sha256(p_bytes + g_bytes)
|
||||
k = btoi(k_bytes)
|
||||
|
||||
kg_x = (k * g_x) % p
|
||||
|
||||
while True:
|
||||
a_bytes = os.urandom(256)
|
||||
a = btoi(a_bytes)
|
||||
|
||||
A = pow(g, a, p)
|
||||
A_bytes = itob(A)
|
||||
|
||||
u = btoi(sha256(A_bytes + B_bytes))
|
||||
|
||||
if u > 0:
|
||||
break
|
||||
|
||||
g_b = (B - kg_x) % p
|
||||
|
||||
ux = u * x
|
||||
a_ux = a + ux
|
||||
S = pow(g_b, a_ux, p)
|
||||
S_bytes = itob(S)
|
||||
|
||||
K_bytes = sha256(S_bytes)
|
||||
|
||||
M1_bytes = sha256(
|
||||
xor(sha256(p_bytes), sha256(g_bytes))
|
||||
+ sha256(algo.salt1)
|
||||
+ sha256(algo.salt2)
|
||||
+ A_bytes
|
||||
+ B_bytes
|
||||
+ K_bytes
|
||||
)
|
||||
|
||||
return types.InputCheckPasswordSRP(srp_id, A_bytes, M1_bytes)
|
@@ -49,7 +49,8 @@ class DeleteUserProfilePhotos(BaseClient):
|
||||
input_photos.append(
|
||||
types.InputPhoto(
|
||||
id=s[0],
|
||||
access_hash=s[1]
|
||||
access_hash=s[1],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -31,7 +31,7 @@ from .input_media import (
|
||||
from .messages_and_media import (
|
||||
Audio, Contact, Document, Animation, Location, Photo, PhotoSize,
|
||||
Sticker, Venue, Video, VideoNote, Voice, UserProfilePhotos,
|
||||
Message, Messages, MessageEntity
|
||||
Message, Messages, MessageEntity, Poll, PollOption
|
||||
)
|
||||
from .user_and_chats import (
|
||||
Chat, ChatMember, ChatMembers, ChatPhoto,
|
||||
|
@@ -26,6 +26,8 @@ from .message_entity import MessageEntity
|
||||
from .messages import Messages
|
||||
from .photo import Photo
|
||||
from .photo_size import PhotoSize
|
||||
from .poll import Poll
|
||||
from .poll_option import PollOption
|
||||
from .sticker import Sticker
|
||||
from .user_profile_photos import UserProfilePhotos
|
||||
from .venue import Venue
|
||||
|
@@ -262,6 +262,7 @@ class Message(PyrogramType):
|
||||
location: "pyrogram.Location" = None,
|
||||
venue: "pyrogram.Venue" = None,
|
||||
web_page: bool = None,
|
||||
poll: "pyrogram.Poll" = None,
|
||||
new_chat_members: List[User] = None,
|
||||
left_chat_member: User = None,
|
||||
new_chat_title: str = None,
|
||||
@@ -317,6 +318,7 @@ class Message(PyrogramType):
|
||||
self.location = location
|
||||
self.venue = venue
|
||||
self.web_page = web_page
|
||||
self.poll = poll
|
||||
self.new_chat_members = new_chat_members
|
||||
self.left_chat_member = left_chat_member
|
||||
self.new_chat_title = new_chat_title
|
||||
@@ -440,6 +442,7 @@ class Message(PyrogramType):
|
||||
sticker = None
|
||||
document = None
|
||||
web_page = None
|
||||
poll = None
|
||||
|
||||
media = message.media
|
||||
|
||||
@@ -494,6 +497,8 @@ class Message(PyrogramType):
|
||||
elif isinstance(media, types.MessageMediaWebPage):
|
||||
web_page = True
|
||||
media = None
|
||||
elif isinstance(media, types.MessageMediaPoll):
|
||||
poll = pyrogram.Poll._parse(client, media)
|
||||
else:
|
||||
media = None
|
||||
|
||||
@@ -542,6 +547,7 @@ class Message(PyrogramType):
|
||||
sticker=sticker,
|
||||
document=document,
|
||||
web_page=web_page,
|
||||
poll=poll,
|
||||
views=message.views,
|
||||
via_bot=User._parse(client, users.get(message.via_bot_id, None)),
|
||||
outgoing=message.out,
|
||||
|
102
pyrogram/client/types/messages_and_media/poll.py
Normal file
102
pyrogram/client/types/messages_and_media/poll.py
Normal file
@@ -0,0 +1,102 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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 List
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import types
|
||||
from .poll_option import PollOption
|
||||
from ..pyrogram_type import PyrogramType
|
||||
|
||||
|
||||
class Poll(PyrogramType):
|
||||
"""This object represents a Poll.
|
||||
|
||||
Args:
|
||||
id (``int``):
|
||||
The poll id in this chat.
|
||||
|
||||
closed (``bool``):
|
||||
Whether the poll is closed or not.
|
||||
|
||||
question (``str``):
|
||||
Poll question.
|
||||
|
||||
options (List of :obj:`PollOption`):
|
||||
The available poll options.
|
||||
|
||||
total_voters (``int``):
|
||||
Total amount of voters for this poll.
|
||||
|
||||
option_chosen (``int``, *optional*):
|
||||
The index of your chosen option (in case you voted already), None otherwise.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
*,
|
||||
client: "pyrogram.client.ext.BaseClient",
|
||||
id: int,
|
||||
closed: bool,
|
||||
question: str,
|
||||
options: List[PollOption],
|
||||
total_voters: int,
|
||||
option_chosen: int = None):
|
||||
super().__init__(client)
|
||||
|
||||
self.id = id
|
||||
self.closed = closed
|
||||
self.question = question
|
||||
self.options = options
|
||||
self.total_voters = total_voters
|
||||
self.option_chosen = option_chosen
|
||||
|
||||
@staticmethod
|
||||
def _parse(client, media_poll: types.MessageMediaPoll) -> "Poll":
|
||||
poll = media_poll.poll
|
||||
results = media_poll.results.results
|
||||
total_voters = media_poll.results.total_voters
|
||||
option_chosen = None
|
||||
|
||||
options = []
|
||||
|
||||
for i, answer in enumerate(poll.answers):
|
||||
voters = 0
|
||||
|
||||
if results:
|
||||
result = results[i]
|
||||
voters = result.voters
|
||||
|
||||
if result.chosen:
|
||||
option_chosen = i
|
||||
|
||||
options.append(PollOption(
|
||||
text=answer.text,
|
||||
voters=voters,
|
||||
data=answer.option,
|
||||
client=client
|
||||
))
|
||||
|
||||
return Poll(
|
||||
id=poll.id,
|
||||
closed=poll.closed,
|
||||
question=poll.question,
|
||||
options=options,
|
||||
total_voters=total_voters,
|
||||
option_chosen=option_chosen,
|
||||
client=client
|
||||
)
|
47
pyrogram/client/types/messages_and_media/poll_option.py
Normal file
47
pyrogram/client/types/messages_and_media/poll_option.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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 pyrogram
|
||||
from ..pyrogram_type import PyrogramType
|
||||
|
||||
|
||||
class PollOption(PyrogramType):
|
||||
"""This object represents a Poll Option.
|
||||
|
||||
Args:
|
||||
text (``str``):
|
||||
Text of the poll option.
|
||||
|
||||
voters (``int``):
|
||||
The number of users who voted this option.
|
||||
|
||||
data (``bytes``):
|
||||
Unique data that identifies this option among all the other options in a poll.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
*,
|
||||
client: "pyrogram.client.ext.BaseClient",
|
||||
text: str,
|
||||
voters: int,
|
||||
data: bytes):
|
||||
super().__init__(client)
|
||||
|
||||
self.text = text
|
||||
self.voters = voters
|
||||
self.data = data
|
@@ -199,11 +199,11 @@ class Chat(PyrogramType):
|
||||
parsed_chat.can_set_sticker_set = full_chat.can_set_stickers
|
||||
parsed_chat.sticker_set_name = full_chat.stickerset
|
||||
|
||||
if full_chat.pinned_msg_id:
|
||||
parsed_chat.pinned_message = client.get_messages(
|
||||
parsed_chat.id,
|
||||
message_ids=full_chat.pinned_msg_id
|
||||
)
|
||||
if full_chat.pinned_msg_id:
|
||||
parsed_chat.pinned_message = client.get_messages(
|
||||
parsed_chat.id,
|
||||
message_ids=full_chat.pinned_msg_id
|
||||
)
|
||||
|
||||
if isinstance(full_chat.exported_invite, types.ChatInviteExported):
|
||||
parsed_chat.invite_link = full_chat.exported_invite.link
|
||||
|
Reference in New Issue
Block a user