Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -14,7 +14,6 @@ from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInf
|
|
| 14 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
| 15 |
|
| 16 |
# ================= CONFIGURATION =================
|
| 17 |
-
# শুধুমাত্র Hugging Face Secrets থেকে ভ্যালু নেওয়া হচ্ছে। এখানে কোনো টোকেন দেওয়া নেই।
|
| 18 |
BOT_TOKEN = os.environ.get("BOT_TOKEN")
|
| 19 |
API_ID = int(os.environ.get("API_ID", 0))
|
| 20 |
API_HASH = os.environ.get("API_HASH")
|
|
@@ -366,31 +365,46 @@ async def handle_media_upload(client, message):
|
|
| 366 |
is_large_video = True
|
| 367 |
is_blur = False
|
| 368 |
|
| 369 |
-
status_msg = await message.reply("⏳ <b>Video is too large!</b> Skipping blur..." if is_large_video else "⏳ Downloading media...")
|
| 370 |
bot_me = client.me if client.me else await client.get_me()
|
| 371 |
bot_link = f"https://t.me/{bot_me.username}"
|
| 372 |
|
| 373 |
original_file, watermarked_file, blurred_file, final_file, embed_link = None, None, None, None, None
|
| 374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
try:
|
| 376 |
-
original_file = await message.download()
|
| 377 |
final_file = original_file
|
| 378 |
|
|
|
|
| 379 |
if media_type == "video" and not is_large_video:
|
| 380 |
-
await status_msg.edit_text("⏳ Watermarking video... (
|
| 381 |
watermarked_file = f"{original_file}_wm.mp4"
|
| 382 |
cmd = [
|
| 383 |
"ffmpeg", "-y", "-i", original_file,
|
| 384 |
"-vf", "drawtext=text='@mxvdo':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)'",
|
| 385 |
-
"-c:v", "libx264", "-preset", "
|
| 386 |
-
"-pix_fmt", "yuv420p", "-c:a", "
|
| 387 |
]
|
| 388 |
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
| 389 |
await process.communicate()
|
| 390 |
if process.returncode == 0 and os.path.exists(watermarked_file): final_file = watermarked_file
|
| 391 |
|
| 392 |
if is_blur and not is_large_video:
|
| 393 |
-
await status_msg.edit_text(f"⏳ Applying {blur_percent}% blur...")
|
| 394 |
radius = max(2, min(20, int((blur_percent / 100.0) * 30)))
|
| 395 |
ext = "jpg" if media_type == "photo" else "mp4"
|
| 396 |
blurred_file = f"{original_file}_blurred.{ext}"
|
|
@@ -403,9 +417,12 @@ async def handle_media_upload(client, message):
|
|
| 403 |
else:
|
| 404 |
ff_filter = ["-vf", f"boxblur={radius}:1"]
|
| 405 |
|
| 406 |
-
if media_type == "photo":
|
| 407 |
-
|
| 408 |
-
|
|
|
|
|
|
|
|
|
|
| 409 |
|
| 410 |
process_blur = await asyncio.create_subprocess_exec(*cmd_blur, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
| 411 |
await process_blur.communicate()
|
|
@@ -563,7 +580,6 @@ async def manual_clean_channel(client, message):
|
|
| 563 |
try:
|
| 564 |
kicked, checked = 0, 0
|
| 565 |
|
| 566 |
-
# ডাটাবেজ থেকে সব ইউজারের আইডি নিয়ে আসা
|
| 567 |
res_users = await db_query(lambda: supabase.table('referrals').select('user_id').execute())
|
| 568 |
if not res_users.data:
|
| 569 |
await message.reply("❌ No users found in database!")
|
|
@@ -573,7 +589,6 @@ async def manual_clean_channel(client, message):
|
|
| 573 |
|
| 574 |
for user_id in set(user_ids):
|
| 575 |
try:
|
| 576 |
-
# বট চেক করবে এই ইউজারটি চ্যানেলে জয়েন করা আছে কিনা
|
| 577 |
chat_member = await client.get_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 578 |
|
| 579 |
if chat_member.status in [enums.ChatMemberStatus.MEMBER, enums.ChatMemberStatus.RESTRICTED]:
|
|
@@ -598,7 +613,7 @@ async def manual_clean_channel(client, message):
|
|
| 598 |
if not is_valid:
|
| 599 |
try:
|
| 600 |
await client.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 601 |
-
await client.unban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 602 |
kicked += 1
|
| 603 |
except Exception: pass
|
| 604 |
|
|
@@ -652,7 +667,7 @@ async def auto_clean_channel_loop():
|
|
| 652 |
except Exception as e:
|
| 653 |
print(f"Auto clean error: {e}")
|
| 654 |
|
| 655 |
-
await asyncio.sleep(4 * 3600)
|
| 656 |
|
| 657 |
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean"]))
|
| 658 |
async def catch_admin_steps(client, message):
|
|
|
|
| 14 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
| 15 |
|
| 16 |
# ================= CONFIGURATION =================
|
|
|
|
| 17 |
BOT_TOKEN = os.environ.get("BOT_TOKEN")
|
| 18 |
API_ID = int(os.environ.get("API_ID", 0))
|
| 19 |
API_HASH = os.environ.get("API_HASH")
|
|
|
|
| 365 |
is_large_video = True
|
| 366 |
is_blur = False
|
| 367 |
|
| 368 |
+
status_msg = await message.reply("⏳ <b>Video is too large!</b> Skipping blur..." if is_large_video else "⏳ Downloading media... 0%")
|
| 369 |
bot_me = client.me if client.me else await client.get_me()
|
| 370 |
bot_link = f"https://t.me/{bot_me.username}"
|
| 371 |
|
| 372 |
original_file, watermarked_file, blurred_file, final_file, embed_link = None, None, None, None, None
|
| 373 |
|
| 374 |
+
# === Progress Bar Function ===
|
| 375 |
+
last_update_time = time.time()
|
| 376 |
+
async def download_progress(current, total):
|
| 377 |
+
nonlocal last_update_time
|
| 378 |
+
now = time.time()
|
| 379 |
+
if now - last_update_time >= 4.0:
|
| 380 |
+
try:
|
| 381 |
+
percent = (current / total) * 100
|
| 382 |
+
await status_msg.edit_text(f"⏳ Downloading media... {percent:.1f}%")
|
| 383 |
+
last_update_time = now
|
| 384 |
+
except Exception:
|
| 385 |
+
pass
|
| 386 |
+
# =============================
|
| 387 |
+
|
| 388 |
try:
|
| 389 |
+
original_file = await message.download(progress=download_progress)
|
| 390 |
final_file = original_file
|
| 391 |
|
| 392 |
+
# High Quality Video Output Settings (-crf 22, -preset fast, -c:a copy)
|
| 393 |
if media_type == "video" and not is_large_video:
|
| 394 |
+
await status_msg.edit_text("⏳ Watermarking video... (High Quality Processing)")
|
| 395 |
watermarked_file = f"{original_file}_wm.mp4"
|
| 396 |
cmd = [
|
| 397 |
"ffmpeg", "-y", "-i", original_file,
|
| 398 |
"-vf", "drawtext=text='@mxvdo':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)'",
|
| 399 |
+
"-c:v", "libx264", "-preset", "fast", "-threads", "2", "-crf", "22",
|
| 400 |
+
"-pix_fmt", "yuv420p", "-c:a", "copy", "-movflags", "+faststart", watermarked_file
|
| 401 |
]
|
| 402 |
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
| 403 |
await process.communicate()
|
| 404 |
if process.returncode == 0 and os.path.exists(watermarked_file): final_file = watermarked_file
|
| 405 |
|
| 406 |
if is_blur and not is_large_video:
|
| 407 |
+
await status_msg.edit_text(f"⏳ Applying {blur_percent}% blur... (High Quality Processing)")
|
| 408 |
radius = max(2, min(20, int((blur_percent / 100.0) * 30)))
|
| 409 |
ext = "jpg" if media_type == "photo" else "mp4"
|
| 410 |
blurred_file = f"{original_file}_blurred.{ext}"
|
|
|
|
| 417 |
else:
|
| 418 |
ff_filter = ["-vf", f"boxblur={radius}:1"]
|
| 419 |
|
| 420 |
+
if media_type == "photo":
|
| 421 |
+
cmd_blur = ["ffmpeg", "-y", "-i", final_file] + ff_filter + [blurred_file]
|
| 422 |
+
elif media_type == "animation":
|
| 423 |
+
cmd_blur = ["ffmpeg", "-y", "-i", final_file] + ff_filter + ["-c:v", "libx264", "-preset", "fast", "-threads", "2", "-pix_fmt", "yuv420p", blurred_file]
|
| 424 |
+
else:
|
| 425 |
+
cmd_blur = ["ffmpeg", "-y", "-i", final_file] + ff_filter + ["-c:v", "libx264", "-preset", "fast", "-threads", "2", "-crf", "22", "-pix_fmt", "yuv420p", "-c:a", "copy", "-movflags", "+faststart", blurred_file]
|
| 426 |
|
| 427 |
process_blur = await asyncio.create_subprocess_exec(*cmd_blur, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
| 428 |
await process_blur.communicate()
|
|
|
|
| 580 |
try:
|
| 581 |
kicked, checked = 0, 0
|
| 582 |
|
|
|
|
| 583 |
res_users = await db_query(lambda: supabase.table('referrals').select('user_id').execute())
|
| 584 |
if not res_users.data:
|
| 585 |
await message.reply("❌ No users found in database!")
|
|
|
|
| 589 |
|
| 590 |
for user_id in set(user_ids):
|
| 591 |
try:
|
|
|
|
| 592 |
chat_member = await client.get_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 593 |
|
| 594 |
if chat_member.status in [enums.ChatMemberStatus.MEMBER, enums.ChatMemberStatus.RESTRICTED]:
|
|
|
|
| 613 |
if not is_valid:
|
| 614 |
try:
|
| 615 |
await client.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 616 |
+
await client.unban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 617 |
kicked += 1
|
| 618 |
except Exception: pass
|
| 619 |
|
|
|
|
| 667 |
except Exception as e:
|
| 668 |
print(f"Auto clean error: {e}")
|
| 669 |
|
| 670 |
+
await asyncio.sleep(4 * 3600)
|
| 671 |
|
| 672 |
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean"]))
|
| 673 |
async def catch_admin_steps(client, message):
|