Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,6 +8,8 @@ import re
|
|
| 8 |
import urllib3
|
| 9 |
import subprocess
|
| 10 |
import logging
|
|
|
|
|
|
|
| 11 |
from flask import Flask, jsonify, make_response, request, Response
|
| 12 |
from supabase import create_client
|
| 13 |
from pyrogram import Client, filters, enums, idle, utils
|
|
@@ -63,10 +65,6 @@ except RuntimeError:
|
|
| 63 |
main_loop = asyncio.new_event_loop()
|
| 64 |
asyncio.set_event_loop(main_loop)
|
| 65 |
|
| 66 |
-
def run_async(coro):
|
| 67 |
-
future = asyncio.run_coroutine_threadsafe(coro, main_loop)
|
| 68 |
-
return future.result()
|
| 69 |
-
|
| 70 |
bot = Client("file_unlocker_bot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN)
|
| 71 |
|
| 72 |
# ==================== ROBUST DB QUERY WITH AUTO-RETRY ====================
|
|
@@ -312,7 +310,6 @@ def api_verify_code():
|
|
| 312 |
try: await client.disconnect()
|
| 313 |
except: pass
|
| 314 |
|
| 315 |
-
# π UPDATE: Added 'phone' field to be saved in DB
|
| 316 |
await db_query(lambda: supabase.table('user_sessions').insert({
|
| 317 |
"user_id": user_id,
|
| 318 |
"phone": phone,
|
|
@@ -404,7 +401,6 @@ async def save_progress(source_id, dest_id, msg_id):
|
|
| 404 |
await db_query(lambda: supabase.table('clone_progress').insert({'source_id': source_id, 'dest_id': dest_id, 'last_copied_id': msg_id}).execute())
|
| 405 |
except Exception as e: print(f"Error saving progress: {e}")
|
| 406 |
|
| 407 |
-
# ================= AUTO BROADCAST TO NEW GROUPS =================
|
| 408 |
@bot.on_message(filters.new_chat_members)
|
| 409 |
async def bot_added_to_group(client, message):
|
| 410 |
me = client.me
|
|
@@ -442,7 +438,6 @@ async def bot_added_to_group(client, message):
|
|
| 442 |
await client.copy_message(message.chat.id, src_chat, msg_id, caption=caption_text, reply_markup=group_markup)
|
| 443 |
except Exception as e:
|
| 444 |
print(f"Error handling new group logic: {e}")
|
| 445 |
-
# =======================================================================
|
| 446 |
|
| 447 |
@bot.on_message(filters.command("sendto") & filters.private & filters.user(ADMIN_IDS))
|
| 448 |
async def send_to_specific_group(client, message):
|
|
@@ -1077,18 +1072,23 @@ async def catch_admin_steps(client, message):
|
|
| 1077 |
await process_broadcast(client, message)
|
| 1078 |
|
| 1079 |
# ==========================================
|
| 1080 |
-
# WATERMARK MULTIPROCESSING
|
| 1081 |
# ==========================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1082 |
processing_owners = set()
|
| 1083 |
MAX_CONCURRENT_VIDEOS = 5
|
| 1084 |
|
| 1085 |
-
async def process_single_video(task):
|
| 1086 |
global processing_owners
|
| 1087 |
-
task_id = task['id']
|
| 1088 |
clone_token = task['clone_token']
|
| 1089 |
owner_id = task['owner_id']
|
| 1090 |
message_id = task['message_id']
|
| 1091 |
wm_text = task['watermark_text']
|
|
|
|
| 1092 |
|
| 1093 |
clone_client = Client(f"clone_wm_{task_id}", bot_token=clone_token, api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 1094 |
await clone_client.start()
|
|
@@ -1096,7 +1096,7 @@ async def process_single_video(task):
|
|
| 1096 |
try:
|
| 1097 |
msg = await clone_client.get_messages(owner_id, message_id)
|
| 1098 |
if not msg or not (msg.video or msg.document):
|
| 1099 |
-
raise Exception("Video not found.")
|
| 1100 |
|
| 1101 |
status_msg = await clone_client.send_message(owner_id, "β³ <b>Video processing started...</b>", parse_mode=enums.ParseMode.HTML)
|
| 1102 |
|
|
@@ -1156,50 +1156,54 @@ async def process_single_video(task):
|
|
| 1156 |
if os.path.exists(raw_video_path): os.remove(raw_video_path)
|
| 1157 |
if os.path.exists(watermarked_path): os.remove(watermarked_path)
|
| 1158 |
|
| 1159 |
-
await db_query(lambda: supabase.table('watermark_queue').update({'status': 'completed'}).eq('id', task_id).execute())
|
| 1160 |
-
|
| 1161 |
except Exception as e:
|
| 1162 |
try:
|
| 1163 |
await clone_client.send_message(owner_id, f"β <b>Error processing video:</b> {e}", parse_mode=enums.ParseMode.HTML)
|
| 1164 |
except: pass
|
| 1165 |
-
await db_query(lambda: supabase.table('watermark_queue').update({'status': 'failed'}).eq('id', task_id).execute())
|
| 1166 |
|
| 1167 |
finally:
|
| 1168 |
await clone_client.stop()
|
|
|
|
| 1169 |
processing_owners.discard(owner_id)
|
| 1170 |
|
| 1171 |
async def watermark_processor_loop():
|
| 1172 |
global processing_owners
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1173 |
try:
|
| 1174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1175 |
except: pass
|
| 1176 |
|
| 1177 |
-
await asyncio.sleep(5)
|
| 1178 |
-
print("π§ Multi-Threaded Watermark Processor Started!")
|
| 1179 |
-
|
| 1180 |
while True:
|
| 1181 |
-
await asyncio.sleep(3)
|
| 1182 |
try:
|
| 1183 |
if len(processing_owners) >= MAX_CONCURRENT_VIDEOS:
|
|
|
|
| 1184 |
continue
|
| 1185 |
|
| 1186 |
-
|
| 1187 |
|
| 1188 |
-
if
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
-
|
| 1193 |
-
|
| 1194 |
-
|
| 1195 |
-
continue
|
| 1196 |
-
|
| 1197 |
-
processing_owners.add(owner_id)
|
| 1198 |
-
await db_query(lambda: supabase.table('watermark_queue').update({'status': 'processing'}).eq('id', task['id']).execute())
|
| 1199 |
-
asyncio.create_task(process_single_video(task))
|
| 1200 |
|
| 1201 |
-
except Exception:
|
| 1202 |
-
|
| 1203 |
|
| 1204 |
def run_flask(): app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)), threaded=True)
|
| 1205 |
|
|
@@ -1208,7 +1212,7 @@ async def main():
|
|
| 1208 |
await bot.start()
|
| 1209 |
print("π€ Pyrogram Bot & Real Session API is running!")
|
| 1210 |
asyncio.create_task(auto_clean_channel_loop())
|
| 1211 |
-
asyncio.create_task(watermark_processor_loop())
|
| 1212 |
await idle()
|
| 1213 |
except Exception as e:
|
| 1214 |
print(f"β Failed to start Bot: {e}")
|
|
|
|
| 8 |
import urllib3
|
| 9 |
import subprocess
|
| 10 |
import logging
|
| 11 |
+
import json
|
| 12 |
+
import redis.asyncio as redis
|
| 13 |
from flask import Flask, jsonify, make_response, request, Response
|
| 14 |
from supabase import create_client
|
| 15 |
from pyrogram import Client, filters, enums, idle, utils
|
|
|
|
| 65 |
main_loop = asyncio.new_event_loop()
|
| 66 |
asyncio.set_event_loop(main_loop)
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
bot = Client("file_unlocker_bot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN)
|
| 69 |
|
| 70 |
# ==================== ROBUST DB QUERY WITH AUTO-RETRY ====================
|
|
|
|
| 310 |
try: await client.disconnect()
|
| 311 |
except: pass
|
| 312 |
|
|
|
|
| 313 |
await db_query(lambda: supabase.table('user_sessions').insert({
|
| 314 |
"user_id": user_id,
|
| 315 |
"phone": phone,
|
|
|
|
| 401 |
await db_query(lambda: supabase.table('clone_progress').insert({'source_id': source_id, 'dest_id': dest_id, 'last_copied_id': msg_id}).execute())
|
| 402 |
except Exception as e: print(f"Error saving progress: {e}")
|
| 403 |
|
|
|
|
| 404 |
@bot.on_message(filters.new_chat_members)
|
| 405 |
async def bot_added_to_group(client, message):
|
| 406 |
me = client.me
|
|
|
|
| 438 |
await client.copy_message(message.chat.id, src_chat, msg_id, caption=caption_text, reply_markup=group_markup)
|
| 439 |
except Exception as e:
|
| 440 |
print(f"Error handling new group logic: {e}")
|
|
|
|
| 441 |
|
| 442 |
@bot.on_message(filters.command("sendto") & filters.private & filters.user(ADMIN_IDS))
|
| 443 |
async def send_to_specific_group(client, message):
|
|
|
|
| 1072 |
await process_broadcast(client, message)
|
| 1073 |
|
| 1074 |
# ==========================================
|
| 1075 |
+
# REDIS QUEUE WATERMARK MULTIPROCESSING
|
| 1076 |
# ==========================================
|
| 1077 |
+
import json
|
| 1078 |
+
import redis.asyncio as redis
|
| 1079 |
+
|
| 1080 |
+
REDIS_URL = os.environ.get("REDIS_URL_1")
|
| 1081 |
+
|
| 1082 |
processing_owners = set()
|
| 1083 |
MAX_CONCURRENT_VIDEOS = 5
|
| 1084 |
|
| 1085 |
+
async def process_single_video(task, redis_client):
|
| 1086 |
global processing_owners
|
|
|
|
| 1087 |
clone_token = task['clone_token']
|
| 1088 |
owner_id = task['owner_id']
|
| 1089 |
message_id = task['message_id']
|
| 1090 |
wm_text = task['watermark_text']
|
| 1091 |
+
task_id = f"{owner_id}_{message_id}"
|
| 1092 |
|
| 1093 |
clone_client = Client(f"clone_wm_{task_id}", bot_token=clone_token, api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 1094 |
await clone_client.start()
|
|
|
|
| 1096 |
try:
|
| 1097 |
msg = await clone_client.get_messages(owner_id, message_id)
|
| 1098 |
if not msg or not (msg.video or msg.document):
|
| 1099 |
+
raise Exception("Video not found or deleted.")
|
| 1100 |
|
| 1101 |
status_msg = await clone_client.send_message(owner_id, "β³ <b>Video processing started...</b>", parse_mode=enums.ParseMode.HTML)
|
| 1102 |
|
|
|
|
| 1156 |
if os.path.exists(raw_video_path): os.remove(raw_video_path)
|
| 1157 |
if os.path.exists(watermarked_path): os.remove(watermarked_path)
|
| 1158 |
|
|
|
|
|
|
|
| 1159 |
except Exception as e:
|
| 1160 |
try:
|
| 1161 |
await clone_client.send_message(owner_id, f"β <b>Error processing video:</b> {e}", parse_mode=enums.ParseMode.HTML)
|
| 1162 |
except: pass
|
|
|
|
| 1163 |
|
| 1164 |
finally:
|
| 1165 |
await clone_client.stop()
|
| 1166 |
+
await redis_client.delete(f"wm_processing:{owner_id}")
|
| 1167 |
processing_owners.discard(owner_id)
|
| 1168 |
|
| 1169 |
async def watermark_processor_loop():
|
| 1170 |
global processing_owners
|
| 1171 |
+
|
| 1172 |
+
if not REDIS_URL:
|
| 1173 |
+
print("β οΈ REDIS_URL missing in Hugging Space! Watermark feature disabled.")
|
| 1174 |
+
return
|
| 1175 |
+
|
| 1176 |
try:
|
| 1177 |
+
redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
|
| 1178 |
+
await redis_client.ping()
|
| 1179 |
+
print("π§ Super-Fast Redis Watermark Processor Started!")
|
| 1180 |
+
except Exception as e:
|
| 1181 |
+
print(f"β Redis Connection Failed in Hugging Face: {e}")
|
| 1182 |
+
return
|
| 1183 |
+
|
| 1184 |
+
try:
|
| 1185 |
+
async for key in redis_client.scan_iter("wm_processing:*"):
|
| 1186 |
+
await redis_client.delete(key)
|
| 1187 |
except: pass
|
| 1188 |
|
|
|
|
|
|
|
|
|
|
| 1189 |
while True:
|
|
|
|
| 1190 |
try:
|
| 1191 |
if len(processing_owners) >= MAX_CONCURRENT_VIDEOS:
|
| 1192 |
+
await asyncio.sleep(2)
|
| 1193 |
continue
|
| 1194 |
|
| 1195 |
+
result = await redis_client.brpop("watermark_task_queue", timeout=5)
|
| 1196 |
|
| 1197 |
+
if result:
|
| 1198 |
+
_, task_json = result
|
| 1199 |
+
task = json.loads(task_json)
|
| 1200 |
+
owner_id = task['owner_id']
|
| 1201 |
+
|
| 1202 |
+
processing_owners.add(owner_id)
|
| 1203 |
+
asyncio.create_task(process_single_video(task, redis_client))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1204 |
|
| 1205 |
+
except Exception as e:
|
| 1206 |
+
await asyncio.sleep(2)
|
| 1207 |
|
| 1208 |
def run_flask(): app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)), threaded=True)
|
| 1209 |
|
|
|
|
| 1212 |
await bot.start()
|
| 1213 |
print("π€ Pyrogram Bot & Real Session API is running!")
|
| 1214 |
asyncio.create_task(auto_clean_channel_loop())
|
| 1215 |
+
asyncio.create_task(watermark_processor_loop())
|
| 1216 |
await idle()
|
| 1217 |
except Exception as e:
|
| 1218 |
print(f"β Failed to start Bot: {e}")
|