Spaces:
Sleeping
Sleeping
| 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() | |
| 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()) | |
| 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() | |
| 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}") | |
| 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()) | |
| 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() | |
| 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) | |
| 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)) | |
| 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)) | |
| 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)) | |
| 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)) | |
| 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() | |
| 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) | |
| async def forward_to_admin(message: types.Message): | |
| await bot.send_message(ADMIN_ID, f"💬 **[O'yinchi {message.from_user.first_name}]:** {message.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}") | |
| 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 | |
| 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) | |
| async def webhook_endpoint(request: Request): | |
| update = types.Update(**await request.json()) | |
| await dp.feed_update(bot=bot, update=update) | |
| return {"status": "ok"} | |
| async def root(): | |
| return {"status": "running", "message": "Minecraft Webhook Server Active"} | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=7860) | |