2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-28 21:07:59 +00:00

Merge branch 'master' into new-api

# Conflicts:
#	pyrogram/client/client.py
This commit is contained in:
Dan 2018-03-26 13:46:48 +02:00
commit f3cf08d351
16 changed files with 1096 additions and 860 deletions

View File

@ -1,6 +1,6 @@
## Include
include COPYING COPYING.lesser NOTICE
recursive-include compiler *.tl *.tsv *.txt
include COPYING COPYING.lesser NOTICE requirements.txt
recursive-include compiler *.py *.tl *.tsv *.txt
## Exclude
prune pyrogram/api/errors/exceptions

View File

@ -29,42 +29,33 @@ Table of Contents
About
=====
**Pyrogram** is a fully functional Telegram Client Library written from the ground up in Python.
It offers simple and complete access to the `Telegram Messenger API`_ and is designed for Python
developers keen on building custom Telegram applications.
**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 in Python that interact with the MTProto API as both User and Bot.
Features
--------
- **Easy to setup**: Pyrogram can be easily installed and upgraded using **pip**, requires
a minimal set of dependencies (which are also automatically managed) and very few lines
of code to get started with.
- **Easy to setup**: Pyrogram can be easily installed using pip and requires very few lines of code to get started with.
- **Easy to use**: Pyrogram provides idiomatic, developer-friendly, clean and readable
Python code (either generated or hand-written) making the Telegram API simple to use.
- **Easy to use**: Pyrogram provides idiomatic, clean and readable Python code making the Telegram API simple to use.
- **High level**: Pyrogram automatically handles all the low-level details of
communication with the Telegram servers by implementing the
`MTProto Mobile Protocol v2.0`_ and the mechanisms needed for establishing
a reliable connection.
- **High-level**: Pyrogram automatically handles all the low-level details of communication with Telegram servers.
- **Fast**: Pyrogram's speed is boosted up by `TgCrypto`_, a high-performance, easy-to-install
Telegram Crypto Library written in C as a Python extension.
- **Updated**: Pyrogram makes use of the latest Telegram MTProto API version, currently Layer 76.
- **Updated**: Pyrogram makes use of the latest Telegram API version, currently `Layer 75`_.
- **Fast**: Pyrogram critical parts are boosted up by `TgCrypto`_, a high-performance Crypto Library written in pure C.
- **Documented**: Pyrogram API public methods are documented and resemble the well
established Telegram Bot API, thus offering a familiar look to Bot developers.
- **Documented**: Pyrogram API methods are documented and resemble the well established Telegram Bot API,
thus offering a familiar look to Bot developers.
- **Full API support**: Beside the simple, bot-like methods offered by the Pyrogram API,
the library also provides a complete, low-level access to every single Telegram API method.
- **Full API support**: Beside the simple Bot API-like methods, Pyrogram also provides an easy access to every single
Telegram MTProto API method allowing you to programmatically execute any action an official client is able to do, and more.
Requirements
------------
- Python 3.3 or higher.
- Python 3.4 or higher.
- A Telegram API key.
@ -75,17 +66,11 @@ Getting Started
Installation
------------
- You can easily install and upgrade the library using standard Python tools:
- You can install and upgrade Pyrogram using pip:
.. code:: shell
$ pip install --upgrade pyrogram
- Or, with TgCrypto_:
.. code:: shell
$ pip install --upgrade pyrogram[tgcrypto]
$ pip3 install --upgrade pyrogram
Configuration
-------------
@ -102,7 +87,7 @@ Configuration
Usage
-----
- And here's how Pyrogram looks like:
- And here is how Pyrogram looks like:
.. code:: python
@ -112,26 +97,25 @@ Usage
client.start()
client.send_message("me", "Hi there! I'm using Pyrogram")
client.send_photo("me", "/home/dan/pic.jpg", "Nice photo!")
client.stop()
That's all you need for getting started with Pyrogram. For more detailed information,
please refer to the Documentation_.
please refer to the Documentation_ and the Examples_ folder.
Documentation
=============
- The entire Pyrogram's documentation resides at https://docs.pyrogram.ml.
- The entire Pyrogram documentation resides at https://docs.pyrogram.ml.
Contribution
============
**You are very welcome to contribute** by either submitting pull requests or
reporting issues/bugs as well as suggesting best practices, ideas, enhancements
on both code and documentation. Any help is appreciated!
Pyrogram is brand new! **You are welcome to try it and help make it better** by either submitting pull
requests or reporting issues/bugs as well as suggesting best practices, ideas, enhancements on both code
and documentation. Any help is appreciated!
Feedback
@ -140,7 +124,6 @@ Feedback
Means for getting in touch:
- `Community`_
- `Telegram`_
- `GitHub`_
- `Email`_
@ -154,17 +137,11 @@ License
`GNU Lesser General Public License v3 or later (LGPLv3+)`_
.. _`Telegram Messenger API`: https://core.telegram.org/api#telegram-api
.. _`Telegram`: https://telegram.org/
.. _`MTProto Mobile Protocol v2.0`: https://core.telegram.org/mtproto
.. _`your own`: https://docs.pyrogram.ml/start/ProjectSetup#api-keys
.. _`Layer 75`: compiler/api/source/main_api.tl
.. _`your own`: https://github.com/pyrogram/pyrogram/wiki/Getting-Started#api-keys
.. _`Introduction`: https://github.com/pyrogram/pyrogram/wiki/Getting-Started
.. _`Telegram`: https://t.me/haskell
.. _`Examples`: https://github.com/pyrogram/pyrogram/blob/master/examples/README.md
.. _`Community`: https://t.me/PyrogramChat
@ -181,9 +158,9 @@ License
.. |header| raw:: html
<h1 align="center">
<a href="https://pyrogram.ml">
<div><img src="https://pyrogram.ml/images/icon.png" alt="Pyrogram Icon"></div>
<div><img src="https://pyrogram.ml/images/label.png" alt="Pyrogram Label"></div>
<a href="https://github.com/pyrogram/pyrogram">
<div><img src="https://media.pyrogram.ml/images/icon.png" alt="Pyrogram Icon"></div>
<div><img src="https://media.pyrogram.ml/images/label.png" alt="Pyrogram Label"></div>
</a>
</h1>
@ -204,11 +181,11 @@ License
</a>
<br><br>
<a href="compiler/api/source/main_api.tl">
<img src="https://www.pyrogram.ml/images/scheme.svg"
alt="Scheme Layer 75">
<img src="https://media.pyrogram.ml/images/scheme.svg"
alt="Scheme Layer 76">
</a>
<a href="https://github.com/pyrogram/tgcrypto">
<img src="https://www.pyrogram.ml/images/tgcrypto.svg"
<img src="https://media.pyrogram.ml/images/tgcrypto.svg"
alt="TgCrypto">
</a>
</p>
@ -221,7 +198,7 @@ License
.. |scheme| image:: https://www.pyrogram.ml/images/scheme.svg
:target: compiler/api/source/main_api.tl
:alt: Scheme Layer 75
:alt: Scheme Layer 76
.. |tgcrypto| image:: https://www.pyrogram.ml/images/tgcrypto.svg
:target: https://github.com/pyrogram/tgcrypto

View File

@ -148,6 +148,7 @@ messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAct
messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionScreenshotTaken#4792929b = MessageAction;
messageActionCustomAction#fae69f56 message:string = MessageAction;
messageActionBotAllowed#abe9affe domain:string = MessageAction;
dialog#e4def5db flags:# pinned:flags.2?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;
@ -300,8 +301,8 @@ updateRecentStickers#9a422c20 = Update;
updateConfig#a229dd06 = Update;
updatePtsChanged#3354678f = Update;
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
updateDialogPinned#d711a2cc flags:# pinned:flags.0?true peer:Peer = Update;
updatePinnedDialogs#d8caf68d flags:# order:flags.0?Vector<Peer> = Update;
updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update;
updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector<DialogPeer> = Update;
updateBotWebhookJSON#8317c0c3 data:DataJSON = Update;
updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update;
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
@ -335,11 +336,11 @@ photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> =
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#ea52fe5a dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes cdn_file_hashes:Vector<CdnFileHash> = upload.File;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector<FileHash> = upload.File;
dcOption#5d8c6cc 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 = DcOption;
config#9c840964 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> 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 chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_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 suggested_lang_code:flags.2?string lang_pack_version:flags.2?int disabled_features:Vector<DisabledFeature> = Config;
config#86b5778e 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 date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> 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 suggested_lang_code:flags.2?string lang_pack_version:flags.2?int = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
@ -444,8 +445,6 @@ stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
messages.allStickersNotModified#e86602c3 = messages.AllStickers;
messages.allStickers#edfd405f hash:int sets:Vector<StickerSet> = messages.AllStickers;
disabledFeature#ae636f24 feature:string description:string = DisabledFeature;
messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages;
contactLinkUnknown#5f4f9247 = ContactLink;
@ -483,7 +482,7 @@ inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
stickerSet#cd303b41 flags:# installed:flags.0?true archived:flags.1?true official:flags.2?true masks:flags.3?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
stickerSet#5585a139 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
@ -520,6 +519,8 @@ messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity;
messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity;
messageEntityMentionName#352dca58 offset:int length:int user_id:int = MessageEntity;
inputMessageEntityMentionName#208e68c9 offset:int length:int user_id:InputUser = MessageEntity;
messageEntityPhone#9b69e34b offset:int length:int = MessageEntity;
messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
@ -570,7 +571,7 @@ inputBotInlineMessageMediaVenue#aaafadc8 flags:# geo_point:InputGeoPoint title:s
inputBotInlineMessageMediaContact#2daf01a7 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineResult#2cbbe15a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultDocument#fff8fdc4 flags:# id:string type:string title:flags.1?string description:flags.2?string document:InputDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:InputBotInlineMessage = InputBotInlineResult;
@ -581,7 +582,7 @@ botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:f
botInlineMessageMediaVenue#4366232e flags:# geo:GeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineResult#9bebaeb9 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:BotInlineMessage = BotInlineResult;
botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;
messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector<BotInlineResult> cache_time:int users:Vector<User> = messages.BotResults;
@ -630,7 +631,7 @@ messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers;
messages.featuredStickers#f89d88e5 hash:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;
messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
messages.recentStickers#5ce20970 hash:int stickers:Vector<Document> = messages.RecentStickers;
messages.recentStickers#22f3afb3 hash:int packs:Vector<StickerPack> stickers:Vector<Document> dates:Vector<int> = messages.RecentStickers;
messages.archivedStickers#4fcba9c8 count:int sets:Vector<StickerSetCovered> = messages.ArchivedStickers;
@ -712,6 +713,7 @@ paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string e
paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials;
webDocument#c61acbd8 url:string access_hash:long size:int mime_type:string attributes:Vector<DocumentAttribute> dc_id:int = WebDocument;
webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;
@ -800,8 +802,6 @@ channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?tru
popularContact#5ce14175 client_id:long importers:int = PopularContact;
cdnFileHash#77eec38f offset:int limit:int hash:bytes = CdnFileHash;
messages.favedStickersNotModified#9e8fa6d3 = messages.FavedStickers;
messages.favedStickers#f37f2f16 hash:int packs:Vector<StickerPack> stickers:Vector<Document> = messages.FavedStickers;
@ -823,6 +823,15 @@ inputMessageID#a676a322 id:int = InputMessage;
inputMessageReplyTo#bad88395 id:int = InputMessage;
inputMessagePinned#86872538 = InputMessage;
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
dialogPeer#e56dbf05 peer:Peer = DialogPeer;
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = messages.FoundStickerSets;
fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -849,7 +858,7 @@ auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentC
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
account.registerDevice#1389cc token_type:int token:string app_sandbox:Bool other_uids:Vector<int> = Bool;
account.registerDevice#5cbea590 token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
@ -902,7 +911,7 @@ contacts.resetSaved#879537f1 = Bool;
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#191ba9c5 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.search#39e9ea0 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true peer:InputPeer max_id:int = messages.AffectedHistory;
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
@ -914,6 +923,7 @@ messages.forwardMessages#708e0195 flags:# silent:flags.5?true background:flags.6
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.hideReportSpam#a8f1709b peer:InputPeer = Bool;
messages.getPeerSettings#3672e09c peer:InputPeer = PeerSettings;
messages.report#bd82b658 peer:InputPeer id:Vector<int> reason:ReportReason = Bool;
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull;
messages.editChatTitle#dc452855 chat_id:int title:string = Updates;
@ -933,7 +943,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool;
messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages;
messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers;
messages.getStickers#85cb5182 flags:# exclude_featured:flags.0?true emoticon:string hash:string = messages.Stickers;
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
@ -961,7 +971,7 @@ messages.editMessage#5d1b8dd flags:# no_webpage:flags.1?true stop_geo_live:flags
messages.editInlineBotMessage#b0e08243 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = 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#2d9776b9 peers:Vector<InputPeer> = messages.PeerDialogs;
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool;
messages.getAllDrafts#6a3f8d65 = Updates;
messages.getFeaturedStickers#2dacca4f hash:int = messages.FeaturedStickers;
@ -979,8 +989,8 @@ messages.getInlineGameHighScores#f635e1b id:InputBotInlineMessageID user_id:Inpu
messages.getCommonChats#d0a48c4 user_id:InputUser max_id:int limit:int = messages.Chats;
messages.getAllChats#eba80ff0 except_ids:Vector<int> = messages.Chats;
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
messages.toggleDialogPin#3289be6a flags:# pinned:flags.0?true peer:InputPeer = Bool;
messages.reorderPinnedDialogs#959ff644 flags:# force:flags.0?true order:Vector<InputPeer> = Bool;
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
messages.getPinnedDialogs#e254d64e = messages.PeerDialogs;
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
@ -990,9 +1000,10 @@ messages.getFavedStickers#21ce0b0e hash:int = messages.FavedStickers;
messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool;
messages.getUnreadMentions#46578472 peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readMentions#f0189d3 peer:InputPeer = messages.AffectedHistory;
messages.getRecentLocations#249431e2 peer:InputPeer limit:int = messages.Messages;
messages.getRecentLocations#bbc45b09 peer:InputPeer limit:int hash:int = messages.Messages;
messages.sendMultiMedia#2095512f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> = Updates;
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
messages.searchStickerSets#c2b7d08b flags:# exclude_featured:flags.0?true q:string hash:int = messages.FoundStickerSets;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1008,8 +1019,9 @@ upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
upload.reuploadCdnFile#1af91c09 file_token:bytes request_token:bytes = Vector<CdnFileHash>;
upload.getCdnFileHashes#f715c87b file_token:bytes offset:int = Vector<CdnFileHash>;
upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector<FileHash>;
upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector<FileHash>;
upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<FileHash>;
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
@ -1085,4 +1097,4 @@ langpack.getStrings#2e1ee318 lang_code:string keys:Vector<string> = Vector<LangP
langpack.getDifference#b2e4d7d from_version:int = LangPackDifference;
langpack.getLanguages#800fd57d = Vector<LangPackLanguage>;
// LAYER 75
// LAYER 76

View File

@ -11,7 +11,7 @@ class {class_name}(Object):
"""
ID = {object_id}
def __init__(self{arguments}, **kwargs):
def __init__(self{arguments}):
{fields}
@staticmethod

View File

@ -2,12 +2,16 @@
This folder contains example scripts to show you how **Pyrogram** looks like.
You can start with [hello_world.py](https://github.com/pyrogram/pyrogram/blob/master/examples/hello_world.py) and continue
with the more advanced examples. Every script is working right away, meaning you can simply copy-paste and run, the only things
you have to change are the target chats (username, id) and file paths for sending media (photo, video, ...).
with the more advanced examples.
Every script is working right away (provided you correctly set up your credentials), meaning
you can simply copy-paste and run, the only things you have to change are the target chats (username, id) and file paths for
sending media (photo, video, ...).
- [**hello_world.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/hello_world.py)
- [**get_history.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/get_history.py)
- [**get_participants.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/get_participants.py)
- [**get_participants2.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/get_participants2.py)
- [**inline_bots.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/inline_bots.py)
- [**updates.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/updates.py)
- [**simple_echo.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/simple_echo.py)

View File

@ -0,0 +1,63 @@
import time
from string import ascii_lowercase
from pyrogram import Client
from pyrogram.api import functions, types
from pyrogram.api.errors import FloodWait
"""
This is an improved version of get_participants.py
Since Telegram will return at most 10.000 users for a single query, this script
repeats the search using numbers ("0" to "9") and all the available ascii letters ("a" to "z").
This can be further improved by also searching for non-ascii characters (e.g.: Japanese script),
as some user names may not contain ascii letters at all.
"""
client = Client("example")
client.start()
target = "username" # Target channel/supergroup username or id
users = {} # To ensure uniqueness, users will be stored in a dictionary with user_id as key
limit = 200 # Amount of users to retrieve for each API call (200 is the maximum)
# "" + "0123456789" + "abcdefghijklmnopqrstuvwxyz" (as list)
queries = [""] + [str(i) for i in range(10)] + list(ascii_lowercase)
for q in queries:
print("Searching for '{}'".format(q))
offset = 0 # For each query, offset restarts from 0
while True:
try:
participants = client.send(
functions.channels.GetParticipants(
channel=client.resolve_peer(target),
filter=types.ChannelParticipantsSearch(q),
offset=offset,
limit=limit,
hash=0
)
)
except FloodWait as e:
# Very large chats could trigger FloodWait.
# When happens, wait X seconds before continuing
print("Flood wait: {} seconds".format(e.x))
time.sleep(e.x)
continue
if not participants.participants:
print("Done searching for '{}'".format(q))
print()
break # No more participants left
# User information are stored in the participants.users list.
# Add those users to the dictionary
users.update({i.id: i for i in participants.users})
offset += len(participants.participants)
print("Total users: {}".format(len(users)))
client.stop()

View File

@ -23,7 +23,7 @@ __copyright__ = "Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance
"e" if sys.getfilesystemencoding() == "ascii" else "\xe8"
)
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__version__ = "0.6.2"
__version__ = "0.6.4"
from .api.errors import Error
from .client import ChatAction

File diff suppressed because it is too large Load Diff

View File

@ -81,7 +81,7 @@ class InputMedia:
width: int = 0,
height: int = 0,
duration: int = 0,
supports_streaming: bool = None):
supports_streaming: bool = True):
self.media = media
self.caption = caption
self.parse_mode = parse_mode

View File

@ -36,7 +36,7 @@ class Markdown:
CODE_DELIMITER = "`"
PRE_DELIMITER = "```"
MARKDOWN_RE = re.compile(r"```([\w ]*)\n([\w\W]*)(?:\n|)```|\[([^[(]+)\]\(([^])]+)\)|({d})(.+?)\5".format(
MARKDOWN_RE = re.compile(r"```([\w ]*)\n([\w\W]*)(?:\n|)```|\[(.+?)\]\((.+?)\)|({d})(.+?)\5".format(
d="|".join(
["".join(i) for i in [
["\{}".format(j) for j in i]

View File

@ -54,6 +54,7 @@ class Connection:
def close(self):
self.connection.close()
log.info("Disconnected")
def send(self, data: bytes):
with self.lock:

View File

@ -20,7 +20,15 @@ import logging
import socket
from collections import namedtuple
try:
import socks
except ImportError as e:
e.msg = (
"PySocks is missing and Pyrogram can't run without. "
"Please install it using \"pip3 install pysocks\"."
)
raise e
log = logging.getLogger(__name__)

View File

@ -16,52 +16,33 @@
# 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 logging
log = logging.getLogger(__name__)
try:
import tgcrypto
except ImportError:
log.warning(
"TgCrypto is missing! "
"Pyrogram will work the same, but at a much slower speed. "
except ImportError as e:
e.msg = (
"TgCrypto is missing and Pyrogram can't run without. "
"Please install it using \"pip3 install tgcrypto\". "
"More info: https://docs.pyrogram.ml/resources/TgCrypto"
)
is_fast = False
import pyaes
else:
log.info("Using TgCrypto")
is_fast = True
raise e
# TODO: Ugly IFs
class AES:
@classmethod
def ige_encrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
if is_fast:
return tgcrypto.ige_encrypt(data, key, iv)
else:
return cls.ige(data, key, iv, True)
@classmethod
def ige_decrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
if is_fast:
return tgcrypto.ige_decrypt(data, key, iv)
else:
return cls.ige(data, key, iv, False)
@staticmethod
def ctr_decrypt(data: bytes, key: bytes, iv: bytes, offset: int) -> bytes:
replace = int.to_bytes(offset // 16, byteorder="big", length=4)
replace = int.to_bytes(offset // 16, 4, "big")
iv = iv[:-4] + replace
if is_fast:
return tgcrypto.ctr_decrypt(data, key, iv)
else:
ctr = pyaes.AESModeOfOperationCTR(key)
ctr._counter._counter = list(iv)
return ctr.decrypt(data)
@staticmethod
def xor(a: bytes, b: bytes) -> bytes:
@ -70,23 +51,3 @@ class AES:
len(a),
"big",
)
@classmethod
def ige(cls, data: bytes, key: bytes, iv: bytes, encrypt: bool) -> bytes:
cipher = pyaes.AES(key)
iv_1 = iv[:16]
iv_2 = iv[16:]
data = [data[i: i + 16] for i in range(0, len(data), 16)]
if encrypt:
for i, chunk in enumerate(data):
iv_1 = data[i] = cls.xor(cipher.encrypt(cls.xor(chunk, iv_1)), iv_2)
iv_2 = chunk
else:
for i, chunk in enumerate(data):
iv_2 = data[i] = cls.xor(cipher.decrypt(cls.xor(chunk, iv_2)), iv_1)
iv_1 = chunk
return b"".join(data)

View File

@ -61,7 +61,7 @@ class Session:
INITIAL_SALT = 0x616e67656c696361
NET_WORKERS = 1
WAIT_TIMEOUT = 10
WAIT_TIMEOUT = 30
MAX_RETRIES = 5
ACKS_THRESHOLD = 8
PING_INTERVAL = 5
@ -122,8 +122,6 @@ class Session:
self.is_connected = Event()
def start(self):
terms = None
while True:
try:
self.connection.connect()
@ -141,7 +139,7 @@ class Session:
self.next_salt_thread.start()
if not self.is_cdn:
terms = self._send(
self._send(
functions.InvokeWithLayer(
layer,
functions.InitConnection(
@ -150,10 +148,10 @@ class Session:
self.SYSTEM_VERSION,
self.APP_VERSION,
"en", "", "en",
functions.help.GetTermsOfService(),
functions.help.GetConfig(),
)
)
)
).text
self.ping_thread = Thread(target=self.ping, name="PingThread")
self.ping_thread.start()
@ -168,8 +166,6 @@ class Session:
log.debug("Session started")
return terms
def stop(self):
self.is_connected.clear()
@ -190,6 +186,9 @@ class Session:
for i in range(self.NET_WORKERS):
self.recv_queue.put(None)
for i in self.results.values():
i.event.set()
log.debug("Session stopped")
def restart(self):
@ -401,7 +400,7 @@ class Session:
try:
return self._send(data)
except (OSError, TimeoutError):
log.warning("Retrying {}".format(type(data)))
(log.warning if i > 0 else log.info)("{}: {} Retrying {}".format(i, datetime.now(), type(data)))
continue
else:
return None

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
pysocks
tgcrypto

View File

@ -24,12 +24,15 @@ from setuptools import setup, find_packages
from compiler.api import compiler as api_compiler
from compiler.error import compiler as error_compiler
# from compiler.docs import compiler as docs_compiler
def requirements():
with open("requirements.txt", encoding="utf-8") as r:
return [i.strip() for i in r]
if len(argv) > 1 and argv[1] != "sdist":
api_compiler.start()
error_compiler.start()
# docs_compiler.start()
with open("pyrogram/__init__.py", encoding="utf-8") as f:
version = re.findall(r"__version__ = \"(.+)\"", f.read())[0]
@ -43,12 +46,12 @@ setup(
name="Pyrogram",
version=version,
description="Telegram MTProto API Client Library for Python",
url="https://github.com/pyrogram/pyrogram",
long_description=readme,
url="https://github.com/pyrogram",
download_url="https://github.com/pyrogram/pyrogram/releases/latest",
author="Dan Tès",
author_email="admin@pyrogram.ml",
license="LGPLv3+",
keywords="telegram mtproto api client library python",
long_description=readme,
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
@ -56,25 +59,28 @@ setup(
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: Implementation",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Internet",
"Topic :: Communications",
"Topic :: Communications :: Chat",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Libraries :: Python Modules"
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Libraries :: Application Frameworks"
],
packages=find_packages(),
zip_safe=False,
install_requires=[
"pyaes",
"pysocks"
],
extras_require={
"tgcrypto": [
"tgcrypto"
]
keywords="telegram chat messenger mtproto api client library python",
project_urls={
"Tracker": "https://github.com/pyrogram/pyrogram/issues",
"Community": "https://t.me/PyrogramChat",
"Source": "https://github.com/pyrogram/pyrogram",
"Documentation": "https://docs.pyrogram.ml",
},
include_package_data=True,
python_requires="~=3.4",
packages=find_packages(exclude=["compiler*"]),
zip_safe=False,
install_requires=requirements()
)