VisionByte/replit-host-bot
0
1import logging2import json3import os4import re5from datetime import datetime6from telegram import (7 Update, InlineKeyboardButton, InlineKeyboardMarkup,8 BotCommand9)10from telegram.ext import (11 Application, CommandHandler, MessageHandler,12 CallbackQueryHandler, ContextTypes, ConversationHandler, filters13)14from telegram.constants import ParseMode15 16# ─── Config ───────────────────────────────────────────────────────────────────17BOT_TOKEN = "8642217017:AAEHsExfWGqxNUFgOx6bXGuyNtABAdvJBV0"18ADMIN_ID = 877922051819DB_FILE = "database.json"20 21logging.basicConfig(22 format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",23 level=logging.INFO24)25logger = logging.getLogger(__name__)26 27# ─── Conversation States ───────────────────────────────────────────────────────28WAITING_TOKEN, WAITING_CODE, WAITING_BOT_NAME, WAITING_BROADCAST = range(4)29 30# ─── Database ──────────────────────────────────────────────────────────────────31def load_db():32 if not os.path.exists(DB_FILE):33 return {"users": {}, "bots": {}, "stats": {"total_hosted": 0}}34 with open(DB_FILE, "r", encoding="utf-8") as f:35 return json.load(f)36 37def save_db(db):38 with open(DB_FILE, "w", encoding="utf-8") as f:39 json.dump(db, f, ensure_ascii=False, indent=2)40 41def register_user(user_id: int, username: str, full_name: str):42 db = load_db()43 uid = str(user_id)44 if uid not in db["users"]:45 db["users"][uid] = {46 "username": username,47 "full_name": full_name,48 "joined": datetime.now().isoformat(),49 "bots": [],50 "banned": False51 }52 save_db(db)53 return db["users"][uid]54 55def is_banned(user_id: int) -> bool:56 db = load_db()57 uid = str(user_id)58 return db["users"].get(uid, {}).get("banned", False)59 60# ─── Helpers ───────────────────────────────────────────────────────────────────61def validate_token(token: str) -> bool:62 return bool(re.match(r"^\d{8,12}:[A-Za-z0-9_-]{35}$", token.strip()))63 64def back_btn(callback="main_menu"):65 return InlineKeyboardMarkup([[66 InlineKeyboardButton("🔙 رجوع | Back", callback_data=callback)67 ]])68 69def generate_replit_files(bot_token: str, bot_code: str, bot_name: str) -> dict:70 """Generate all Replit config files"""71 72 replit_nix = '''{ pkgs }: {73 deps = [74 pkgs.python31175 pkgs.python311Packages.pip76 ];77}'''78 79 replit_config = f'''run = "python main.py"80entrypoint = "main.py"81 82[nix]83channel = "stable-23_11"84 85[deployment]86run = ["sh", "-c", "python main.py"]87deploymentTarget = "cloudrun"88 89[[ports]]90localPort = 808091externalPort = 8092'''93 94 requirements = '''python-telegram-bot==21.695requests96'''97 98 keep_alive = '''from flask import Flask99from threading import Thread100 101app = Flask("")102 103@app.route("/")104def home():105 return "Bot is alive! 🤖"106 107def run():108 app.run(host="0.0.0.0", port=8080)109 110def keep_alive():111 t = Thread(target=run)112 t.start()113'''114 115 main_py = f'''# ═══════════════════════════════════════════116# Bot: {bot_name}117# Hosted via @ReplitHostBot118# Generated automatically119# ═══════════════════════════════════════════120 121import os122from keep_alive import keep_alive123 124# Keep the bot alive on Replit125keep_alive()126 127# ─── Your Bot Code Below ───────────────────128{bot_code}129'''130 131 return {132 "main.py": main_py,133 "keep_alive.py": keep_alive,134 "requirements.txt": requirements,135 ".replit": replit_config,136 "replit.nix": replit_nix,137 }138 139# ─── /start ────────────────────────────────────────────────────────────────────140async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):141 user = update.effective_user142 if is_banned(user.id):143 await update.message.reply_text("🚫 تم حظرك من استخدام البوت.\n🚫 You are banned from using this bot.")144 return145 146 register_user(user.id, user.username or "", user.full_name or "")147 148 text = (149 "╔══════════════════════════════╗\n"150 "║ 🚀 *Replit Host Bot* ║\n"151 "╚══════════════════════════════╝\n\n"152 "🇸🇦 *مرحباً بك في بوت الاستضافة المجانية!*\n"153 "استضف بوت تيليجرام الخاص بك مجاناً على Replit في دقائق.\n\n"154 "🇬🇧 *Welcome to the Free Hosting Bot!*\n"155 "Host your Telegram bot on Replit for free in minutes.\n\n"156 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"157 "📌 *ما الذي يقدمه هذا البوت؟*\n"158 "• توليد ملفات Replit تلقائياً\n"159 "• دليل خطوة بخطوة مصوّر\n"160 "• إدارة بوتاتك المسجّلة\n\n"161 "📌 *What does this bot offer?*\n"162 "• Auto-generate Replit config files\n"163 "• Step-by-step visual guide\n"164 "• Manage your registered bots"165 )166 167 keyboard = InlineKeyboardMarkup([168 [InlineKeyboardButton("🚀 استضف بوت | Host a Bot", callback_data="host_bot")],169 [InlineKeyboardButton("📋 بوتاتي | My Bots", callback_data="my_bots"),170 InlineKeyboardButton("📖 دليل | Guide", callback_data="guide")],171 [InlineKeyboardButton("ℹ️ عن البوت | About", callback_data="about"),172 InlineKeyboardButton("📞 دعم | Support", callback_data="support")],173 ])174 175 await update.message.reply_text(text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)176 177# ─── Main Menu Callback ────────────────────────────────────────────────────────178async def main_menu_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):179 query = update.callback_query180 await query.answer()181 user = update.effective_user182 if is_banned(user.id):183 await query.edit_message_text("🚫 تم حظرك.\n🚫 You are banned.")184 return185 186 text = (187 "╔══════════════════════════════╗\n"188 "║ 🚀 *Replit Host Bot* ║\n"189 "╚══════════════════════════════╝\n\n"190 "🇸🇦 *مرحباً بك في بوت الاستضافة المجانية!*\n\n"191 "🇬🇧 *Welcome to the Free Hosting Bot!*"192 )193 keyboard = InlineKeyboardMarkup([194 [InlineKeyboardButton("🚀 استضف بوت | Host a Bot", callback_data="host_bot")],195 [InlineKeyboardButton("📋 بوتاتي | My Bots", callback_data="my_bots"),196 InlineKeyboardButton("📖 دليل | Guide", callback_data="guide")],197 [InlineKeyboardButton("ℹ️ عن البوت | About", callback_data="about"),198 InlineKeyboardButton("📞 دعم | Support", callback_data="support")],199 ])200 await query.edit_message_text(text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)201 202# ─── Host Bot Flow ─────────────────────────────────────────────────────────────203async def host_bot_start(update: Update, context: ContextTypes.DEFAULT_TYPE):204 query = update.callback_query205 await query.answer()206 207 text = (208 "🚀 *استضافة بوت جديد | Host a New Bot*\n\n"209 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"210 "🇸🇦 *الخطوة 1/3:* أرسل توكن البوت\n"211 "احصل عليه من @BotFather\n\n"212 "🇬🇧 *Step 1/3:* Send your bot token\n"213 "Get it from @BotFather\n\n"214 "📌 *مثال | Example:*\n"215 "`1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ`"216 )217 await query.edit_message_text(text, reply_markup=back_btn(), parse_mode=ParseMode.MARKDOWN)218 return WAITING_TOKEN219 220async def receive_token(update: Update, context: ContextTypes.DEFAULT_TYPE):221 user = update.effective_user222 if is_banned(user.id):223 return ConversationHandler.END224 225 token = update.message.text.strip()226 227 if not validate_token(token):228 await update.message.reply_text(229 "❌ *توكن غير صحيح | Invalid Token*\n\n"230 "🇸🇦 تأكد من نسخ التوكن كاملاً من @BotFather\n"231 "🇬🇧 Make sure to copy the full token from @BotFather\n\n"232 "🔄 أرسل التوكن مجدداً | Send the token again:",233 parse_mode=ParseMode.MARKDOWN234 )235 return WAITING_TOKEN236 237 context.user_data["pending_token"] = token238 239 text = (240 "✅ *تم استلام التوكن | Token Received*\n\n"241 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"242 "🇸🇦 *الخطوة 2/3:* أرسل اسماً للبوت\n"243 "(للتعريف فقط - مثال: My Echo Bot)\n\n"244 "🇬🇧 *Step 2/3:* Send a name for the bot\n"245 "(For identification only - e.g. My Echo Bot)"246 )247 await update.message.reply_text(text, reply_markup=back_btn(), parse_mode=ParseMode.MARKDOWN)248 return WAITING_BOT_NAME249 250async def receive_bot_name(update: Update, context: ContextTypes.DEFAULT_TYPE):251 name = update.message.text.strip()252 if len(name) > 50:253 await update.message.reply_text("❌ الاسم طويل جداً (max 50 chars). أرسل اسماً أقصر:")254 return WAITING_BOT_NAME255 256 context.user_data["pending_name"] = name257 258 text = (259 f"✅ *الاسم: {name}*\n\n"260 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"261 "🇸🇦 *الخطوة 3/3:* أرسل كود البوت\n"262 "• أرسله كملف `.py` أو نص عادي\n"263 "• تأكد أن الكود يعمل بشكل صحيح\n\n"264 "🇬🇧 *Step 3/3:* Send your bot code\n"265 "• Send as `.py` file or plain text\n"266 "• Make sure the code works correctly\n\n"267 "⚠️ *ملاحظة | Note:*\n"268 "لا تضع التوكن داخل الكود — سيُضاف تلقائياً\n"269 "Don't put the token in code — it will be added automatically"270 )271 await update.message.reply_text(text, reply_markup=back_btn(), parse_mode=ParseMode.MARKDOWN)272 return WAITING_CODE273 274async def receive_code(update: Update, context: ContextTypes.DEFAULT_TYPE):275 user = update.effective_user276 bot_code = ""277 278 # Accept file or text279 if update.message.document:280 if not update.message.document.file_name.endswith(".py"):281 await update.message.reply_text("❌ أرسل ملف `.py` فقط | Send only `.py` files")282 return WAITING_CODE283 file = await update.message.document.get_file()284 file_bytes = await file.download_as_bytearray()285 bot_code = file_bytes.decode("utf-8")286 elif update.message.text:287 bot_code = update.message.text.strip()288 else:289 await update.message.reply_text("❌ أرسل الكود كنص أو ملف .py | Send code as text or .py file")290 return WAITING_CODE291 292 token = context.user_data.get("pending_token")293 bot_name = context.user_data.get("pending_name", "My Bot")294 295 # Generate files296 files = generate_replit_files(token, bot_code, bot_name)297 298 # Save to DB299 db = load_db()300 uid = str(user.id)301 bot_id = f"bot_{datetime.now().strftime('%Y%m%d%H%M%S')}_{user.id}"302 303 db["bots"][bot_id] = {304 "owner_id": user.id,305 "name": bot_name,306 "token_preview": token[:12] + "...",307 "created": datetime.now().isoformat(),308 "status": "pending_deploy"309 }310 if uid not in db["users"]:311 db["users"][uid] = {"bots": [], "banned": False}312 db["users"][uid].setdefault("bots", []).append(bot_id)313 db["stats"]["total_hosted"] = db["stats"].get("total_hosted", 0) + 1314 save_db(db)315 316 # Send each file317 await update.message.reply_text(318 "✅ *تم توليد الملفات بنجاح! | Files generated successfully!*\n\n"319 "📂 سأرسل لك الآن كل الملفات المطلوبة:\n"320 "📂 I'll now send you all required files:",321 parse_mode=ParseMode.MARKDOWN322 )323 324 file_descriptions = {325 "main.py": "📄 *main.py* — الكود الرئيسي للبوت | Main bot code",326 "keep_alive.py": "📄 *keep_alive.py* — للإبقاء على البوت حياً | Keeps bot alive",327 "requirements.txt": "📄 *requirements.txt* — المكتبات المطلوبة | Required libraries",328 ".replit": "⚙️ *.replit* — إعدادات Replit | Replit config",329 "replit.nix": "⚙️ *replit.nix* — بيئة Python | Python environment",330 }331 332 for filename, content in files.items():333 desc = file_descriptions.get(filename, f"📄 *{filename}*")334 await update.message.reply_text(desc, parse_mode=ParseMode.MARKDOWN)335 336 # Send as file337 import io338 file_obj = io.BytesIO(content.encode("utf-8"))339 file_obj.name = filename340 await update.message.reply_document(document=file_obj, filename=filename)341 342 # Send guide343 guide_text = (344 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"345 "📖 *خطوات الرفع على Replit | Upload Steps*\n"346 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"347 "1️⃣ افتح [replit.com](https://replit.com) وسجّل دخول\n"348 " *Open replit.com and sign in*\n\n"349 "2️⃣ اضغط *Create Repl* ← اختر *Python*\n"350 " *Click Create Repl → Choose Python*\n\n"351 "3️⃣ احذف الملفات الموجودة كلها\n"352 " *Delete all existing files*\n\n"353 "4️⃣ ارفع الملفات اللي بعثتهالك (Import Files)\n"354 " *Upload the files I sent you*\n\n"355 "5️⃣ اضغط *Run* ▶️\n"356 " *Click Run ▶️*\n\n"357 "6️⃣ 🎉 البوت شغّال!\n"358 " *🎉 Your bot is running!*\n\n"359 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"360 "💡 *نصيحة | Tip:*\n"361 "للإبقاء على البوت 24/7، استخدم [UptimeRobot](https://uptimerobot.com) مجاناً\n"362 "To keep bot 24/7, use UptimeRobot for free\n\n"363 "❓ مشكلة؟ اضغط /support"364 )365 366 keyboard = InlineKeyboardMarkup([367 [InlineKeyboardButton("📋 بوتاتي | My Bots", callback_data="my_bots")],368 [InlineKeyboardButton("🏠 القائمة الرئيسية | Main Menu", callback_data="main_menu")]369 ])370 await update.message.reply_text(guide_text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN,371 disable_web_page_preview=True)372 373 context.user_data.clear()374 return ConversationHandler.END375 376async def cancel_host(update: Update, context: ContextTypes.DEFAULT_TYPE):377 context.user_data.clear()378 if update.callback_query:379 await update.callback_query.answer()380 await main_menu_callback(update, context)381 return ConversationHandler.END382 383# ─── My Bots ───────────────────────────────────────────────────────────────────384async def my_bots(update: Update, context: ContextTypes.DEFAULT_TYPE):385 query = update.callback_query386 await query.answer()387 user = update.effective_user388 389 db = load_db()390 uid = str(user.id)391 user_bots = db["users"].get(uid, {}).get("bots", [])392 393 if not user_bots:394 text = (395 "📋 *بوتاتي | My Bots*\n\n"396 "🇸🇦 لا يوجد بوتات مسجّلة بعد.\n"397 "🇬🇧 No bots registered yet.\n\n"398 "اضغط 🚀 لاستضافة أول بوت!"399 )400 keyboard = InlineKeyboardMarkup([401 [InlineKeyboardButton("🚀 استضف بوت | Host a Bot", callback_data="host_bot")],402 [InlineKeyboardButton("🔙 رجوع | Back", callback_data="main_menu")]403 ])404 await query.edit_message_text(text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)405 return406 407 text = "📋 *بوتاتي المسجّلة | My Registered Bots*\n\n"408 keyboard_buttons = []409 410 for bot_id in user_bots:411 bot = db["bots"].get(bot_id)412 if bot:413 created = bot["created"][:10]414 text += f"🤖 *{bot['name']}*\n"415 text += f" 📅 {created} | 🔑 `{bot['token_preview']}`\n\n"416 keyboard_buttons.append([417 InlineKeyboardButton(f"🗑️ حذف {bot['name']}", callback_data=f"del_{bot_id}")418 ])419 420 keyboard_buttons.append([InlineKeyboardButton("🔙 رجوع | Back", callback_data="main_menu")])421 await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard_buttons),422 parse_mode=ParseMode.MARKDOWN)423 424async def delete_bot_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):425 query = update.callback_query426 await query.answer()427 bot_id = query.data.replace("del_", "")428 user = update.effective_user429 430 db = load_db()431 uid = str(user.id)432 433 if bot_id in db["bots"] and db["bots"][bot_id]["owner_id"] == user.id:434 del db["bots"][bot_id]435 if uid in db["users"] and bot_id in db["users"][uid].get("bots", []):436 db["users"][uid]["bots"].remove(bot_id)437 save_db(db)438 await query.answer("✅ تم الحذف | Deleted", show_alert=True)439 440 await my_bots(update, context)441 442# ─── Guide ─────────────────────────────────────────────────────────────────────443async def guide(update: Update, context: ContextTypes.DEFAULT_TYPE):444 query = update.callback_query445 await query.answer()446 447 text = (448 "📖 *دليل الاستضافة الكامل | Full Hosting Guide*\n"449 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"450 "🔵 *ما هو Replit؟ | What is Replit?*\n"451 "منصة مجانية لتشغيل الكود مباشرة في المتصفح.\n"452 "Free platform to run code directly in browser.\n\n"453 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"454 "📋 *خطوات الاستضافة | Hosting Steps:*\n\n"455 "1️⃣ سجّل في [replit.com](https://replit.com)\n"456 "2️⃣ اضغط *+ Create Repl*\n"457 "3️⃣ اختر *Python* كنوع المشروع\n"458 "4️⃣ ارفع الملفات اللي أرسلها البوت\n"459 "5️⃣ اضغط ▶️ *Run*\n"460 "6️⃣ بوتك شغّال! 🎉\n\n"461 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"462 "⏰ *الإبقاء على البوت 24/7:*\n\n"463 "1️⃣ سجّل في [uptimerobot.com](https://uptimerobot.com)\n"464 "2️⃣ أضف Monitor جديد (HTTP)\n"465 "3️⃣ ضع رابط Replit بتاعك\n"466 "4️⃣ البوت هيشتغل طول الوقت! ✅\n\n"467 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"468 "❓ *مشاكل شائعة | Common Issues:*\n\n"469 "• *البوت بيوقف بعد فترة* → استخدم UptimeRobot\n"470 "• *خطأ في المكتبات* → تأكد من requirements.txt\n"471 "• *التوكن خاطئ* → راجع @BotFather"472 )473 474 await query.edit_message_text(text, reply_markup=back_btn(), parse_mode=ParseMode.MARKDOWN,475 disable_web_page_preview=True)476 477# ─── About ─────────────────────────────────────────────────────────────────────478async def about(update: Update, context: ContextTypes.DEFAULT_TYPE):479 query = update.callback_query480 await query.answer()481 482 db = load_db()483 total = db["stats"].get("total_hosted", 0)484 total_users = len(db["users"])485 486 text = (487 "ℹ️ *عن البوت | About the Bot*\n"488 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"489 "🤖 *Replit Host Bot*\n"490 "بوت لاستضافة بوتات تيليجرام مجاناً\n"491 "Free Telegram bot hosting assistant\n\n"492 f"📊 *إحصائيات | Statistics:*\n"493 f"• 👥 المستخدمون | Users: `{total_users}`\n"494 f"• 🚀 بوتات تمت استضافتها | Bots hosted: `{total}`\n\n"495 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"496 "⚙️ *التقنيات المستخدمة | Tech Stack:*\n"497 "• Python 3.11\n"498 "• python-telegram-bot 21.6\n"499 "• Replit Free Tier\n\n"500 "💚 *مجاني تماماً | 100% Free*"501 )502 await query.edit_message_text(text, reply_markup=back_btn(), parse_mode=ParseMode.MARKDOWN)503 504# ─── Support ───────────────────────────────────────────────────────────────────505async def support(update: Update, context: ContextTypes.DEFAULT_TYPE):506 query = update.callback_query507 await query.answer()508 509 text = (510 "📞 *الدعم الفني | Support*\n"511 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"512 "🇸🇦 هل واجهت مشكلة؟ أرسل وصف المشكلة للأدمن:\n"513 "🇬🇧 Facing an issue? Send your problem to admin:\n\n"514 "👤 *Admin:* @YourUsername\n\n"515 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"516 "📌 *قبل التواصل، تأكد من:*\n"517 "• قراءة الدليل /guide\n"518 "• تحميل جميع الملفات\n"519 "• التوكن صحيح"520 )521 await query.edit_message_text(text, reply_markup=back_btn(), parse_mode=ParseMode.MARKDOWN)522 523# ─── Admin Panel ───────────────────────────────────────────────────────────────524async def admin(update: Update, context: ContextTypes.DEFAULT_TYPE):525 if update.effective_user.id != ADMIN_ID:526 await update.message.reply_text("🚫 غير مصرح | Not authorized")527 return528 529 db = load_db()530 total_users = len(db["users"])531 total_bots = len(db["bots"])532 banned = sum(1 for u in db["users"].values() if u.get("banned"))533 534 text = (535 "🔧 *لوحة الأدمن | Admin Panel*\n"536 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"537 f"👥 المستخدمون: `{total_users}`\n"538 f"🤖 البوتات: `{total_bots}`\n"539 f"🚫 المحظورون: `{banned}`\n"540 f"🚀 إجمالي الاستضافات: `{db['stats'].get('total_hosted', 0)}`\n\n"541 )542 543 keyboard = InlineKeyboardMarkup([544 [InlineKeyboardButton("👥 المستخدمون | Users", callback_data="admin_users")],545 [InlineKeyboardButton("📢 بث رسالة | Broadcast", callback_data="admin_broadcast")],546 [InlineKeyboardButton("🤖 كل البوتات | All Bots", callback_data="admin_all_bots")],547 ])548 await update.message.reply_text(text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)549 550async def admin_users(update: Update, context: ContextTypes.DEFAULT_TYPE):551 query = update.callback_query552 await query.answer()553 if update.effective_user.id != ADMIN_ID:554 return555 556 db = load_db()557 text = "👥 *قائمة المستخدمين | Users List*\n\n"558 559 for uid, udata in list(db["users"].items())[:20]:560 status = "🚫" if udata.get("banned") else "✅"561 name = udata.get("full_name", "Unknown")562 bots_count = len(udata.get("bots", []))563 text += f"{status} `{uid}` — {name} — 🤖 {bots_count}\n"564 565 keyboard = InlineKeyboardMarkup([566 [InlineKeyboardButton("🚫 حظر مستخدم | Ban User", callback_data="admin_ban")],567 [InlineKeyboardButton("✅ رفع حظر | Unban User", callback_data="admin_unban")],568 [InlineKeyboardButton("🔙 رجوع", callback_data="admin_back")]569 ])570 await query.edit_message_text(text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)571 572async def admin_all_bots(update: Update, context: ContextTypes.DEFAULT_TYPE):573 query = update.callback_query574 await query.answer()575 if update.effective_user.id != ADMIN_ID:576 return577 578 db = load_db()579 text = "🤖 *كل البوتات | All Bots*\n\n"580 581 for bid, bdata in list(db["bots"].items())[:15]:582 text += f"• *{bdata['name']}* — 👤 `{bdata['owner_id']}` — 📅 {bdata['created'][:10]}\n"583 584 if not db["bots"]:585 text += "لا يوجد بوتات مسجّلة بعد."586 587 await query.edit_message_text(text, reply_markup=back_btn("admin_back"), parse_mode=ParseMode.MARKDOWN)588 589async def admin_ban_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):590 if update.effective_user.id != ADMIN_ID:591 return592 args = context.args593 if not args:594 await update.message.reply_text("الاستخدام: /ban [user_id]")595 return596 uid = args[0]597 db = load_db()598 if uid in db["users"]:599 db["users"][uid]["banned"] = True600 save_db(db)601 await update.message.reply_text(f"✅ تم حظر المستخدم `{uid}`", parse_mode=ParseMode.MARKDOWN)602 else:603 await update.message.reply_text("❌ المستخدم غير موجود")604 605async def admin_unban_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):606 if update.effective_user.id != ADMIN_ID:607 return608 args = context.args609 if not args:610 await update.message.reply_text("الاستخدام: /unban [user_id]")611 return612 uid = args[0]613 db = load_db()614 if uid in db["users"]:615 db["users"][uid]["banned"] = False616 save_db(db)617 await update.message.reply_text(f"✅ تم رفع الحظر عن `{uid}`", parse_mode=ParseMode.MARKDOWN)618 else:619 await update.message.reply_text("❌ المستخدم غير موجود")620 621async def admin_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):622 if update.effective_user.id != ADMIN_ID:623 return624 db = load_db()625 text = (626 "📊 *إحصائيات | Statistics*\n\n"627 f"👥 المستخدمون: `{len(db['users'])}`\n"628 f"🤖 البوتات المسجّلة: `{len(db['bots'])}`\n"629 f"🚀 إجمالي الاستضافات: `{db['stats'].get('total_hosted', 0)}`\n"630 f"🚫 المحظورون: `{sum(1 for u in db['users'].values() if u.get('banned'))}`"631 )632 await update.message.reply_text(text, parse_mode=ParseMode.MARKDOWN)633 634# Broadcast635broadcast_waiting = {}636 637async def admin_broadcast_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):638 query = update.callback_query639 await query.answer()640 if update.effective_user.id != ADMIN_ID:641 return642 await query.edit_message_text(643 "📢 *بث رسالة | Broadcast*\n\nأرسل الرسالة الآن:",644 reply_markup=back_btn("admin_back"),645 parse_mode=ParseMode.MARKDOWN646 )647 broadcast_waiting[update.effective_user.id] = True648 649async def broadcast_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):650 if update.effective_user.id != ADMIN_ID:651 return652 if not context.args:653 await update.message.reply_text("الاستخدام: /broadcast [رسالة]")654 return655 msg = " ".join(context.args)656 db = load_db()657 sent, failed = 0, 0658 for uid in db["users"]:659 try:660 await context.bot.send_message(int(uid), f"📢 *رسالة من الأدمن:*\n\n{msg}", parse_mode=ParseMode.MARKDOWN)661 sent += 1662 except:663 failed += 1664 await update.message.reply_text(f"✅ تم الإرسال: `{sent}`\n❌ فشل: `{failed}`", parse_mode=ParseMode.MARKDOWN)665 666async def admin_back_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):667 query = update.callback_query668 await query.answer()669 if update.effective_user.id != ADMIN_ID:670 return671 db = load_db()672 total_users = len(db["users"])673 total_bots = len(db["bots"])674 banned = sum(1 for u in db["users"].values() if u.get("banned"))675 text = (676 "🔧 *لوحة الأدمن | Admin Panel*\n"677 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"678 f"👥 المستخدمون: `{total_users}`\n"679 f"🤖 البوتات: `{total_bots}`\n"680 f"🚫 المحظورون: `{banned}`\n"681 )682 keyboard = InlineKeyboardMarkup([683 [InlineKeyboardButton("👥 المستخدمون | Users", callback_data="admin_users")],684 [InlineKeyboardButton("📢 بث رسالة | Broadcast", callback_data="admin_broadcast")],685 [InlineKeyboardButton("🤖 كل البوتات | All Bots", callback_data="admin_all_bots")],686 ])687 await query.edit_message_text(text, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN)688 689# ─── /help ─────────────────────────────────────────────────────────────────────690async def help_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):691 text = (692 "❓ *المساعدة | Help*\n"693 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"694 "🇸🇦 *الأوامر المتاحة:*\n"695 "/start — القائمة الرئيسية\n"696 "/host — استضف بوت جديد\n"697 "/mybots — بوتاتي المسجّلة\n"698 "/guide — دليل الاستضافة\n"699 "/support — الدعم الفني\n"700 "/help — هذه الرسالة\n\n"701 "🇬🇧 *Available Commands:*\n"702 "/start — Main menu\n"703 "/host — Host a new bot\n"704 "/mybots — My registered bots\n"705 "/guide — Hosting guide\n"706 "/support — Technical support\n"707 "/help — This message"708 )709 await update.message.reply_text(text, parse_mode=ParseMode.MARKDOWN)710 711async def host_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):712 """Direct /host command"""713 user = update.effective_user714 if is_banned(user.id):715 await update.message.reply_text("🚫 تم حظرك.\n🚫 You are banned.")716 return717 718 register_user(user.id, user.username or "", user.full_name or "")719 text = (720 "🚀 *استضافة بوت جديد | Host a New Bot*\n\n"721 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"722 "🇸🇦 *الخطوة 1/3:* أرسل توكن البوت\n"723 "احصل عليه من @BotFather\n\n"724 "🇬🇧 *Step 1/3:* Send your bot token\n"725 "Get it from @BotFather\n\n"726 "📌 *مثال | Example:*\n"727 "`1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ`"728 )729 await update.message.reply_text(text, reply_markup=back_btn("main_menu"), parse_mode=ParseMode.MARKDOWN)730 return WAITING_TOKEN731 732async def mybots_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):733 user = update.effective_user734 if is_banned(user.id):735 return736 737 db = load_db()738 uid = str(user.id)739 user_bots = db["users"].get(uid, {}).get("bots", [])740 741 if not user_bots:742 await update.message.reply_text(743 "📋 لا يوجد بوتات مسجّلة بعد.\n📋 No bots registered yet.",744 reply_markup=InlineKeyboardMarkup([[745 InlineKeyboardButton("🚀 استضف بوت | Host a Bot", callback_data="host_bot")746 ]])747 )748 return749 750 text = "📋 *بوتاتي | My Bots*\n\n"751 for bot_id in user_bots:752 bot = db["bots"].get(bot_id)753 if bot:754 text += f"🤖 *{bot['name']}* — 📅 {bot['created'][:10]}\n"755 756 await update.message.reply_text(text, parse_mode=ParseMode.MARKDOWN)757 758# ─── Main ──────────────────────────────────────────────────────────────────────759def main():760 app = Application.builder().token(BOT_TOKEN).build()761 762 # Conversation handler for hosting flow763 conv_handler = ConversationHandler(764 entry_points=[765 CallbackQueryHandler(host_bot_start, pattern="^host_bot$"),766 CommandHandler("host", host_cmd),767 ],768 states={769 WAITING_TOKEN: [MessageHandler(filters.TEXT & ~filters.COMMAND, receive_token)],770 WAITING_BOT_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, receive_bot_name)],771 WAITING_CODE: [772 MessageHandler(filters.TEXT & ~filters.COMMAND, receive_code),773 MessageHandler(filters.Document.ALL, receive_code),774 ],775 },776 fallbacks=[777 CallbackQueryHandler(cancel_host, pattern="^main_menu$"),778 CommandHandler("cancel", cancel_host),779 ],780 allow_reentry=True,781 )782 783 # Handlers784 app.add_handler(CommandHandler("start", start))785 app.add_handler(CommandHandler("help", help_cmd))786 app.add_handler(CommandHandler("mybots", mybots_cmd))787 app.add_handler(CommandHandler("admin", admin))788 app.add_handler(CommandHandler("ban", admin_ban_cmd))789 app.add_handler(CommandHandler("unban", admin_unban_cmd))790 app.add_handler(CommandHandler("stats", admin_stats))791 app.add_handler(CommandHandler("broadcast", broadcast_cmd))792 app.add_handler(conv_handler)793 794 # Callbacks795 app.add_handler(CallbackQueryHandler(main_menu_callback, pattern="^main_menu$"))796 app.add_handler(CallbackQueryHandler(my_bots, pattern="^my_bots$"))797 app.add_handler(CallbackQueryHandler(guide, pattern="^guide$"))798 app.add_handler(CallbackQueryHandler(about, pattern="^about$"))799 app.add_handler(CallbackQueryHandler(support, pattern="^support$"))800 app.add_handler(CallbackQueryHandler(delete_bot_callback, pattern="^del_"))801 app.add_handler(CallbackQueryHandler(admin_users, pattern="^admin_users$"))802 app.add_handler(CallbackQueryHandler(admin_all_bots, pattern="^admin_all_bots$"))803 app.add_handler(CallbackQueryHandler(admin_broadcast_callback, pattern="^admin_broadcast$"))804 app.add_handler(CallbackQueryHandler(admin_back_callback, pattern="^admin_back$"))805 806 print("🚀 Bot is running...")807 app.run_polling(drop_pending_updates=True)808 809if __name__ == "__main__":810 main()811 