Cxops commited on
Commit
8a77e1d
·
verified ·
1 Parent(s): 717697e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -406
app.py CHANGED
@@ -1,473 +1,234 @@
1
  import os
2
- import sys
3
- import time
4
- import base64
5
- import hashlib
6
  import shutil
7
  import threading
8
- import asyncio
9
- import tempfile
10
- from pathlib import Path
11
- from typing import Optional
12
 
13
- import requests
14
  from flask import Flask
 
15
  from pyrogram import Client, filters
16
  from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
17
- from huggingface_hub import HfApi, hf_hub_download, create_commit, CommitOperationAdd
18
- from cryptography.fernet import Fernet
19
 
20
- # --------------- CONFIG ---------------
 
 
 
 
 
21
  API_ID = int(os.environ["API_ID"])
22
  API_HASH = os.environ["API_HASH"]
23
  BOT_TOKEN = os.environ["BOT_TOKEN"]
24
  HF_TOKEN = os.environ["HF_TOKEN"]
25
- OBFUSCATION_KEY = os.environ.get("OBFUSCATION_KEY", "change-me-to-a-secret-string")
26
 
27
  DATASET_REPO = "Cxops/Bzxv"
28
- MAX_FILE_SIZE_TG = 1900 * 1024 * 1024 # 1900 MB per part (safe margin)
29
- MIN_FREE_DISK = 45 * 1024 * 1024 * 1024 # 45 GB
30
- KEEPALIVE_INTERVAL = 300 # 5 minutes
31
-
32
- # --------------- ENCRYPTION SETUP ---------------
33
- fernet_key = base64.urlsafe_b64encode(hashlib.sha256(OBFUSCATION_KEY.encode()).digest())
34
- fernet = Fernet(fernet_key)
35
-
36
- def encrypt_text(plain: str) -> str:
37
- token = fernet.encrypt(plain.encode())
38
- # URL‑safe base64 without padding (safe for filenames)
39
- return base64.urlsafe_b64encode(token).decode().rstrip("=")
40
-
41
- def decrypt_text(encoded: str) -> str:
42
- # Add padding back
43
- padding = 4 - len(encoded) % 4
44
- if padding != 4:
45
- encoded += "=" * padding
46
- token = base64.urlsafe_b64decode(encoded.encode())
47
- return fernet.decrypt(token).decode()
48
-
49
- def get_encrypted_folder(user_id: int) -> str:
50
- return encrypt_text(str(user_id))
51
-
52
- def get_encrypted_filename(original: str) -> str:
53
- return encrypt_text(original)
54
-
55
- # --------------- FLASK HEALTH SERVER ---------------
56
  web = Flask(__name__)
57
 
58
  @web.route("/")
59
  def home():
60
- return "Telegram HF Storage Bot Running"
61
 
62
  def run_web():
63
  web.run(host="0.0.0.0", port=7860)
64
 
65
- # --------------- HF CLIENT ---------------
 
 
 
66
  hf = HfApi(token=HF_TOKEN)
67
 
68
- # --------------- PYROGRAM BOT ---------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  app = Client(
70
- "storage_bot",
71
  api_id=API_ID,
72
  api_hash=API_HASH,
73
  bot_token=BOT_TOKEN
74
  )
75
 
76
- # --------------- ASYNC QUEUES & STATE ---------------
77
- upload_queue = asyncio.Queue()
78
- active_jobs = {} # job_id -> {status, cancel_event, message, ...}
79
- processing_now = False # simple mutex for the worker
80
 
81
- # --------------- HELPERS ---------------
82
-
83
- def cleanup(path: str):
84
  try:
85
- if os.path.isdir(path):
86
- shutil.rmtree(path, ignore_errors=True)
87
- elif os.path.isfile(path):
88
- os.remove(path)
89
- except Exception:
90
  pass
91
 
92
- def get_free_disk() -> int:
93
- """Return free space in bytes on the current filesystem."""
94
- st = shutil.disk_usage("/")
95
- return st.free
96
-
97
- async def progress_updater(job_id: int, msg, cancel_event: asyncio.Event, total_bytes: Optional[int] = None):
98
- """Update message every 5 seconds with a progress indicator (elapsed time or percentage)."""
99
- start = time.time()
100
- while not cancel_event.is_set():
101
- elapsed = int(time.time() - start)
102
- text = f"⏳ Working... {elapsed}s elapsed"
103
- if total_bytes:
104
- # can't show real bytes, just a generic message
105
- pass
106
- try:
107
- await msg.edit_text(text, reply_markup=InlineKeyboardMarkup([
108
- [InlineKeyboardButton("❌ Cancel", callback_data=f"cancel_job:{job_id}")]
109
- ]))
110
- except Exception:
111
- break
112
- await asyncio.sleep(5)
113
- # Final cancellation message will be set by the caller
114
-
115
- # --------------- UPLOAD / DOWNLOAD LOGIC ---------------
116
-
117
- async def do_upload_job(user_id: int, chat_id: int, file_msg, orig_filename: str, job_id: int, cancel_event: asyncio.Event, status_msg):
118
- """Download from Telegram, upload to HF, update progress, handle cancel."""
119
- temp_dir = tempfile.mkdtemp()
120
- try:
121
- # 1. Download file from Telegram
122
- await status_msg.edit_text("⬇️ Downloading from Telegram...",
123
- reply_markup=InlineKeyboardMarkup([
124
- [InlineKeyboardButton("❌ Cancel", callback_data=f"cancel_job:{job_id}")]
125
- ]))
126
- local_path = await file_msg.download(file_name=os.path.join(temp_dir, orig_filename))
127
- if cancel_event.is_set():
128
- return
129
-
130
- # 2. Upload to Hugging Face dataset
131
- await status_msg.edit_text("⬆️ Uploading to Hugging Face...",
132
- reply_markup=InlineKeyboardMarkup([
133
- [InlineKeyboardButton("❌ Cancel", callback_data=f"cancel_job:{job_id}")]
134
- ]))
135
- # Encrypt folder + filename
136
- enc_folder = get_encrypted_folder(user_id)
137
- enc_filename = get_encrypted_filename(orig_filename)
138
- repo_path = f"{enc_folder}/{enc_filename}"
139
-
140
- # Use a synchronous upload in an executor, keep updating progress
141
- loop = asyncio.get_event_loop()
142
- upload_done = loop.create_future()
143
-
144
- def sync_upload():
145
- try:
146
- hf.upload_file(
147
- path_or_fileobj=local_path,
148
- path_in_repo=repo_path,
149
- repo_id=DATASET_REPO,
150
- repo_type="dataset",
151
- )
152
- return True
153
- except Exception as e:
154
- raise e
155
-
156
- task = loop.run_in_executor(None, sync_upload)
157
-
158
- # Progress task runs in background
159
- progress_task = asyncio.create_task(progress_updater(job_id, status_msg, cancel_event))
160
-
161
- # Wait for upload to finish or cancel
162
- while not task.done():
163
- if cancel_event.is_set():
164
- # Cancel is set – we cannot stop the in‑flight upload, but we can delete the file afterwards
165
- break
166
- await asyncio.sleep(1)
167
-
168
- # If cancelled while uploading, we still wait for the upload to finish (or timeout) so we can delete it
169
- if cancel_event.is_set():
170
- # Wait for upload to finish (with a timeout)
171
- try:
172
- await asyncio.wait_for(task, timeout=30) # hope it finishes soon
173
- except asyncio.TimeoutError:
174
- pass # can't delete if still running, but at least we tried
175
- # Delete the uploaded file from HF
176
- try:
177
- hf.delete_file(
178
- path_in_repo=repo_path,
179
- repo_id=DATASET_REPO,
180
- repo_type="dataset",
181
- )
182
- except Exception:
183
- pass
184
- progress_task.cancel()
185
- await status_msg.edit_text("❌ Upload cancelled.",
186
- reply_markup=None)
187
- return
188
 
189
- # Normal completion
190
- await task # raise any exception
191
- progress_task.cancel()
192
- await status_msg.edit_text(f"✅ Uploaded: `{orig_filename}`",
193
- reply_markup=None)
 
 
194
 
195
- except Exception as e:
196
- await status_msg.edit_text(f"❌ Upload failed: {e}",
197
- reply_markup=None)
198
- finally:
199
- cleanup(temp_dir)
 
 
200
 
201
- async def do_download_job(chat_id: int, enc_path: str, job_id: int, cancel_event: asyncio.Event, status_msg):
202
- """Download from HF, split if >2GB, send parts to user, progress updates."""
203
- temp_dir = tempfile.mkdtemp()
204
  try:
205
- # Decrypt original filename from path
206
- _, enc_filename = enc_path.split("/", 1)
207
- orig_filename = decrypt_text(enc_filename)
 
208
 
209
- await status_msg.edit_text("⬇️ Downloading from dataset...",
210
- reply_markup=InlineKeyboardMarkup([
211
- [InlineKeyboardButton("❌ Cancel", callback_data=f"cancel_job:{job_id}")]
212
- ]))
213
 
214
- loop = asyncio.get_event_loop()
215
- download_done = loop.create_future()
216
 
217
- def sync_download():
218
- return hf_hub_download(
219
- repo_id=DATASET_REPO,
220
- repo_type="dataset",
221
- filename=enc_path,
222
- token=HF_TOKEN,
223
- local_dir=temp_dir,
224
- )
225
 
226
- task = loop.run_in_executor(None, sync_download)
227
- progress_task = asyncio.create_task(progress_updater(job_id, status_msg, cancel_event))
228
-
229
- while not task.done():
230
- if cancel_event.is_set():
231
- # wait a bit then cancel
232
- break
233
- await asyncio.sleep(1)
234
-
235
- if cancel_event.is_set():
236
- progress_task.cancel()
237
- await status_msg.edit_text("❌ Download cancelled.",
238
- reply_markup=None)
239
- return
240
-
241
- local_file = await task
242
- progress_task.cancel()
243
-
244
- # Check file size
245
- file_size = os.path.getsize(local_file)
246
- if file_size <= MAX_FILE_SIZE_TG:
247
- # Send as single file
248
- await status_msg.edit_text("📤 Sending file to Telegram...",
249
- reply_markup=None)
250
- await app.send_document(
251
- chat_id,
252
- document=local_file,
253
- file_name=orig_filename,
254
- caption=orig_filename
255
- )
256
- await status_msg.delete()
257
- else:
258
- # Split into parts
259
- await status_msg.edit_text("📤 Splitting and sending...",
260
- reply_markup=None)
261
- part_size = MAX_FILE_SIZE_TG
262
- num_parts = -(-file_size // part_size) # ceil division
263
- with open(local_file, "rb") as f:
264
- for i in range(1, num_parts + 1):
265
- if cancel_event.is_set():
266
- await status_msg.edit_text("❌ Cancelled during send.")
267
- return
268
- chunk = f.read(part_size)
269
- part_name = f"{orig_filename}.part{i}of{num_parts}"
270
- part_path = os.path.join(temp_dir, part_name)
271
- with open(part_path, "wb") as p:
272
- p.write(chunk)
273
- await app.send_document(
274
- chat_id,
275
- document=part_path,
276
- file_name=part_name,
277
- caption=f"{orig_filename} – Part {i}/{num_parts}"
278
- )
279
- os.remove(part_path)
280
- await status_msg.delete()
281
 
282
  except Exception as e:
283
- await status_msg.edit_text(f"❌ Download failed: {e}")
284
- finally:
285
- cleanup(temp_dir)
286
 
287
- # --------------- QUEUE WORKER ---------------
288
- async def upload_worker():
289
- """Process upload jobs one by one, respecting disk space."""
290
- global processing_now
291
- while True:
292
- job = await upload_queue.get()
293
- user_id, chat_id, file_msg, orig_filename, job_id = job
294
- cancel_event = asyncio.Event()
295
- active_jobs[job_id]["cancel_event"] = cancel_event
296
- active_jobs[job_id]["status"] = "running"
297
-
298
- # Check disk space
299
- while get_free_disk() < MIN_FREE_DISK:
300
- # Not enough space, wait a bit
301
- await asyncio.sleep(10)
302
-
303
- # Create a new status message
304
- status_msg = await app.send_message(
305
- chat_id,
306
- "⏳ Starting upload...",
307
- reply_markup=InlineKeyboardMarkup([
308
- [InlineKeyboardButton("❌ Cancel", callback_data=f"cancel_job:{job_id}")]
309
- ])
310
  )
311
- active_jobs[job_id]["status_msg"] = status_msg
312
 
313
- try:
314
- await do_upload_job(user_id, chat_id, file_msg, orig_filename, job_id, cancel_event, status_msg)
315
- finally:
316
- # Cleanup
317
- active_jobs.pop(job_id, None)
318
- upload_queue.task_done()
319
 
320
- # --------------- BOT HANDLERS ---------------
321
 
322
- @app.on_message(filters.command("start"))
323
- async def start_cmd(_, message):
324
- await message.reply_text(
325
- "Send me a file to upload it to the dataset.\n"
326
- "/files – list your uploaded files"
327
- )
328
 
329
- @app.on_message(filters.command("files"))
330
- async def list_files(_, message):
331
- user_id = message.from_user.id
332
- enc_folder = get_encrypted_folder(user_id)
333
 
334
- try:
335
- all_files = hf.list_repo_files(repo_id=DATASET_REPO, repo_type="dataset")
336
- user_files = [f for f in all_files if f.startswith(enc_folder + "/")]
337
- if not user_files:
338
- return await message.reply_text("You have no uploaded files.")
339
 
340
- buttons = []
341
- for path in user_files:
342
- _, enc_name = path.split("/", 1)
343
- try:
344
- orig_name = decrypt_text(enc_name)
345
- except Exception:
346
- orig_name = enc_name # fallback
347
- buttons.append([InlineKeyboardButton(orig_name[:60], callback_data=f"get:{path}")])
348
 
349
- await message.reply_text(
350
- "Your uploaded files:",
351
- reply_markup=InlineKeyboardMarkup(buttons)
352
- )
353
- except Exception as e:
354
- await message.reply_text(f"Error listing files: {e}")
355
 
356
- @app.on_callback_query(filters.regex("^get:"))
357
- async def get_file_callback(_, query):
358
- path = query.data.replace("get:", "")
359
- job_id = int(time.time() * 1000) # simple unique id
360
- cancel_event = asyncio.Event()
361
- active_jobs[job_id] = {
362
- "status": "running",
363
- "cancel_event": cancel_event,
364
- "type": "download"
365
- }
366
-
367
- status_msg = await query.message.edit_text(
368
- "⏳ Preparing download...",
369
- reply_markup=InlineKeyboardMarkup([
370
- [InlineKeyboardButton("❌ Cancel", callback_data=f"cancel_job:{job_id}")]
371
- ])
372
- )
373
- active_jobs[job_id]["status_msg"] = status_msg
374
-
375
- asyncio.create_task(do_download_job(
376
- query.message.chat.id,
377
- path,
378
- job_id,
379
- cancel_event,
380
- status_msg
381
- ))
382
-
383
- @app.on_callback_query(filters.regex("^cancel_job:"))
384
- async def cancel_job_callback(_, query):
385
- _, job_id_str = query.data.split(":")
386
- job_id = int(job_id_str)
387
- if job_id in active_jobs:
388
- active_jobs[job_id]["cancel_event"].set()
389
- await query.answer("Cancelling...")
390
- else:
391
- await query.answer("Job not found.")
392
-
393
- @app.on_callback_query(filters.regex("^upload:"))
394
- async def upload_callback(_, query):
395
- # Data: upload:user_id:message_id:orig_filename
396
- _, user_id_str, msg_id_str, orig_filename = query.data.split(":", 3)
397
- user_id = int(user_id_str)
398
- chat_id = query.message.chat.id
399
-
400
- # Find the original file message
401
  try:
402
- file_msg = await app.get_messages(chat_id, int(msg_id_str))
403
- except Exception:
404
- return await query.answer("Original message missing.", show_alert=True)
405
 
406
- if not file_msg:
407
- return await query.answer("File no longer available.", show_alert=True)
408
 
409
- job_id = int(time.time() * 1000)
410
- active_jobs[job_id] = {"status": "queued"}
411
 
412
- await upload_queue.put((user_id, chat_id, file_msg, orig_filename, job_id))
 
413
 
414
- await query.message.edit_text(
415
- f"📦 `{orig_filename}` added to upload queue.\n"
416
- "You will be notified when it starts.",
417
- reply_markup=None
418
- )
419
 
420
- @app.on_callback_query(filters.regex("^cancel_upload:"))
421
- async def cancel_upload_prompt(_, query):
422
- await query.message.delete()
423
-
424
- @app.on_message(filters.document | filters.video | filters.audio | filters.photo)
425
- async def on_file(_, message):
426
- # Determine file name
427
- if message.document:
428
- filename = message.document.file_name
429
- elif message.video:
430
- filename = message.video.file_name or f"{message.video.file_unique_id}.mp4"
431
- elif message.audio:
432
- filename = message.audio.file_name or f"{message.audio.file_unique_id}.mp3"
433
- else: # photo
434
- filename = f"{message.photo.file_unique_id}.jpg"
435
-
436
- # Build inline keyboard
437
- kb = InlineKeyboardMarkup([
438
- [InlineKeyboardButton("⬆️ Upload File", callback_data=f"upload:{message.from_user.id}:{message.id}:{filename}")],
439
- [InlineKeyboardButton("❌ Cancel", callback_data="cancel_upload:0")]
440
- ])
441
-
442
- await message.reply_text(
443
- f"Do you want to upload `{filename}`?",
444
- reply_markup=kb
445
- )
446
 
447
- # --------------- KEEPALIVE ---------------
448
- def keepalive():
449
- while True:
450
- try:
451
- requests.get("http://localhost:7860/", timeout=10)
452
- except Exception:
453
- pass
454
- time.sleep(KEEPALIVE_INTERVAL)
455
 
456
- # --------------- MAIN ---------------
457
- async def main():
458
- # Start the upload worker
459
- asyncio.create_task(upload_worker())
 
 
 
 
460
 
461
- # Start the bot
462
- await app.start()
463
- print("Bot started")
464
- await asyncio.Event().wait() # run forever
 
465
 
466
  if __name__ == "__main__":
467
- # Start Flask in a separate thread
 
468
  threading.Thread(target=run_web, daemon=True).start()
469
- # Start keepalive pinger
470
- threading.Thread(target=keepalive, daemon=True).start()
471
 
472
- # Run Pyrogram
473
- app.run(main())
 
1
  import os
2
+ import tempfile
 
 
 
3
  import shutil
4
  import threading
5
+ import queue
 
 
 
6
 
 
7
  from flask import Flask
8
+
9
  from pyrogram import Client, filters
10
  from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
 
 
11
 
12
+ from huggingface_hub import HfApi, hf_hub_download
13
+
14
+ # =========================
15
+ # CONFIG
16
+ # =========================
17
+
18
  API_ID = int(os.environ["API_ID"])
19
  API_HASH = os.environ["API_HASH"]
20
  BOT_TOKEN = os.environ["BOT_TOKEN"]
21
  HF_TOKEN = os.environ["HF_TOKEN"]
 
22
 
23
  DATASET_REPO = "Cxops/Bzxv"
24
+
25
+ # =========================
26
+ # FLASK (HEALTH CHECK)
27
+ # =========================
28
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  web = Flask(__name__)
30
 
31
  @web.route("/")
32
  def home():
33
+ return "OK - Ultra Fast Bot Running"
34
 
35
  def run_web():
36
  web.run(host="0.0.0.0", port=7860)
37
 
38
+ # =========================
39
+ # HF CLIENT
40
+ # =========================
41
+
42
  hf = HfApi(token=HF_TOKEN)
43
 
44
+ # =========================
45
+ # UPLOAD QUEUE SYSTEM (FAST)
46
+ # =========================
47
+
48
+ upload_queue = queue.Queue()
49
+
50
+ def worker():
51
+ while True:
52
+ try:
53
+ local_path, repo_path, status = upload_queue.get()
54
+
55
+ hf.upload_file(
56
+ path_or_fileobj=local_path,
57
+ path_in_repo=repo_path,
58
+ repo_id=DATASET_REPO,
59
+ repo_type="dataset",
60
+ )
61
+
62
+ try:
63
+ status.edit_text("⚡ Upload Complete (Ultra Fast)")
64
+ except:
65
+ pass
66
+
67
+ except Exception as e:
68
+ try:
69
+ status.edit_text(f"Upload Failed:\n{e}")
70
+ except:
71
+ pass
72
+
73
+ finally:
74
+ upload_queue.task_done()
75
+
76
+ # start multiple workers (PARALLEL SPEED)
77
+ for _ in range(3):
78
+ threading.Thread(target=worker, daemon=True).start()
79
+
80
+ # =========================
81
+ # PYROGRAM
82
+ # =========================
83
+
84
  app = Client(
85
+ "ultra_fast_bot",
86
  api_id=API_ID,
87
  api_hash=API_HASH,
88
  bot_token=BOT_TOKEN
89
  )
90
 
91
+ # =========================
92
+ # CLEANUP
93
+ # =========================
 
94
 
95
+ def cleanup(path):
 
 
96
  try:
97
+ shutil.rmtree(path, ignore_errors=True)
98
+ except:
 
 
 
99
  pass
100
 
101
+ # =========================
102
+ # START
103
+ # =========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
+ @app.on_message(filters.command("start"))
106
+ async def start(_, m):
107
+ await m.reply_text(
108
+ "⚡ ULTRA FAST STORAGE BOT\n\n"
109
+ "Send file → stored in Hugging Face\n"
110
+ "/files → list files"
111
+ )
112
 
113
+ # =========================
114
+ # LIST FILES
115
+ # =========================
116
+
117
+ @app.on_message(filters.command("files"))
118
+ async def files(_, m):
119
+ uid = str(m.from_user.id)
120
 
 
 
 
121
  try:
122
+ all_files = hf.list_repo_files(
123
+ repo_id=DATASET_REPO,
124
+ repo_type="dataset"
125
+ )
126
 
127
+ user_files = [f for f in all_files if f.startswith(uid + "/")]
 
 
 
128
 
129
+ if not user_files:
130
+ return await m.reply_text("No files found.")
131
 
132
+ buttons = [
133
+ [InlineKeyboardButton(os.path.basename(f), callback_data=f"get:{f}")]
134
+ for f in user_files[:50]
135
+ ]
 
 
 
 
136
 
137
+ await m.reply_text(
138
+ "Your files:",
139
+ reply_markup=InlineKeyboardMarkup(buttons)
140
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
  except Exception as e:
143
+ await m.reply_text(str(e))
 
 
144
 
145
+ # =========================
146
+ # DOWNLOAD FROM HF
147
+ # =========================
148
+
149
+ @app.on_callback_query(filters.regex("^get:"))
150
+ async def get_file(_, q):
151
+ path = q.data.split(":", 1)[1]
152
+
153
+ tmp = tempfile.mkdtemp()
154
+
155
+ try:
156
+ await q.message.edit_text("⚡ Downloading...")
157
+
158
+ file_path = hf_hub_download(
159
+ repo_id=DATASET_REPO,
160
+ repo_type="dataset",
161
+ filename=path,
162
+ token=HF_TOKEN,
163
+ local_dir=tmp
 
 
 
 
164
  )
 
165
 
166
+ await q.message.reply_document(file_path)
 
 
 
 
 
167
 
168
+ await q.message.delete()
169
 
170
+ except Exception as e:
171
+ await q.message.reply_text(str(e))
 
 
 
 
172
 
173
+ finally:
174
+ cleanup(tmp)
 
 
175
 
176
+ # =========================
177
+ # UPLOAD FROM TELEGRAM (FAST)
178
+ # =========================
 
 
179
 
180
+ @app.on_message(
181
+ filters.document |
182
+ filters.video |
183
+ filters.audio |
184
+ filters.photo
185
+ )
186
+ async def upload(_, m):
 
187
 
188
+ tmp = tempfile.mkdtemp()
 
 
 
 
 
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  try:
191
+ status = await m.reply_text("⚡ Downloading...")
 
 
192
 
193
+ if m.document:
194
+ name = m.document.file_name
195
 
196
+ elif m.video:
197
+ name = m.video.file_name or f"{m.video.file_unique_id}.mp4"
198
 
199
+ elif m.audio:
200
+ name = m.audio.file_name or f"{m.audio.file_unique_id}.mp3"
201
 
202
+ else:
203
+ name = f"{m.photo[-1].file_unique_id}.jpg"
 
 
 
204
 
205
+ local_path = await m.download(file_name=f"{tmp}/{name}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
+ repo_path = f"{m.from_user.id}/{name}"
208
+
209
+ # 🔥 push into queue (INSTANT RETURN)
210
+ upload_queue.put((local_path, repo_path, status))
211
+
212
+ await status.edit_text("⚡ Queued for ultra-fast upload...")
 
 
213
 
214
+ except Exception as e:
215
+ await m.reply_text(f"Error:\n{e}")
216
+
217
+ finally:
218
+ def delayed_cleanup():
219
+ import time
220
+ time.sleep(15)
221
+ cleanup(tmp)
222
 
223
+ threading.Thread(target=delayed_cleanup, daemon=True).start()
224
+
225
+ # =========================
226
+ # RUN
227
+ # =========================
228
 
229
  if __name__ == "__main__":
230
+ print("🚀 Ultra Fast Bot Starting...")
231
+
232
  threading.Thread(target=run_web, daemon=True).start()
 
 
233
 
234
+ app.run()