4
4
import os
5
5
6
6
from pyrogram import filters
7
- from pyrogram .errors import MessageDeleteForbidden
7
+ from pyrogram .errors import MessageDeleteForbidden , MessageIdInvalid
8
8
from pyrogram .types import Message , CallbackQuery , InlineKeyboardMarkup , InlineKeyboardButton
9
9
10
- from FileToLink import bot , Config
10
+ from FileToLink import bot , Config , Strings
11
11
12
12
13
13
class Worker :
14
14
def __init__ (self , msg : Message ):
15
+ """
16
+ :param msg: Message from Archive Channel
17
+ """
15
18
if msg .empty :
16
19
raise ValueError
17
20
self .msg = msg
21
+ self .archive_id = msg .message_id
18
22
self .media = (msg .video or msg .document or msg .photo or msg .audio or
19
23
msg .voice or msg .video_note or msg .sticker or msg .animation )
20
24
self .size = self .media .file_size
21
25
self .id = self .media .file_unique_id
22
- self .link = None
26
+ self .link = f' { Config . Link_Root } dl/ { self . archive_id } '
23
27
self .current_dl : int = 0 # Number of currently downloading parts
24
28
25
29
if hasattr (self .media , 'mime_type' ) and self .media .mime_type not in (None , '' ):
@@ -53,11 +57,9 @@ def __init__(self, msg: Message):
53
57
self .parts = [False for _ in
54
58
range (int (self .size / Config .Part_size ) + (1 if self .size % Config .Part_size else 0 ))]
55
59
self .done = False # If All parts are downloaded
60
+ self .fast = False # If User update to Fast Link
56
61
AllWorkers .add (self )
57
62
58
- def set_link (self , archive_id : int ):
59
- self .link = f'{ Config .Link_Root } dl/{ archive_id } '
60
-
61
63
async def create_file (self ):
62
64
"""
63
65
Create empty file with same size of real file
@@ -151,36 +153,38 @@ def part_number(self, byte_number: int):
151
153
152
154
class Workers :
153
155
def __init__ (self ):
154
- """
155
- Store Workers by file_unique_id and by archive_id
156
- """
156
+ """ Store Workers by file_unique_id and by archive_id """
157
157
self .by_file_id = {}
158
158
self .by_archive_id = {}
159
159
160
160
def get (self , archive_id : int = None , file_id : str = None ):
161
+ """Get the worker by archive_id or by file_id"""
161
162
if archive_id is not None and archive_id in self .by_archive_id :
162
163
return self .by_archive_id [archive_id ]
163
164
elif file_id is not None and file_id in self .by_file_id :
164
165
return self .by_file_id [file_id ]
165
166
else :
166
167
return None
167
168
168
- def add (self , worker , archive_id : int = None ):
169
+ def add (self , worker ):
170
+ """Add the worker to <self.by_file_id> and <self.by_archive_id>"""
169
171
if worker .id not in self .by_file_id :
170
172
self .by_file_id [worker .id ] = worker
171
- if archive_id is not None and archive_id not in self .by_archive_id :
172
- self .by_archive_id [archive_id ] = worker
173
-
174
- def remove (self , archive_id : int = None , file_id : str = None ):
175
- if archive_id is not None and archive_id in self .by_archive_id :
176
- del self .by_file_id [self .by_archive_id [archive_id ].id ]
173
+ if worker .msg .message_id not in self .by_archive_id :
174
+ self .by_archive_id [worker .archive_id ] = worker
175
+
176
+ def remove (self , archive_id : int ):
177
+ """Remove the worker from <self.by_file_id> and <self.by_archive_id>"""
178
+ if archive_id in self .by_archive_id :
179
+ file_id = self .by_archive_id [archive_id ].id
180
+ if file_id in self .by_file_id :
181
+ del self .by_file_id [file_id ]
177
182
del self .by_archive_id [archive_id ]
178
- elif file_id is not None and file_id in self .by_file_id :
179
- del self .by_file_id [file_id ]
180
183
181
184
182
185
AllWorkers = Workers ()
183
186
NotFound = [] # Store IDs of messages that not exist in Archive Channel
187
+ FastProcesses = {} # {User_ID: Number_Of_Link_Updating}
184
188
185
189
186
190
async def create_worker (archive_msg_id ):
@@ -190,17 +194,84 @@ async def create_worker(archive_msg_id):
190
194
if msg .empty or not msg .media :
191
195
raise ValueError
192
196
worker = Worker (msg )
193
- AllWorkers .add (worker , archive_id = archive_msg_id )
197
+ AllWorkers .add (worker )
194
198
await worker .create_file ()
195
199
return worker
196
200
197
201
202
+ @bot .on_callback_query (filters .create (lambda _ , __ , cb : cb .data .split ('|' )[0 ] == 'fast' ))
203
+ async def update_to_fast_link (_ , cb : CallbackQuery ):
204
+ msg = cb .message
205
+ user_id = msg .chat .id
206
+ if user_id in FastProcesses and FastProcesses [user_id ] >= Config .Max_Fast_Processes :
207
+ await cb .answer (Strings .update_limited , show_alert = True )
208
+ return
209
+
210
+ archive_id = int (cb .data .split ('|' )[1 ])
211
+ worker : Worker = AllWorkers .get (archive_id = archive_id )
212
+ if worker is None :
213
+ try :
214
+ worker = await create_worker (archive_id )
215
+ except (ValueError , MessageIdInvalid ):
216
+ await cb .answer (Strings .file_not_found , show_alert = True )
217
+ return
218
+ if worker .fast :
219
+ await cb .answer (Strings .already_updated , show_alert = True )
220
+ return
221
+
222
+ buttons = cb .message .reply_markup .inline_keyboard
223
+ update_button_row = - 1 # Last Row
224
+ old_data = buttons [update_button_row ][0 ].callback_data
225
+ buttons [update_button_row ][0 ].text = Strings .wait_update
226
+ new_data = f"fast-prog|{ archive_id } "
227
+ buttons [update_button_row ][0 ].callback_data = new_data
228
+
229
+ await cb .answer (Strings .wait )
230
+ await cb .message .edit_reply_markup (InlineKeyboardMarkup (buttons ))
231
+ progress = await msg .reply_text (
232
+ Strings .wait_update , reply_to_message_id = msg .message_id ,
233
+ reply_markup = InlineKeyboardMarkup ([[InlineKeyboardButton (Strings .progress , callback_data = new_data )]]))
234
+
235
+ if user_id in FastProcesses :
236
+ FastProcesses [user_id ] += 1
237
+ else :
238
+ FastProcesses [user_id ] = 1
239
+
240
+ await worker .dl_all ()
241
+ worker .fast = True
242
+
243
+ FastProcesses [user_id ] -= 1
244
+
245
+ buttons [update_button_row ][0 ].text = Strings .re_update_link
246
+ buttons [update_button_row ][0 ].callback_data = old_data
247
+ await msg .edit_reply_markup (InlineKeyboardMarkup (buttons ))
248
+ await progress .edit_text (Strings .fast )
249
+
250
+
251
+ @bot .on_callback_query (filters .create (lambda _ , __ , cb : cb .data .split ('|' )[0 ] == 'fast-prog' ))
252
+ async def fast_progress (_ , cb : CallbackQuery ):
253
+ archive_id = int (cb .data .split ('|' )[1 ])
254
+ worker = AllWorkers .get (archive_id = archive_id )
255
+ if worker is None :
256
+ await cb .answer (Strings .file_not_found , show_alert = True )
257
+ return
258
+ downloaded = len ([i for i in worker .parts if i ])
259
+ total = len (worker .parts )
260
+ await cb .answer (progress_bar (downloaded , total ), show_alert = True )
261
+
262
+
198
263
@bot .on_callback_query (filters .create (lambda _ , __ , cb : cb .data == 'delete-file' ))
199
264
async def delete_file_handler (_ , cb : CallbackQuery ):
200
265
msg = cb .message
201
266
AllWorkers .remove (msg .message_id )
202
267
try :
203
268
await msg .delete ()
204
269
except MessageDeleteForbidden :
205
- button = InlineKeyboardButton ("⚠️You can delete it" , callback_data = 'time-out' )
270
+ button = InlineKeyboardButton (Strings . delete_manually_button , callback_data = 'time-out' )
206
271
await msg .edit_reply_markup (InlineKeyboardMarkup ([[button ]]))
272
+
273
+
274
+ def progress_bar (current , total , length = 16 , finished = '█' , unfinished = '░' ):
275
+ rate = current / total
276
+ finished_len = int (length * rate ) if rate <= 1 else length
277
+ return f'{ finished * finished_len } { unfinished * (length - finished_len )} { int (rate * 100 )} %'
0 commit comments