import logging import json import os import asyncio from datetime import datetime import pytz from aiogram import Bot, Dispatcher, types, F from aiogram.filters import Command from aiogram.utils.keyboard import InlineKeyboardBuilder from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.client.session.aiohttp import AiohttpSession import aiohttp from fastapi import FastAPI, Request from contextlib import asynccontextmanager import uvicorn TOKEN = "8471671662:AAGOgJx0mb-z4CIGGmJY0J_C4SCL9l1mUoA" ADMIN_ID = 7253593181 # Sizning to'g'ri va aniq server manzilingiz SPACE_WEBHOOK_URL = "https://raxmatjon2013-minicraft-server-bot.hf.space/webhook" RADMIN_IP = "26.99.233.131" RADMIN_NETWORK_NAME = "raxmatjonMC" RADMIN_NETWORK_PASS = "123456789" bot = None dp = Dispatcher() logging.basicConfig(level=logging.INFO) class ServerState(StatesGroup): waiting_for_port = State() in_chat = State() waiting_for_broadcast = State() USERS_FILE = "registered_users.json" LANG_FILE = "user_languages.json" def load_data(filename, default_type=list): if os.path.exists(filename): with open(filename, "r") as f: try: return json.load(f) except: return default_type() return default_type() def save_data(filename, data): with open(filename, "w") as f: json.dump(data, f) registered_users = set(load_data(USERS_FILE, list)) user_languages = load_data(LANG_FILE, dict) server_status = {"uz": "🔴 O'CHIQ", "ru": "🔴 ВЫКЛЮЧЕН", "en": "🔴 OFFLINE"} is_server_on = False current_port = None active_chats = {} user_by_admin = {} def is_work_time(): tz = pytz.timezone('Asia/Tashkent') now = datetime.now(tz) return 11 <= now.hour < 20 TEXTS = { "welcome": {"uz": "🎮 **Minecraft Server Botiga Xush Kelibsiz!** 🎮", "ru": "🎮 **Добро пожаловать!** 🎮", "en": "🎮 **Welcome!** 🎮"}, "btn_add_port": {"uz": "➕ Port kiritish", "ru": "➕ Ввести порт", "en": "➕ Enter Port"}, "btn_status": {"uz": "📊 Server holati", "ru": "📊 Status", "en": "📊 Status"}, "btn_how_to": {"uz": "❓ Qanday ulanadi?", "ru": "❓ Инструкция", "en": "❓ Guide"}, "btn_rules": {"uz": "📜 Server qoidalari", "ru": "📜 Правила", "en": "📜 Rules"}, "btn_players": {"uz": "👥 O'yinchilar", "ru": "👥 Игроки", "en": "👥 Players"}, "btn_support": {"uz": "📞 Yordam xizmati", "ru": "📞 Поддержка", "en": "📞 Support"}, "btn_downloads": {"uz": "💾 Yuklamalar", "ru": "💾 Скачать", "en": "💾 Downloads"}, "btn_faq": {"uz": "💡 Savol-Javoblar", "ru": "💡 FAQ", "en": "💡 FAQ"}, "btn_back": {"uz": "⬅️ Orqaga", "ru": "⬅️ Назад", "en": "⬅️ Back"}, "btn_end_chat": {"uz": "🛑 Suhbatni tugatish", "ru": "🛑 Завершить чат", "en": "🛑 End Chat"}, "ask_port": {"uz": f"🌐 **Radmin IP:** `{RADMIN_IP}`\n\n📥 PORT kiriting:", "ru": "📥 Введите ПОРТ:", "en": "📥 Enter PORT:"}, "error_port": {"uz": "❌ Xato format!", "ru": "❌ Неверный формат!", "en": "❌ Invalid format!"}, "success": {"uz": f"📢 **🔔 Server ishga tushdi! 🔔**\n\n🔗 Adres:\n`{RADMIN_IP}:{{port}}`", "ru": f"📢 **🔔 Сервер запущен! 🔔**", "en": f"📢 **🔔 Server is live! 🔔**"}, "guide_text": {"uz": f"🎮 **Ulanish:**\n👤 Name: `{RADMIN_NETWORK_NAME}`\n🔑 Pass: `{RADMIN_NETWORK_PASS}`", "ru": "🎮 Инструкция...", "en": "🎮 Guide..."}, "rules_text": {"uz": "📜 **Qoidalar:**\n1. Griefing taqiqlanadi.", "ru": "📜 Правила...", "en": "📜 Rules..."}, "players_text": {"uz": "👥 **O'yinchilar:**\n• 👑 `raxmatjonMC`", "ru": "👥 Игроки...", "en": "👥 Players..."}, "downloads_text": {"uz": "💾 **Yuklamalar:**\n• [Radmin VPN](https://www.radmin-vpn.com/)", "ru": "💾 Скачать...", "en": "💾 Downloads..."}, "faq_text": {"uz": "💡 **FAQ:** Versiyalar bir xil bo'lsin.", "ru": "💡 FAQ...", "en": "💡 FAQ..."}, "support_connecting": {"uz": "⏳ Bog'lanyapsiz... Yozing.", "ru": "⏳ Связываю...", "en": "⏳ Connecting..."}, "support_closed": {"uz": "💤 Ish vaqti soat 11:00 dan 20:00 gacha.", "ru": "💤 Поддержка сейчас недоступна.", "en": "💤 Support is closed."}, "chat_ended": {"uz": "🛑 Suhbat yakunlandi. Baholang:", "ru": "🛑 Чат завершен.", "en": "🛑 Chat ended."} } def lang_keyboard(): builder = InlineKeyboardBuilder() builder.row(types.InlineKeyboardButton(text="🇺🇿 O'zbekcha", callback_data="lang_uz"), types.InlineKeyboardButton(text="🇷🇺 Русский", callback_data="lang_ru"), types.InlineKeyboardButton(text="🇺🇸 English", callback_data="lang_en")) return builder.as_markup() def main_menu_keyboard(lang): builder = InlineKeyboardBuilder() builder.row(types.InlineKeyboardButton(text=TEXTS["btn_add_port"][lang], callback_data="add_map"), types.InlineKeyboardButton(text=TEXTS["btn_status"][lang], callback_data="server_status")) builder.row(types.InlineKeyboardButton(text=TEXTS["btn_how_to"][lang], callback_data="how_to_get_port"), types.InlineKeyboardButton(text=TEXTS["btn_rules"][lang], callback_data="server_rules")) builder.row(types.InlineKeyboardButton(text=TEXTS["btn_players"][lang], callback_data="server_players"), types.InlineKeyboardButton(text=TEXTS["btn_downloads"][lang], callback_data="server_downloads")) builder.row(types.InlineKeyboardButton(text=TEXTS["btn_faq"][lang], callback_data="server_faq"), types.InlineKeyboardButton(text=TEXTS["btn_support"][lang], callback_data="connect_support")) return builder.as_markup() def rating_keyboard(): builder = InlineKeyboardBuilder() for i in range(1, 11): builder.add(types.InlineKeyboardButton(text=str(i), callback_data=f"rate_{i}")) builder.adjust(5) return builder.as_markup() def end_chat_keyboard(lang): builder = InlineKeyboardBuilder() builder.row(types.InlineKeyboardButton(text=TEXTS["btn_end_chat"][lang], callback_data="user_end_chat")) return builder.as_markup() def back_keyboard(lang): builder = InlineKeyboardBuilder() builder.row(types.InlineKeyboardButton(text=TEXTS["btn_back"][lang], callback_data="back_to_menu")) return builder.as_markup() @dp.message(Command("admin")) async def admin_panel(message: types.Message): if message.from_user.id == ADMIN_ID: builder = InlineKeyboardBuilder() builder.row(types.InlineKeyboardButton(text="📢 E'lon yuborish", callback_data="admin_broadcast")) await message.answer(f"🛠 **Admin Panel**\nJami: {len(registered_users)}", reply_markup=builder.as_markup()) @dp.callback_query(F.data == "admin_broadcast") async def start_broadcast(callback: types.CallbackQuery, state: FSMContext): await callback.message.answer("📝 E'lon matnini kiriting:") await state.set_state(ServerState.waiting_for_broadcast) await callback.answer() @dp.message(ServerState.waiting_for_broadcast) async def do_broadcast(message: types.Message, state: FSMContext): text = message.text await state.clear() count = 0 for u_id in registered_users: try: await bot.send_message(u_id, f"📢 **E'lon!**\n\n{text}") count += 1 except: pass await message.answer(f"✅ Yetkazildi: {count}") @dp.message(Command("start")) async def start_cmd(message: types.Message): if message.from_user.id not in registered_users: registered_users.add(message.from_user.id) save_data(USERS_FILE, list(registered_users)) await message.answer("🌐 Tilni tanlang / Choose language:", reply_markup=lang_keyboard()) @dp.callback_query(F.data.startswith("lang_")) async def set_language(callback: types.CallbackQuery): lang = callback.data.split("_")[1] user_languages[str(callback.from_user.id)] = lang save_data(LANG_FILE, user_languages) await callback.message.edit_text(TEXTS["welcome"][lang], parse_mode="Markdown", reply_markup=main_menu_keyboard(lang)) await callback.answer() @dp.callback_query(F.data == "add_map") async def add_map_callback(callback: types.CallbackQuery, state: FSMContext): lang = user_languages.get(str(callback.from_user.id), "uz") await callback.message.edit_text(TEXTS["ask_port"][lang], parse_mode="Markdown", reply_markup=back_keyboard(lang)) await state.set_state(ServerState.waiting_for_port) @dp.callback_query(F.data in ["how_to_get_port", "server_rules", "server_players", "server_downloads", "server_faq"]) async def sections_callback(callback: types.CallbackQuery): lang = user_languages.get(str(callback.from_user.id), "uz") mapped_keys = {"how_to_get_port": "guide_text", "server_rules": "rules_text", "server_players": "players_text", "server_downloads": "downloads_text", "server_faq": "faq_text"} await callback.message.edit_text(TEXTS[mapped_keys[callback.data]][lang], parse_mode="Markdown", reply_markup=back_keyboard(lang)) @dp.callback_query(F.data == "back_to_menu") async def back_to_menu(callback: types.CallbackQuery, state: FSMContext): await state.clear() lang = user_languages.get(str(callback.from_user.id), "uz") await callback.message.edit_text(TEXTS["welcome"][lang], parse_mode="Markdown", reply_markup=main_menu_keyboard(lang)) @dp.message(ServerState.waiting_for_port) async def process_port(message: types.Message, state: FSMContext): global is_server_on, current_port lang = user_languages.get(str(message.from_user.id), "uz") if not message.text.isdigit(): await message.answer(TEXTS["error_port"][lang]) return current_port = message.text.strip() is_server_on = True await state.clear() await message.answer(TEXTS["success"][lang].format(port=current_port), parse_mode="Markdown", reply_markup=main_menu_keyboard(lang)) @dp.callback_query(F.data == "server_status") async def check_status(callback: types.CallbackQuery): lang = user_languages.get(str(callback.from_user.id), "uz") text = f"📊 Status: {server_status[lang]}" if not is_server_on else f"📊 Status: 🟢 YONIQ\n🔗 Adres: `{RADMIN_IP}:{current_port}`" await callback.message.edit_text(text, parse_mode="Markdown", reply_markup=main_menu_keyboard(lang)) @dp.callback_query(F.data == "connect_support") async def connect_support(callback: types.CallbackQuery, state: FSMContext): lang = user_languages.get(str(callback.from_user.id), "uz") if not is_work_time(): await callback.message.edit_text(TEXTS["support_closed"][lang], parse_mode="Markdown", reply_markup=back_keyboard(lang)) await callback.answer() return user_id = callback.from_user.id await callback.message.edit_text(TEXTS["support_connecting"][lang], reply_markup=end_chat_keyboard(lang)) await state.set_state(ServerState.in_chat) await bot.send_message(ADMIN_ID, f"🔔 **Murojaat!**\n👤 {callback.from_user.full_name}\nID: `{user_id}`") user_by_admin[ADMIN_ID] = user_id active_chats[user_id] = ADMIN_ID await callback.answer() @dp.callback_query(F.data == "user_end_chat") async def user_end_chat(callback: types.CallbackQuery, state: FSMContext): lang = user_languages.get(str(callback.from_user.id), "uz") user_id = callback.from_user.id await state.clear() await callback.message.edit_text(TEXTS["chat_ended"][lang], reply_markup=rating_keyboard()) if user_id in active_chats: await bot.send_message(ADMIN_ID, "🛑 Suhbat yakunlandi.") active_chats.pop(user_id, None) user_by_admin.pop(ADMIN_ID, None) @dp.message(ServerState.in_chat, F.text) async def forward_to_admin(message: types.Message): await bot.send_message(ADMIN_ID, f"💬 **[O'yinchi {message.from_user.first_name}]:** {message.text}") @dp.message(F.chat.id == ADMIN_ID, F.text) async def forward_to_user(message: types.Message): user_id = user_by_admin.get(ADMIN_ID) if user_id: await bot.send_message(user_id, f"👨‍💼 **[Admin]:** {message.text}") @dp.callback_query(F.data.startswith("rate_")) async def process_rating(callback: types.CallbackQuery): score = callback.data.split("_")[1] lang = user_languages.get(str(callback.from_user.id), "uz") await callback.message.edit_text(f"⭐️ Rahmat! Bahongiz: {score}\n\n" + TEXTS["welcome"][lang], parse_mode="Markdown", reply_markup=main_menu_keyboard(lang)) await bot.send_message(ADMIN_ID, f"📊 **Baho:** {score}/10") await callback.answer() # Serverni o'chib qolishdan asraydigan fondagi vazifa async def keep_alive(): await asyncio.sleep(15) async with aiohttp.ClientSession() as session: while True: try: async with session.get("https://raxmatjon2013-minicraft-server-bot.hf.space/") as resp: logging.info(f"Uyg'otish muvaffaqiyatli: {resp.status}") except: pass await asyncio.sleep(180) # Har 3 daqiqada serverni turtib turadi @asynccontextmanager async def lifespan(app: FastAPI): global bot connector = aiohttp.TCPConnector(ssl=False) session = AiohttpSession() session._session = aiohttp.ClientSession(connector=connector) bot = Bot(token=TOKEN, session=session) asyncio.create_task(keep_alive()) yield await bot.session.close() app = FastAPI(lifespan=lifespan) @app.post("/webhook") async def webhook_endpoint(request: Request): update = types.Update(**await request.json()) await dp.feed_update(bot=bot, update=update) return {"status": "ok"} @app.get("/") async def root(): return {"status": "running", "message": "Minecraft Webhook Server Active"} if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=7860)