diff --git a/MANIFEST.in b/MANIFEST.in index 84d50dd4..168fb020 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ ## Include include COPYING COPYING.lesser NOTICE -recursive-include compiler *.tl *.tsv *.txt +recursive-include compiler *.py *.tl *.tsv *.txt ## Exclude prune pyrogram/api/errors/exceptions diff --git a/compiler/api/source/main_api.tl b/compiler/api/source/main_api.tl index b4d0e7a8..9ede3e28 100644 --- a/compiler/api/source/main_api.tl +++ b/compiler/api/source/main_api.tl @@ -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 = Update; +updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update; +updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector = 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 users:Vector = photos.photo#20212ca8 photo:Photo users:Vector = 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 = upload.File; +upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector = 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 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 = 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 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 = StickerPack; messages.allStickersNotModified#e86602c3 = messages.AllStickers; messages.allStickers#edfd405f hash:int sets:Vector = 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 documents:Vector = 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 cache_time:int users:Vector = messages.BotResults; @@ -630,7 +631,7 @@ messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers; messages.featuredStickers#f89d88e5 hash:int sets:Vector unread:Vector = messages.FeaturedStickers; messages.recentStickersNotModified#b17f890 = messages.RecentStickers; -messages.recentStickers#5ce20970 hash:int stickers:Vector = messages.RecentStickers; +messages.recentStickers#22f3afb3 hash:int packs:Vector stickers:Vector dates:Vector = messages.RecentStickers; messages.archivedStickers#4fcba9c8 count:int sets:Vector = 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 dc_id:int = WebDocument; +webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector = WebDocument; inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector = 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 stickers:Vector = 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 = 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 = Bool; -account.registerDevice#1389cc token_type:int token:string app_sandbox:Bool other_uids:Vector = Bool; +account.registerDevice#5cbea590 token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector = Bool; account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector = 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 = 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 = 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 reason:ReportReason = Bool; messages.getChats#3c6aa187 id:Vector = 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; messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool; messages.readMessageContents#36a73f77 id:Vector = 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 = 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 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 = messages.PeerDialogs; +messages.getPeerDialogs#e470bcfd peers:Vector = 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 = 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 = 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 = Bool; +messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool; +messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector = Bool; messages.getPinnedDialogs#e254d64e = messages.PeerDialogs; messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector = 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 = 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; -upload.getCdnFileHashes#f715c87b file_token:bytes offset:int = Vector; +upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector; +upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector; +upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector; help.getConfig#c4f9186b = Config; help.getNearestDc#1fb33026 = NearestDc; @@ -1085,4 +1097,4 @@ langpack.getStrings#2e1ee318 lang_code:string keys:Vector = Vector; -// LAYER 75 \ No newline at end of file +// LAYER 76 diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 20ac58bc..0c3bdb1d 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -24,7 +24,9 @@ import math import mimetypes import os import re +import shutil import struct +import tempfile import threading import time from collections import namedtuple @@ -120,7 +122,7 @@ class Client: INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:t\.me/joinchat/)?([\w-]+)$") DIALOGS_AT_ONCE = 100 - UPDATES_WORKERS = 2 + UPDATES_WORKERS = 1 DOWNLOAD_WORKERS = 1 def __init__(self, @@ -503,13 +505,17 @@ class Client: while True: media = self.download_queue.get() + temp_file_path = "" + final_file_path = "" if media is None: break try: media, file_name, done, progress, path = media - tmp_file_name = None + + directory, file_name = os.path.split(file_name) + directory = directory or "downloads" if isinstance(media, types.MessageMediaDocument): document = media.document @@ -535,7 +541,7 @@ class Client: elif isinstance(i, types.DocumentAttributeAnimated): file_name = file_name.replace("doc", "gif") - tmp_file_name = self.get_file( + temp_file_path = self.get_file( dc_id=document.dc_id, id=document.id, access_hash=document.access_hash, @@ -558,7 +564,7 @@ class Client: photo_loc = photo.sizes[-1].location - tmp_file_name = self.get_file( + temp_file_path = self.get_file( dc_id=photo_loc.dc_id, volume_id=photo_loc.volume_id, local_id=photo_loc.local_id, @@ -567,27 +573,24 @@ class Client: progress=progress ) - if file_name is not None: - path[0] = "downloads/{}".format(file_name) - - try: - os.remove("downloads/{}".format(file_name)) - except OSError: - pass - finally: - try: - os.renames("{}".format(tmp_file_name), "downloads/{}".format(file_name)) - except OSError: - pass + if temp_file_path: + final_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name))) + os.makedirs(directory, exist_ok=True) + shutil.move(temp_file_path, final_file_path) except Exception as e: log.error(e, exc_info=True) - finally: - done.set() try: - os.remove("{}".format(tmp_file_name)) + os.remove(temp_file_path) except OSError: pass + else: + # TODO: "" or None for faulty download, which is better? + # os.path methods return "" in case something does not exist, I prefer this. + # For now let's keep None + path[0] = final_file_path or None + finally: + done.set() log.debug("{} stopped".format(name)) @@ -616,6 +619,25 @@ class Client: ) or getattr(update, "channel_id", None) pts = getattr(update, "pts", None) + pts_count = getattr(update, "pts_count", None) + + if isinstance(update, types.UpdateNewChannelMessage): + diff = self.send( + functions.updates.GetChannelDifference( + channel=self.resolve_peer(update.message.to_id.channel_id), + filter=types.ChannelMessagesFilter( + ranges=[types.MessageRange( + min_id=update.message.id, + max_id=update.message.id + )] + ), + pts=pts - pts_count, + limit=pts + ) + ) + + updates.users += diff.users + updates.chats += diff.chats if channel_id and pts: if channel_id not in self.channels_pts: @@ -2225,9 +2247,9 @@ class Client: version=version ) - file_name = "download_{}.temp".format(MsgId()) limit = 1024 * 1024 offset = 0 + file_name = "" try: r = session.send( @@ -2239,7 +2261,9 @@ class Client: ) if isinstance(r, types.upload.File): - with open(file_name, "wb") as f: + with tempfile.NamedTemporaryFile('wb', delete=False) as f: + file_name = f.name + while True: chunk = r.bytes @@ -2263,7 +2287,7 @@ class Client: ) ) - if isinstance(r, types.upload.FileCdnRedirect): + elif isinstance(r, types.upload.FileCdnRedirect): cdn_session = Session( r.dc_id, self.test_mode, @@ -2276,7 +2300,9 @@ class Client: cdn_session.start() try: - with open(file_name, "wb") as f: + with tempfile.NamedTemporaryFile('wb', delete=False) as f: + file_name = f.name + while True: r2 = cdn_session.send( functions.upload.GetCdnFile( @@ -2334,11 +2360,18 @@ class Client: if len(chunk) < limit: break except Exception as e: - log.error(e) + raise e finally: cdn_session.stop() except Exception as e: - log.error(e) + log.error(e, exc_info=True) + + try: + os.remove(file_name) + except OSError: + pass + + return "" else: return file_name finally: @@ -2597,19 +2630,20 @@ class Client: def download_media(self, message: types.Message, - file_name: str = None, + file_name: str = "", block: bool = True, progress: callable = None): """Use this method to download the media from a Message. - Files are saved in the *downloads* folder. - Args: message (:obj:`Message `): The Message containing the media. file_name (:obj:`str`, optional): - Specify a custom *file_name* to be used instead of the one provided by Telegram. + A custom *file_name* to be used instead of the one provided by Telegram. + By default, all files are downloaded in the *downloads* folder in your working directory. + You can also specify a path for downloading files in a custom location: paths that end with "/" + are considered directories. All non-existent folders will be created automatically. block (:obj:`bool`, optional): Blocks the code execution until the file has been downloaded. @@ -2627,7 +2661,7 @@ class Client: The size of the file. Returns: - The relative path of the downloaded file. + On success, the absolute path of the downloaded file as string is returned, None otherwise. Raises: :class:`pyrogram.Error` @@ -2653,26 +2687,27 @@ class Client: def download_photo(self, photo: types.Photo or types.UserProfilePhoto or types.ChatPhoto, - file_name: str = None, + file_name: str = "", block: bool = True): """Use this method to download a photo not contained inside a Message. For example, a photo of a User or a Chat/Channel. - Photos are saved in the *downloads* folder. - Args: photo (:obj:`Photo ` | :obj:`UserProfilePhoto ` | :obj:`ChatPhoto `): The photo object. file_name (:obj:`str`, optional): - Specify a custom *file_name* to be used. + A custom *file_name* to be used instead of the one provided by Telegram. + By default, all photos are downloaded in the *downloads* folder in your working directory. + You can also specify a path for downloading photos in a custom location: paths that end with "/" + are considered directories. All non-existent folders will be created automatically. block (:obj:`bool`, optional): Blocks the code execution until the photo has been downloaded. Defaults to True. Returns: - The relative path of the downloaded photo. + On success, the absolute path of the downloaded photo as string is returned, None otherwise. Raises: :class:`pyrogram.Error` diff --git a/pyrogram/client/style/markdown.py b/pyrogram/client/style/markdown.py index e39ac876..f3c7805d 100644 --- a/pyrogram/client/style/markdown.py +++ b/pyrogram/client/style/markdown.py @@ -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] diff --git a/pyrogram/connection/connection.py b/pyrogram/connection/connection.py index aa958a7a..02f57efc 100644 --- a/pyrogram/connection/connection.py +++ b/pyrogram/connection/connection.py @@ -54,6 +54,7 @@ class Connection: def close(self): self.connection.close() + log.info("Disconnected") def send(self, data: bytes): with self.lock: diff --git a/setup.py b/setup.py index 560f91e9..9c0068c6 100644 --- a/setup.py +++ b/setup.py @@ -22,13 +22,11 @@ from sys import argv from setuptools import setup, find_packages from compiler.api import compiler as api_compiler -from compiler.docs import compiler as docs_compiler from compiler.error import compiler as error_compiler 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] @@ -55,7 +53,6 @@ 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", @@ -76,17 +73,11 @@ setup( "Source": "https://github.com/pyrogram/pyrogram", "Documentation": "https://docs.pyrogram.ml", }, - python_requires="~=3.3", - packages=find_packages(), + python_requires="~=3.4", + packages=find_packages(exclude=["compiler*"]), zip_safe=False, install_requires=[ - "pyaes", - "pysocks" - ], - extras_require={ - "tgcrypto": [ - "tgcrypto" - ] - }, - include_package_data=True, + "pysocks", + "tgcrypto" + ] )