Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -53,6 +53,13 @@ temp_clients = {}
|
|
| 53 |
|
| 54 |
upload_mode = "telegram"
|
| 55 |
ffmpeg_available = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
try:
|
| 57 |
subprocess.run(["ffmpeg", "-version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
| 58 |
except FileNotFoundError:
|
|
@@ -345,6 +352,130 @@ def api_verify_code():
|
|
| 345 |
return jsonify(result)
|
| 346 |
except Exception as e: return jsonify({"status": "error", "msg": str(e)})
|
| 347 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 348 |
# ================= TELEGRAM BOT COMMANDS =================
|
| 349 |
@bot.on_message(filters.command("start"))
|
| 350 |
async def start(client, message):
|
|
@@ -396,15 +527,6 @@ async def start(client, message):
|
|
| 396 |
await message.reply(welcome_text, parse_mode=enums.ParseMode.HTML, reply_markup=markup)
|
| 397 |
except Exception as e: print(f"Start error: {e}")
|
| 398 |
|
| 399 |
-
async def save_progress(source_id, dest_id, msg_id):
|
| 400 |
-
try:
|
| 401 |
-
res = await db_query(lambda: supabase.table('clone_progress').select('id').eq('source_id', source_id).eq('dest_id', dest_id).execute())
|
| 402 |
-
if res.data:
|
| 403 |
-
await db_query(lambda: supabase.table('clone_progress').update({'last_copied_id': msg_id}).eq('id', res.data[0]['id']).execute())
|
| 404 |
-
else:
|
| 405 |
-
await db_query(lambda: supabase.table('clone_progress').insert({'source_id': source_id, 'dest_id': dest_id, 'last_copied_id': msg_id}).execute())
|
| 406 |
-
except Exception as e: print(f"Error saving progress: {e}")
|
| 407 |
-
|
| 408 |
@bot.on_message(filters.new_chat_members)
|
| 409 |
async def bot_added_to_group(client, message):
|
| 410 |
me = client.me
|
|
@@ -821,7 +943,6 @@ async def handle_media_upload(client, message):
|
|
| 821 |
await proc.communicate()
|
| 822 |
if not os.path.exists(thumb_path): thumb_path = None
|
| 823 |
|
| 824 |
-
# Auto-retry logic for sending final result to admin
|
| 825 |
try:
|
| 826 |
if media_type == "photo":
|
| 827 |
sent_to_admin = await client.send_photo(message.chat.id, telegram_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML)
|
|
@@ -842,7 +963,6 @@ async def handle_media_upload(client, message):
|
|
| 842 |
thumb=thumb_path
|
| 843 |
)
|
| 844 |
|
| 845 |
-
# সেভ করে রাখা হচ্ছে যাতে নতুন গ্রুপে এড হলে এই ভিডিওটা দিতে পারে
|
| 846 |
await save_progress(message.chat.id, 0, sent_to_admin.id)
|
| 847 |
|
| 848 |
except Exception as e:
|
|
@@ -856,7 +976,6 @@ async def handle_media_upload(client, message):
|
|
| 856 |
try: await status_msg.delete()
|
| 857 |
except: pass
|
| 858 |
|
| 859 |
-
# Load groups safely with auto-retry
|
| 860 |
try:
|
| 861 |
groups_res = await db_query(lambda: supabase.table('groups').select('group_id').execute())
|
| 862 |
except Exception as db_err:
|
|
@@ -866,7 +985,6 @@ async def handle_media_upload(client, message):
|
|
| 866 |
group_ids = [g['group_id'] for g in groups_res.data]
|
| 867 |
success_count, fail_count = 0, 0
|
| 868 |
|
| 869 |
-
# Safe Broadcast Phase
|
| 870 |
for gid in set(group_ids):
|
| 871 |
retries = 3
|
| 872 |
while retries > 0:
|
|
@@ -888,7 +1006,6 @@ async def handle_media_upload(client, message):
|
|
| 888 |
break
|
| 889 |
await asyncio.sleep(1.5)
|
| 890 |
|
| 891 |
-
# Success notification safely
|
| 892 |
retries = 3
|
| 893 |
while retries > 0:
|
| 894 |
try:
|
|
@@ -1057,7 +1174,7 @@ async def auto_clean_channel_loop():
|
|
| 1057 |
print(f"Auto clean error: {e}")
|
| 1058 |
await asyncio.sleep(4 * 3600)
|
| 1059 |
|
| 1060 |
-
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean", "sendto", "clone", "upload"]))
|
| 1061 |
async def catch_admin_steps(client, message):
|
| 1062 |
state = admin_states.get(message.chat.id, {})
|
| 1063 |
if state.get("step") == 1:
|
|
@@ -1078,9 +1195,6 @@ async def catch_admin_steps(client, message):
|
|
| 1078 |
# ==========================================
|
| 1079 |
# REDIS QUEUE WATERMARK MULTIPROCESSING
|
| 1080 |
# ==========================================
|
| 1081 |
-
import json
|
| 1082 |
-
import redis.asyncio as redis
|
| 1083 |
-
|
| 1084 |
REDIS_URL = os.environ.get("REDIS_URL_1")
|
| 1085 |
|
| 1086 |
processing_owners = set()
|
|
@@ -1094,13 +1208,10 @@ async def process_single_video(task, redis_client):
|
|
| 1094 |
wm_text = task['watermark_text']
|
| 1095 |
task_id = f"{owner_id}_{message_id}"
|
| 1096 |
|
| 1097 |
-
# ==============================
|
| 1098 |
-
# FIX: আগে ভেরিয়েবল ডিফাইন করা হলো যাতে finally ব্লকে এরর না আসে
|
| 1099 |
raw_video_path = None
|
| 1100 |
watermarked_path = None
|
| 1101 |
thumb_path = f"thumb_{task_id}.jpg"
|
| 1102 |
clone_client = None
|
| 1103 |
-
# ==============================
|
| 1104 |
|
| 1105 |
print(f"▶️ [WM] Task Started for User: {owner_id}, Msg: {message_id}")
|
| 1106 |
|
|
@@ -1122,7 +1233,6 @@ async def process_single_video(task, redis_client):
|
|
| 1122 |
|
| 1123 |
watermarked_path = f"wm_{task_id}.mp4"
|
| 1124 |
|
| 1125 |
-
# Hugging Face এ দ্রুত প্রসেস করার জন্য ultrafast, threads 4 এবং crf 26 ব্যবহার করা হলো
|
| 1126 |
cmd = [
|
| 1127 |
"ffmpeg", "-y", "-i", raw_video_path,
|
| 1128 |
"-vf", f"drawtext=text='{wm_text}':x=W-tw-20:y=H-th-20:fontsize=22:fontcolor=white@0.7:shadowcolor=black@0.8:shadowx=2:shadowy=2:enable='gte(t,5)'",
|
|
@@ -1146,14 +1256,12 @@ async def process_single_video(task, redis_client):
|
|
| 1146 |
|
| 1147 |
await clone_client.edit_message_text(owner_id, status_msg.id, "⏳ <b>ফাইনাল ভিডিও স্টোরেজে আপলোড হচ্ছে...</b>", parse_mode=enums.ParseMode.HTML)
|
| 1148 |
|
| 1149 |
-
# Background এ অরিজিনাল ভিডিও স্টোরেজে পাঠানো হচ্ছে, যাতে ইউজারকে ওয়েট করতে না হয়
|
| 1150 |
async def backup_raw_video():
|
| 1151 |
try:
|
| 1152 |
await bot.send_video(chat_id=STORAGE_CHANNEL_ID, video=raw_video_path, caption=f"Original Backup for Clone Owner {owner_id}")
|
| 1153 |
except Exception: pass
|
| 1154 |
asyncio.create_task(backup_raw_video())
|
| 1155 |
|
| 1156 |
-
# ওয়াটারমার্ক করা ভিডিওটি আপলোড হচ্ছে (সঠিক Stream Link বানানোর জন্য)
|
| 1157 |
wm_sent = await bot.send_video(
|
| 1158 |
chat_id=STORAGE_CHANNEL_ID,
|
| 1159 |
video=watermarked_path,
|
|
@@ -1161,7 +1269,6 @@ async def process_single_video(task, redis_client):
|
|
| 1161 |
thumb=thumb_path
|
| 1162 |
)
|
| 1163 |
|
| 1164 |
-
# FIX: এখন লিংকগুলো অরিজিনালের বদলে ওয়াটারমার্ক ভিডিও পয়েন্ট করবে
|
| 1165 |
wm_storage_id = wm_sent.id
|
| 1166 |
stream_link = f"{BACKEND_URL}/stream/{wm_storage_id}"
|
| 1167 |
download_link = f"{BACKEND_URL}/download/{wm_storage_id}"
|
|
@@ -1191,7 +1298,6 @@ async def process_single_video(task, redis_client):
|
|
| 1191 |
print(f"❌ [WM] Failed to send error msg to user: {ex}")
|
| 1192 |
|
| 1193 |
finally:
|
| 1194 |
-
# ফাইল এবং লক ক্লিনআপ
|
| 1195 |
if raw_video_path and os.path.exists(raw_video_path): os.remove(raw_video_path)
|
| 1196 |
if watermarked_path and os.path.exists(watermarked_path): os.remove(watermarked_path)
|
| 1197 |
if thumb_path and os.path.exists(thumb_path): os.remove(thumb_path)
|
|
@@ -1218,7 +1324,6 @@ async def watermark_processor_loop():
|
|
| 1218 |
print(f"❌ Redis Connection Failed in Hugging Face: {e}")
|
| 1219 |
return
|
| 1220 |
|
| 1221 |
-
# Clear stuck locks
|
| 1222 |
try:
|
| 1223 |
async for key in redis_client.scan_iter("wm_processing:*"):
|
| 1224 |
await redis_client.delete(key)
|
|
@@ -1264,5 +1369,4 @@ async def main():
|
|
| 1264 |
|
| 1265 |
if __name__ == "__main__":
|
| 1266 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 1267 |
-
main_loop.run_until_complete(main())
|
| 1268 |
-
#--- END OF FILE main.py
|
|
|
|
| 53 |
|
| 54 |
upload_mode = "telegram"
|
| 55 |
ffmpeg_available = True
|
| 56 |
+
|
| 57 |
+
# ================= AUTO SHARE VARIABLES =================
|
| 58 |
+
auto_share_running = False
|
| 59 |
+
auto_share_task = None
|
| 60 |
+
TARGET_SHARE_GROUP = -1004333630822
|
| 61 |
+
# =========================================================
|
| 62 |
+
|
| 63 |
try:
|
| 64 |
subprocess.run(["ffmpeg", "-version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
| 65 |
except FileNotFoundError:
|
|
|
|
| 352 |
return jsonify(result)
|
| 353 |
except Exception as e: return jsonify({"status": "error", "msg": str(e)})
|
| 354 |
|
| 355 |
+
|
| 356 |
+
async def save_progress(source_id, dest_id, msg_id):
|
| 357 |
+
try:
|
| 358 |
+
res = await db_query(lambda: supabase.table('clone_progress').select('id').eq('source_id', source_id).eq('dest_id', dest_id).execute())
|
| 359 |
+
if res.data:
|
| 360 |
+
await db_query(lambda: supabase.table('clone_progress').update({'last_copied_id': msg_id}).eq('id', res.data[0]['id']).execute())
|
| 361 |
+
else:
|
| 362 |
+
await db_query(lambda: supabase.table('clone_progress').insert({'source_id': source_id, 'dest_id': dest_id, 'last_copied_id': msg_id}).execute())
|
| 363 |
+
except Exception as e: print(f"Error saving progress: {e}")
|
| 364 |
+
|
| 365 |
+
|
| 366 |
+
# ================= AUTO SHARE LOGIC (5 videos / 5 mins) =================
|
| 367 |
+
async def auto_share_loop(client, target_chat_id, delay=300):
|
| 368 |
+
global auto_share_running
|
| 369 |
+
|
| 370 |
+
while auto_share_running:
|
| 371 |
+
try:
|
| 372 |
+
# Check maximum message ID to avoid infinite blank search
|
| 373 |
+
latest_msg_id = 0
|
| 374 |
+
async for m in client.get_chat_history(STORAGE_CHANNEL_ID, limit=1):
|
| 375 |
+
latest_msg_id = m.id
|
| 376 |
+
break
|
| 377 |
+
|
| 378 |
+
progress_res = await db_query(lambda: supabase.table('clone_progress').select('last_copied_id').eq('source_id', STORAGE_CHANNEL_ID).eq('dest_id', target_chat_id).execute())
|
| 379 |
+
last_checked_id = 0
|
| 380 |
+
if progress_res.data:
|
| 381 |
+
last_checked_id = progress_res.data[0]['last_copied_id']
|
| 382 |
+
|
| 383 |
+
if latest_msg_id > 0 and last_checked_id >= latest_msg_id:
|
| 384 |
+
await asyncio.sleep(60)
|
| 385 |
+
continue
|
| 386 |
+
|
| 387 |
+
batch_to_send = []
|
| 388 |
+
while len(batch_to_send) < 5 and auto_share_running:
|
| 389 |
+
if latest_msg_id > 0 and last_checked_id >= latest_msg_id:
|
| 390 |
+
break
|
| 391 |
+
|
| 392 |
+
chunk_ids = list(range(last_checked_id + 1, min(last_checked_id + 51, latest_msg_id + 1)))
|
| 393 |
+
if not chunk_ids:
|
| 394 |
+
break
|
| 395 |
+
|
| 396 |
+
try:
|
| 397 |
+
msgs = await client.get_messages(STORAGE_CHANNEL_ID, chunk_ids)
|
| 398 |
+
for idx, msg in enumerate(msgs):
|
| 399 |
+
msg_expected_id = chunk_ids[idx]
|
| 400 |
+
if msg is None or getattr(msg, "empty", False):
|
| 401 |
+
last_checked_id = max(last_checked_id, msg_expected_id)
|
| 402 |
+
continue
|
| 403 |
+
|
| 404 |
+
if msg.video or (msg.document and msg.document.mime_type and "video" in msg.document.mime_type) or msg.photo:
|
| 405 |
+
batch_to_send.append(msg)
|
| 406 |
+
last_checked_id = max(last_checked_id, msg.id)
|
| 407 |
+
if len(batch_to_send) == 5:
|
| 408 |
+
break
|
| 409 |
+
else:
|
| 410 |
+
last_checked_id = max(last_checked_id, msg.id)
|
| 411 |
+
except FloodWait as e:
|
| 412 |
+
await asyncio.sleep(e.value + 1)
|
| 413 |
+
except Exception as e:
|
| 414 |
+
print(f"Fetch error in auto share: {e}")
|
| 415 |
+
await asyncio.sleep(5)
|
| 416 |
+
|
| 417 |
+
if not batch_to_send:
|
| 418 |
+
await save_progress(STORAGE_CHANNEL_ID, target_chat_id, last_checked_id)
|
| 419 |
+
await asyncio.sleep(10)
|
| 420 |
+
continue
|
| 421 |
+
|
| 422 |
+
sent_message_ids = []
|
| 423 |
+
for msg in batch_to_send:
|
| 424 |
+
if not auto_share_running: break
|
| 425 |
+
try:
|
| 426 |
+
sent = await msg.copy(target_chat_id)
|
| 427 |
+
sent_message_ids.append(sent.id)
|
| 428 |
+
await asyncio.sleep(1.5)
|
| 429 |
+
except FloodWait as e:
|
| 430 |
+
await asyncio.sleep(e.value + 1)
|
| 431 |
+
except Exception as e:
|
| 432 |
+
print(f"Error copying msg {msg.id}: {e}")
|
| 433 |
+
|
| 434 |
+
await save_progress(STORAGE_CHANNEL_ID, target_chat_id, last_checked_id)
|
| 435 |
+
|
| 436 |
+
for _ in range(delay):
|
| 437 |
+
if not auto_share_running: break
|
| 438 |
+
await asyncio.sleep(1)
|
| 439 |
+
|
| 440 |
+
if sent_message_ids and auto_share_running:
|
| 441 |
+
try:
|
| 442 |
+
await client.delete_messages(target_chat_id, sent_message_ids)
|
| 443 |
+
except FloodWait as e:
|
| 444 |
+
await asyncio.sleep(e.value + 1)
|
| 445 |
+
await client.delete_messages(target_chat_id, sent_message_ids)
|
| 446 |
+
except Exception as e:
|
| 447 |
+
print(f"Error deleting msgs: {e}")
|
| 448 |
+
|
| 449 |
+
except Exception as e:
|
| 450 |
+
print(f"Auto-share loop error: {e}")
|
| 451 |
+
await asyncio.sleep(5)
|
| 452 |
+
|
| 453 |
+
@bot.on_message(filters.command("startshare") & filters.private & filters.user(ADMIN_IDS))
|
| 454 |
+
async def start_sharing_cmd(client, message):
|
| 455 |
+
global auto_share_running, auto_share_task
|
| 456 |
+
args = message.command
|
| 457 |
+
|
| 458 |
+
if len(args) > 1 and args[1].lower() == "reset":
|
| 459 |
+
await save_progress(STORAGE_CHANNEL_ID, TARGET_SHARE_GROUP, 0)
|
| 460 |
+
await message.reply("🔄 <b>Progress reset!</b> The bot will now start sharing from the 1st video.")
|
| 461 |
+
|
| 462 |
+
if auto_share_running:
|
| 463 |
+
return await message.reply("⚠️ <b>Auto-share is already running!</b>\nUse `/stopshare` to stop it first.")
|
| 464 |
+
|
| 465 |
+
auto_share_running = True
|
| 466 |
+
auto_share_task = asyncio.create_task(auto_share_loop(client, TARGET_SHARE_GROUP, 300))
|
| 467 |
+
await message.reply(f"✅ <b>Auto-sharing started!</b>\n\n📌 <b>Target Group:</b> <code>{TARGET_SHARE_GROUP}</code>\n📦 <b>Batch Size:</b> 5 videos\n⏱ <b>Interval:</b> 5 minutes\n\n<i>Bot will send 5 videos, wait 5 minutes, delete them, and send the next 5!</i>", parse_mode=enums.ParseMode.HTML)
|
| 468 |
+
|
| 469 |
+
@bot.on_message(filters.command("stopshare") & filters.private & filters.user(ADMIN_IDS))
|
| 470 |
+
async def stop_sharing_cmd(client, message):
|
| 471 |
+
global auto_share_running
|
| 472 |
+
if not auto_share_running:
|
| 473 |
+
return await message.reply("⚠️ Auto-share is not currently running.")
|
| 474 |
+
|
| 475 |
+
auto_share_running = False
|
| 476 |
+
await message.reply("🛑 <b>Auto-sharing stopped successfully!</b>", parse_mode=enums.ParseMode.HTML)
|
| 477 |
+
|
| 478 |
+
|
| 479 |
# ================= TELEGRAM BOT COMMANDS =================
|
| 480 |
@bot.on_message(filters.command("start"))
|
| 481 |
async def start(client, message):
|
|
|
|
| 527 |
await message.reply(welcome_text, parse_mode=enums.ParseMode.HTML, reply_markup=markup)
|
| 528 |
except Exception as e: print(f"Start error: {e}")
|
| 529 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 530 |
@bot.on_message(filters.new_chat_members)
|
| 531 |
async def bot_added_to_group(client, message):
|
| 532 |
me = client.me
|
|
|
|
| 943 |
await proc.communicate()
|
| 944 |
if not os.path.exists(thumb_path): thumb_path = None
|
| 945 |
|
|
|
|
| 946 |
try:
|
| 947 |
if media_type == "photo":
|
| 948 |
sent_to_admin = await client.send_photo(message.chat.id, telegram_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML)
|
|
|
|
| 963 |
thumb=thumb_path
|
| 964 |
)
|
| 965 |
|
|
|
|
| 966 |
await save_progress(message.chat.id, 0, sent_to_admin.id)
|
| 967 |
|
| 968 |
except Exception as e:
|
|
|
|
| 976 |
try: await status_msg.delete()
|
| 977 |
except: pass
|
| 978 |
|
|
|
|
| 979 |
try:
|
| 980 |
groups_res = await db_query(lambda: supabase.table('groups').select('group_id').execute())
|
| 981 |
except Exception as db_err:
|
|
|
|
| 985 |
group_ids = [g['group_id'] for g in groups_res.data]
|
| 986 |
success_count, fail_count = 0, 0
|
| 987 |
|
|
|
|
| 988 |
for gid in set(group_ids):
|
| 989 |
retries = 3
|
| 990 |
while retries > 0:
|
|
|
|
| 1006 |
break
|
| 1007 |
await asyncio.sleep(1.5)
|
| 1008 |
|
|
|
|
| 1009 |
retries = 3
|
| 1010 |
while retries > 0:
|
| 1011 |
try:
|
|
|
|
| 1174 |
print(f"Auto clean error: {e}")
|
| 1175 |
await asyncio.sleep(4 * 3600)
|
| 1176 |
|
| 1177 |
+
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean", "sendto", "clone", "upload", "startshare", "stopshare"]))
|
| 1178 |
async def catch_admin_steps(client, message):
|
| 1179 |
state = admin_states.get(message.chat.id, {})
|
| 1180 |
if state.get("step") == 1:
|
|
|
|
| 1195 |
# ==========================================
|
| 1196 |
# REDIS QUEUE WATERMARK MULTIPROCESSING
|
| 1197 |
# ==========================================
|
|
|
|
|
|
|
|
|
|
| 1198 |
REDIS_URL = os.environ.get("REDIS_URL_1")
|
| 1199 |
|
| 1200 |
processing_owners = set()
|
|
|
|
| 1208 |
wm_text = task['watermark_text']
|
| 1209 |
task_id = f"{owner_id}_{message_id}"
|
| 1210 |
|
|
|
|
|
|
|
| 1211 |
raw_video_path = None
|
| 1212 |
watermarked_path = None
|
| 1213 |
thumb_path = f"thumb_{task_id}.jpg"
|
| 1214 |
clone_client = None
|
|
|
|
| 1215 |
|
| 1216 |
print(f"▶️ [WM] Task Started for User: {owner_id}, Msg: {message_id}")
|
| 1217 |
|
|
|
|
| 1233 |
|
| 1234 |
watermarked_path = f"wm_{task_id}.mp4"
|
| 1235 |
|
|
|
|
| 1236 |
cmd = [
|
| 1237 |
"ffmpeg", "-y", "-i", raw_video_path,
|
| 1238 |
"-vf", f"drawtext=text='{wm_text}':x=W-tw-20:y=H-th-20:fontsize=22:fontcolor=white@0.7:shadowcolor=black@0.8:shadowx=2:shadowy=2:enable='gte(t,5)'",
|
|
|
|
| 1256 |
|
| 1257 |
await clone_client.edit_message_text(owner_id, status_msg.id, "⏳ <b>ফাইনাল ভিডিও স্টোরেজে আপলোড হচ্ছে...</b>", parse_mode=enums.ParseMode.HTML)
|
| 1258 |
|
|
|
|
| 1259 |
async def backup_raw_video():
|
| 1260 |
try:
|
| 1261 |
await bot.send_video(chat_id=STORAGE_CHANNEL_ID, video=raw_video_path, caption=f"Original Backup for Clone Owner {owner_id}")
|
| 1262 |
except Exception: pass
|
| 1263 |
asyncio.create_task(backup_raw_video())
|
| 1264 |
|
|
|
|
| 1265 |
wm_sent = await bot.send_video(
|
| 1266 |
chat_id=STORAGE_CHANNEL_ID,
|
| 1267 |
video=watermarked_path,
|
|
|
|
| 1269 |
thumb=thumb_path
|
| 1270 |
)
|
| 1271 |
|
|
|
|
| 1272 |
wm_storage_id = wm_sent.id
|
| 1273 |
stream_link = f"{BACKEND_URL}/stream/{wm_storage_id}"
|
| 1274 |
download_link = f"{BACKEND_URL}/download/{wm_storage_id}"
|
|
|
|
| 1298 |
print(f"❌ [WM] Failed to send error msg to user: {ex}")
|
| 1299 |
|
| 1300 |
finally:
|
|
|
|
| 1301 |
if raw_video_path and os.path.exists(raw_video_path): os.remove(raw_video_path)
|
| 1302 |
if watermarked_path and os.path.exists(watermarked_path): os.remove(watermarked_path)
|
| 1303 |
if thumb_path and os.path.exists(thumb_path): os.remove(thumb_path)
|
|
|
|
| 1324 |
print(f"❌ Redis Connection Failed in Hugging Face: {e}")
|
| 1325 |
return
|
| 1326 |
|
|
|
|
| 1327 |
try:
|
| 1328 |
async for key in redis_client.scan_iter("wm_processing:*"):
|
| 1329 |
await redis_client.delete(key)
|
|
|
|
| 1369 |
|
| 1370 |
if __name__ == "__main__":
|
| 1371 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 1372 |
+
main_loop.run_until_complete(main())
|
|
|