Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1076,6 +1076,131 @@ async def catch_admin_steps(client, message):
|
|
| 1076 |
elif state.get("step") == "broadcast":
|
| 1077 |
await process_broadcast(client, message)
|
| 1078 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1079 |
def run_flask(): app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)), threaded=True)
|
| 1080 |
|
| 1081 |
async def main():
|
|
@@ -1083,6 +1208,7 @@ async def main():
|
|
| 1083 |
await bot.start()
|
| 1084 |
print("π€ Pyrogram Bot & Real Session API is running!")
|
| 1085 |
asyncio.create_task(auto_clean_channel_loop())
|
|
|
|
| 1086 |
await idle()
|
| 1087 |
except Exception as e:
|
| 1088 |
print(f"β Failed to start Bot: {e}")
|
|
|
|
| 1076 |
elif state.get("step") == "broadcast":
|
| 1077 |
await process_broadcast(client, message)
|
| 1078 |
|
| 1079 |
+
# ==========================================
|
| 1080 |
+
# WATERMARK MULTIPROCESSING SYSTEM
|
| 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()
|
| 1095 |
+
|
| 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 |
+
|
| 1103 |
+
raw_video_path = await clone_client.download_media(msg)
|
| 1104 |
+
|
| 1105 |
+
await clone_client.edit_message_text(owner_id, status_msg.id, "β³ <b>Uploading original file to secure storage...</b>", parse_mode=enums.ParseMode.HTML)
|
| 1106 |
+
|
| 1107 |
+
raw_sent = await bot.send_video(
|
| 1108 |
+
chat_id=STORAGE_CHANNEL_ID,
|
| 1109 |
+
video=raw_video_path,
|
| 1110 |
+
caption=f"Original Backup for Clone Owner {owner_id}"
|
| 1111 |
+
)
|
| 1112 |
+
raw_storage_id = raw_sent.id
|
| 1113 |
+
stream_link = f"{BACKEND_URL}/stream/{raw_storage_id}"
|
| 1114 |
+
download_link = f"{BACKEND_URL}/download/{raw_storage_id}"
|
| 1115 |
+
|
| 1116 |
+
await clone_client.edit_message_text(owner_id, status_msg.id, "β³ <b>Applying Custom Watermark... (This may take a few minutes)</b>", parse_mode=enums.ParseMode.HTML)
|
| 1117 |
+
|
| 1118 |
+
watermarked_path = f"wm_{task_id}.mp4"
|
| 1119 |
+
|
| 1120 |
+
cmd = [
|
| 1121 |
+
"ffmpeg", "-y", "-i", raw_video_path,
|
| 1122 |
+
"-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)'",
|
| 1123 |
+
"-c:v", "libx264", "-preset", "superfast", "-crf", "23",
|
| 1124 |
+
"-c:a", "copy", "-movflags", "+faststart", watermarked_path
|
| 1125 |
+
]
|
| 1126 |
+
|
| 1127 |
+
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
| 1128 |
+
await process.communicate()
|
| 1129 |
+
|
| 1130 |
+
if not os.path.exists(watermarked_path) or os.path.getsize(watermarked_path) == 0:
|
| 1131 |
+
raise Exception("FFmpeg processing failed.")
|
| 1132 |
+
|
| 1133 |
+
await clone_client.edit_message_text(owner_id, status_msg.id, "β³ <b>Uploading final video...</b>", parse_mode=enums.ParseMode.HTML)
|
| 1134 |
+
|
| 1135 |
+
await bot.send_video(
|
| 1136 |
+
chat_id=STORAGE_CHANNEL_ID,
|
| 1137 |
+
video=watermarked_path,
|
| 1138 |
+
caption=f"Watermarked Backup for Clone Owner {owner_id}"
|
| 1139 |
+
)
|
| 1140 |
+
|
| 1141 |
+
final_caption = (
|
| 1142 |
+
f"β
<b>Watermark Successfully Added!</b>\n\n"
|
| 1143 |
+
f"π¬ <b>Stream/Watch Online Link:</b>\n<code>{stream_link}</code>\n\n"
|
| 1144 |
+
f"π₯ <b>Direct Download Link:</b>\n<code>{download_link}</code>"
|
| 1145 |
+
)
|
| 1146 |
+
|
| 1147 |
+
await clone_client.send_video(
|
| 1148 |
+
chat_id=owner_id,
|
| 1149 |
+
video=watermarked_path,
|
| 1150 |
+
caption=final_caption,
|
| 1151 |
+
parse_mode=enums.ParseMode.HTML
|
| 1152 |
+
)
|
| 1153 |
+
|
| 1154 |
+
await clone_client.delete_messages(owner_id, status_msg.id)
|
| 1155 |
+
|
| 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 |
+
await db_query(lambda: supabase.table('watermark_queue').update({'status': 'pending'}).eq('status', 'processing').execute())
|
| 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 |
+
res = await db_query(lambda: supabase.table('watermark_queue').select('*').eq('status', 'pending').order('id', desc=False).limit(10).execute())
|
| 1187 |
+
|
| 1188 |
+
if res and res.data:
|
| 1189 |
+
for task in res.data:
|
| 1190 |
+
if len(processing_owners) >= MAX_CONCURRENT_VIDEOS:
|
| 1191 |
+
break
|
| 1192 |
+
|
| 1193 |
+
owner_id = task['owner_id']
|
| 1194 |
+
if owner_id in processing_owners:
|
| 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 |
+
pass
|
| 1203 |
+
|
| 1204 |
def run_flask(): app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)), threaded=True)
|
| 1205 |
|
| 1206 |
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}")
|