Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -14,13 +14,13 @@ from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInf
|
|
| 14 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
| 15 |
|
| 16 |
# ================= CONFIGURATION =================
|
| 17 |
-
#
|
| 18 |
-
BOT_TOKEN = os.environ.get("BOT_TOKEN")
|
| 19 |
-
API_ID = int(os.environ.get("API_ID", 2040))
|
| 20 |
-
API_HASH = os.environ.get("API_HASH")
|
| 21 |
-
SUPABASE_URL = os.environ.get("SUPABASE_URL")
|
| 22 |
-
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
|
| 23 |
-
BYSE_API_KEY = os.environ.get("BYSE_API_KEY")
|
| 24 |
|
| 25 |
PREMIUM_CHANNEL_ID = -1002825744390
|
| 26 |
|
|
@@ -28,15 +28,11 @@ PREMIUM_CHANNEL_ID = -1002825744390
|
|
| 28 |
WEB_APP_URL = "https://rony90790.github.io/Forward-bot/index.html"
|
| 29 |
ADMIN_IDS = [7307789267]
|
| 30 |
|
| 31 |
-
# WebApp URL (index.html)
|
| 32 |
-
WEB_APP_URL = "https://rony90790.github.io/Forward-bot/index.html"
|
| 33 |
-
BYSE_API_KEY = "133323knboif885fhgwxvf"
|
| 34 |
-
ADMIN_IDS = [7307789267]
|
| 35 |
-
|
| 36 |
app = Flask(__name__)
|
| 37 |
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
|
| 38 |
admin_states = {}
|
| 39 |
temp_clients = {}
|
|
|
|
| 40 |
try:
|
| 41 |
main_loop = asyncio.get_running_loop()
|
| 42 |
except RuntimeError:
|
|
@@ -402,7 +398,6 @@ async def handle_media_upload(client, message):
|
|
| 402 |
|
| 403 |
if clear_percent > 0:
|
| 404 |
clear_ratio = clear_percent / 100.0
|
| 405 |
-
# FFMPEG Audio Map ফিক্স
|
| 406 |
ff_filter = ["-filter_complex", f"[0:v]split[v1][v2];[v2]boxblur={radius}:1[blurred];[v1]crop=iw:ih*{clear_ratio}:0:0[top];[blurred][top]overlay=0:0[vout]", "-map", "[vout]"]
|
| 407 |
if media_type == "video":
|
| 408 |
ff_filter.extend(["-map", "0:a?"])
|
|
@@ -467,7 +462,6 @@ async def handle_media_upload(client, message):
|
|
| 467 |
sent_to_admin = await client.send_animation(message.chat.id, final_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML)
|
| 468 |
tg_file_id = sent_to_admin.animation.file_id
|
| 469 |
else:
|
| 470 |
-
# Pyrogram V2 thumbnail ফিক্স
|
| 471 |
sent_to_admin = await client.send_video(message.chat.id, final_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML, duration=message.video.duration, width=message.video.width, height=message.video.height, thumbnail=thumb_path)
|
| 472 |
tg_file_id = sent_to_admin.video.file_id
|
| 473 |
|
|
@@ -551,88 +545,104 @@ async def add_png(client, message):
|
|
| 551 |
await message.reply("✅ Now send the Video/Embed Link.")
|
| 552 |
except Exception as e: print(e)
|
| 553 |
|
| 554 |
-
# সেশন টার্মিনেশন চেক এবং কিক আউট করার এডমিন কমান্ড
|
| 555 |
@bot.on_message(filters.command("clean") & filters.private & filters.user(ADMIN_IDS))
|
| 556 |
async def manual_clean_channel(client, message):
|
| 557 |
-
await message.reply("⏳ <b>Starting channel cleanup...</b>\nChecking
|
| 558 |
try:
|
| 559 |
kicked, checked = 0, 0
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
res = await db_query(lambda: supabase.table('user_sessions').select('session_string').eq('user_id', user_id).execute())
|
| 567 |
-
|
| 568 |
-
is_valid = False
|
| 569 |
-
if res.data:
|
| 570 |
-
session_string = res.data[0]['session_string']
|
| 571 |
-
temp_client = Client(f"manual_chk_{user_id}", session_string=session_string, api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 572 |
-
try:
|
| 573 |
-
await temp_client.connect()
|
| 574 |
-
await temp_client.get_me()
|
| 575 |
-
await temp_client.disconnect()
|
| 576 |
-
is_valid = True
|
| 577 |
-
except Exception:
|
| 578 |
-
try: await temp_client.disconnect()
|
| 579 |
-
except: pass
|
| 580 |
-
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 581 |
-
|
| 582 |
-
if not is_valid:
|
| 583 |
-
try:
|
| 584 |
-
await client.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 585 |
-
await client.unban_chat_member(PREMIUM_CHANNEL_ID, user_id) # Kick only (allows re-join later)
|
| 586 |
-
kicked += 1
|
| 587 |
-
except Exception as e: pass
|
| 588 |
|
| 589 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 590 |
|
| 591 |
-
await message.reply(f"✅ <b>Cleanup Complete!</b>\n\n👥 Members checked: {checked}\n👢 Users Kicked
|
| 592 |
except Exception as e:
|
| 593 |
await message.reply(f"❌ Error: {e}")
|
| 594 |
|
| 595 |
-
# সেশন টার্মিনেশনের অটো ব্যাকগ্রাউন্ড চেকার লুপ
|
| 596 |
async def auto_clean_channel_loop():
|
| 597 |
-
await asyncio.sleep(60)
|
| 598 |
while True:
|
| 599 |
try:
|
| 600 |
-
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
user_id = member.user.id
|
| 605 |
-
res = await db_query(lambda: supabase.table('user_sessions').select('session_string').eq('user_id', user_id).execute())
|
| 606 |
-
|
| 607 |
-
is_valid = False
|
| 608 |
-
if res.data:
|
| 609 |
-
session_string = res.data[0]['session_string']
|
| 610 |
-
temp_client = Client(f"bg_chk_{user_id}", session_string=session_string, api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 611 |
try:
|
| 612 |
-
await
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
| 616 |
-
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 620 |
except Exception:
|
| 621 |
-
|
| 622 |
-
except: pass
|
| 623 |
-
is_valid = True # নেটওয়ার্ক এরর হলে যেন ইউজার কিক না খায়!
|
| 624 |
-
|
| 625 |
-
if not is_valid:
|
| 626 |
-
try:
|
| 627 |
-
await bot.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 628 |
-
await bot.unban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 629 |
-
except Exception: pass
|
| 630 |
-
|
| 631 |
-
await asyncio.sleep(2)
|
| 632 |
except Exception as e:
|
| 633 |
print(f"Auto clean error: {e}")
|
| 634 |
|
| 635 |
-
await asyncio.sleep(4 * 3600) #
|
| 636 |
|
| 637 |
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean"]))
|
| 638 |
async def catch_admin_steps(client, message):
|
|
@@ -653,6 +663,7 @@ async def catch_admin_steps(client, message):
|
|
| 653 |
await process_broadcast(client, message)
|
| 654 |
|
| 655 |
def run_flask(): app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
|
|
|
|
| 656 |
async def main():
|
| 657 |
await bot.start()
|
| 658 |
print("🤖 Pyrogram Bot & Real Session API is running!")
|
|
|
|
| 14 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
| 15 |
|
| 16 |
# ================= CONFIGURATION =================
|
| 17 |
+
# Environment Variable বা Secret থেকে টোকেনগুলো নেওয়া হচ্ছে (যদি সেট করা না থাকে, তবে ডিফল্টগুলো ব্যবহৃত হবে)
|
| 18 |
+
BOT_TOKEN = os.environ.get("BOT_TOKEN", "8628213901:AAFvfHBpZ6tok40ZQuhIDLAVIMrHeiheMNY")
|
| 19 |
+
API_ID = int(os.environ.get("API_ID", 2040))
|
| 20 |
+
API_HASH = os.environ.get("API_HASH", "b18441a1ff607e10a989891a5462e627")
|
| 21 |
+
SUPABASE_URL = os.environ.get("SUPABASE_URL", "https://yctirvnryrzygoxbpvoy.supabase.co")
|
| 22 |
+
SUPABASE_KEY = os.environ.get("SUPABASE_KEY", "sb_publishable_aBcD-atruskWwoCiLr0lWw_inT8GLoN")
|
| 23 |
+
BYSE_API_KEY = os.environ.get("BYSE_API_KEY", "133323knboif885fhgwxvf")
|
| 24 |
|
| 25 |
PREMIUM_CHANNEL_ID = -1002825744390
|
| 26 |
|
|
|
|
| 28 |
WEB_APP_URL = "https://rony90790.github.io/Forward-bot/index.html"
|
| 29 |
ADMIN_IDS = [7307789267]
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
app = Flask(__name__)
|
| 32 |
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
|
| 33 |
admin_states = {}
|
| 34 |
temp_clients = {}
|
| 35 |
+
|
| 36 |
try:
|
| 37 |
main_loop = asyncio.get_running_loop()
|
| 38 |
except RuntimeError:
|
|
|
|
| 398 |
|
| 399 |
if clear_percent > 0:
|
| 400 |
clear_ratio = clear_percent / 100.0
|
|
|
|
| 401 |
ff_filter = ["-filter_complex", f"[0:v]split[v1][v2];[v2]boxblur={radius}:1[blurred];[v1]crop=iw:ih*{clear_ratio}:0:0[top];[blurred][top]overlay=0:0[vout]", "-map", "[vout]"]
|
| 402 |
if media_type == "video":
|
| 403 |
ff_filter.extend(["-map", "0:a?"])
|
|
|
|
| 462 |
sent_to_admin = await client.send_animation(message.chat.id, final_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML)
|
| 463 |
tg_file_id = sent_to_admin.animation.file_id
|
| 464 |
else:
|
|
|
|
| 465 |
sent_to_admin = await client.send_video(message.chat.id, final_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML, duration=message.video.duration, width=message.video.width, height=message.video.height, thumbnail=thumb_path)
|
| 466 |
tg_file_id = sent_to_admin.video.file_id
|
| 467 |
|
|
|
|
| 545 |
await message.reply("✅ Now send the Video/Embed Link.")
|
| 546 |
except Exception as e: print(e)
|
| 547 |
|
| 548 |
+
# সেশন টার্মিনেশন চেক এবং কিক আউট করার এডমিন কমান্ড (সংশোধিত - Peer ID error Fixed)
|
| 549 |
@bot.on_message(filters.command("clean") & filters.private & filters.user(ADMIN_IDS))
|
| 550 |
async def manual_clean_channel(client, message):
|
| 551 |
+
await message.reply("⏳ <b>Starting channel cleanup...</b>\nChecking database users to verify active sessions. This might take a while.")
|
| 552 |
try:
|
| 553 |
kicked, checked = 0, 0
|
| 554 |
+
|
| 555 |
+
# ডাটাবেজ থেকে সব ইউজারের আইডি নিয়ে আসা
|
| 556 |
+
res_users = await db_query(lambda: supabase.table('referrals').select('user_id').execute())
|
| 557 |
+
if not res_users.data:
|
| 558 |
+
await message.reply("❌ No users found in database!")
|
| 559 |
+
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 560 |
|
| 561 |
+
user_ids = [u['user_id'] for u in res_users.data]
|
| 562 |
+
|
| 563 |
+
for user_id in set(user_ids):
|
| 564 |
+
try:
|
| 565 |
+
# বট চেক করবে এই ইউজারটি চ্যানেলে জয়েন করা আছে কিনা
|
| 566 |
+
chat_member = await client.get_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 567 |
+
|
| 568 |
+
if chat_member.status in [enums.ChatMemberStatus.MEMBER, enums.ChatMemberStatus.RESTRICTED]:
|
| 569 |
+
checked += 1
|
| 570 |
+
|
| 571 |
+
res_session = await db_query(lambda: supabase.table('user_sessions').select('session_string').eq('user_id', user_id).execute())
|
| 572 |
+
|
| 573 |
+
is_valid = False
|
| 574 |
+
if res_session.data:
|
| 575 |
+
session_string = res_session.data[0]['session_string']
|
| 576 |
+
temp_client = Client(f"manual_chk_{user_id}", session_string=session_string, api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 577 |
+
try:
|
| 578 |
+
await temp_client.connect()
|
| 579 |
+
await temp_client.get_me()
|
| 580 |
+
await temp_client.disconnect()
|
| 581 |
+
is_valid = True
|
| 582 |
+
except Exception:
|
| 583 |
+
try: await temp_client.disconnect()
|
| 584 |
+
except: pass
|
| 585 |
+
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 586 |
+
|
| 587 |
+
if not is_valid:
|
| 588 |
+
try:
|
| 589 |
+
await client.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 590 |
+
await client.unban_chat_member(PREMIUM_CHANNEL_ID, user_id) # Kick only
|
| 591 |
+
kicked += 1
|
| 592 |
+
except Exception: pass
|
| 593 |
+
|
| 594 |
+
await asyncio.sleep(1.5)
|
| 595 |
+
except Exception:
|
| 596 |
+
pass
|
| 597 |
|
| 598 |
+
await message.reply(f"✅ <b>Cleanup Complete!</b>\n\n👥 Members checked: {checked}\n👢 Users Kicked: {kicked}")
|
| 599 |
except Exception as e:
|
| 600 |
await message.reply(f"❌ Error: {e}")
|
| 601 |
|
| 602 |
+
# সেশন টার্মিনেশনের অটো ব্যাকগ্রাউন্ড চেকার লুপ (সংশোধিত - Peer ID error Fixed)
|
| 603 |
async def auto_clean_channel_loop():
|
| 604 |
+
await asyncio.sleep(60)
|
| 605 |
while True:
|
| 606 |
try:
|
| 607 |
+
res_users = await db_query(lambda: supabase.table('referrals').select('user_id').execute())
|
| 608 |
+
if res_users.data:
|
| 609 |
+
user_ids = [u['user_id'] for u in res_users.data]
|
| 610 |
+
for user_id in set(user_ids):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
try:
|
| 612 |
+
chat_member = await bot.get_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 613 |
+
if chat_member.status in [enums.ChatMemberStatus.MEMBER, enums.ChatMemberStatus.RESTRICTED]:
|
| 614 |
+
res_session = await db_query(lambda: supabase.table('user_sessions').select('session_string').eq('user_id', user_id).execute())
|
| 615 |
+
|
| 616 |
+
is_valid = False
|
| 617 |
+
if res_session.data:
|
| 618 |
+
session_string = res_session.data[0]['session_string']
|
| 619 |
+
temp_client = Client(f"bg_chk_{user_id}", session_string=session_string, api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 620 |
+
try:
|
| 621 |
+
await temp_client.connect()
|
| 622 |
+
await temp_client.get_me()
|
| 623 |
+
await temp_client.disconnect()
|
| 624 |
+
is_valid = True
|
| 625 |
+
except (SessionRevoked, AuthKeyUnregistered, UserDeactivated):
|
| 626 |
+
try: await temp_client.disconnect()
|
| 627 |
+
except: pass
|
| 628 |
+
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 629 |
+
except Exception:
|
| 630 |
+
try: await temp_client.disconnect()
|
| 631 |
+
except: pass
|
| 632 |
+
is_valid = True
|
| 633 |
+
|
| 634 |
+
if not is_valid:
|
| 635 |
+
try:
|
| 636 |
+
await bot.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 637 |
+
await bot.unban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 638 |
+
except Exception: pass
|
| 639 |
+
await asyncio.sleep(2)
|
| 640 |
except Exception:
|
| 641 |
+
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 642 |
except Exception as e:
|
| 643 |
print(f"Auto clean error: {e}")
|
| 644 |
|
| 645 |
+
await asyncio.sleep(4 * 3600) # প্রতি ৪ ঘণ্টা পর পর রান হবে
|
| 646 |
|
| 647 |
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean"]))
|
| 648 |
async def catch_admin_steps(client, message):
|
|
|
|
| 663 |
await process_broadcast(client, message)
|
| 664 |
|
| 665 |
def run_flask(): app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
|
| 666 |
+
|
| 667 |
async def main():
|
| 668 |
await bot.start()
|
| 669 |
print("🤖 Pyrogram Bot & Real Session API is running!")
|