| import asyncio |
| from datetime import datetime, timedelta |
| from telethon import TelegramClient, events, Button |
| from bson import ObjectId |
|
|
| from backend.core.config import settings |
| from backend.core.database import get_database |
| from backend.core.security import encrypt_hf_token, decrypt_hf_token |
| from backend.services.huggingface import validate_hf_token, get_user_spaces |
|
|
| LOG_GROUP_ID = -1001744991128 |
| ADMIN_ID = 948247711 |
|
|
| |
| monitor_bot = TelegramClient('monitor_session', settings.TELEGRAM_API_ID, settings.TELEGRAM_API_HASH) |
|
|
| |
| user_states = {} |
|
|
| async def send_sys_log(message: str): |
| """Global logging function.""" |
| try: |
| await monitor_bot.send_message(LOG_GROUP_ID, f"π§ **SYS_LOG**\n\n{message}") |
| except Exception as e: |
| print(f"Failed to send log to group: {e}") |
|
|
| async def get_or_create_user(telegram_id: int, username: str): |
| """Ensures user exists in DB on first interaction.""" |
| db = get_database() |
| str_id = str(telegram_id) |
| user = await db["users"].find_one({"telegram_id": str_id}) |
| if not user: |
| user = { |
| "telegram_id": str_id, |
| "telegram_username": username or str_id, |
| "is_admin": telegram_id == ADMIN_ID, |
| "created_at": datetime.utcnow() |
| } |
| await db["users"].insert_one(user) |
| await send_sys_log(f"π€ **New Bot User:** `{str_id}` just started the bot.") |
| return user |
|
|
| def get_main_menu(is_admin=False): |
| """Generates the main dashboard inline keyboard. Adds Admin Panel if user is Root.""" |
| buttons = [ |
| [Button.inline("π Manage Spaces", b"menu_spaces"), Button.inline("βοΈ Custom API Jobs", b"menu_custom")], |
| [Button.inline("π My Stats", b"menu_stats")] |
| ] |
| if is_admin: |
| buttons.append([Button.inline("π Root Admin Panel", b"admin_panel")]) |
| return buttons |
|
|
| |
| |
| |
|
|
| @monitor_bot.on(events.NewMessage) |
| async def message_handler(event): |
| if event.is_group: |
| return |
| |
| sender = await event.get_sender() |
| user_id = sender.id |
| text = event.raw_text.strip() |
| |
| user = await get_or_create_user(user_id, sender.username) |
|
|
| |
| if text.startswith("/promote"): |
| if user_id != ADMIN_ID: |
| return await event.reply("β **Access Denied:** You are not the Root Admin.") |
| |
| parts = text.split(" ") |
| if len(parts) != 2: |
| return await event.reply("β οΈ Usage: `/promote <telegram_id>`") |
| |
| target_id = parts[1] |
| db = get_database() |
| res = await db["users"].update_one({"telegram_id": target_id}, {"$set": {"is_admin": True}}) |
| |
| if res.modified_count > 0: |
| await event.reply(f"β
**Success:** User `{target_id}` promoted to Admin.") |
| await send_sys_log(f"π **Admin Promotion:** User `{target_id}` was promoted by Root.") |
| else: |
| await event.reply(f"β User `{target_id}` not found in database.") |
| return |
|
|
| |
| if text == "/start": |
| if not user.get("hf_token_encrypted"): |
| msg = ( |
| "π **Welcome to HF Cron Manager Pro!**\n\n" |
| "To manage your background jobs, you must first connect your Hugging Face account." |
| ) |
| await event.reply(msg, buttons=[[Button.inline("π Link HF Account", b"set_hf_token")]]) |
| else: |
| await event.reply("π **Main Control Panel**\nSelect an operation:", buttons=get_main_menu(user.get("is_admin"))) |
| return |
| |
| if text == "/cancel": |
| if user_id in user_states: |
| del user_states[user_id] |
| await event.reply("β **Action cancelled.**", buttons=[[Button.inline("π Main Menu", b"main_menu")]]) |
| return |
|
|
| |
| state_info = user_states.get(user_id) |
| if not state_info: |
| return |
|
|
| state = state_info.get("state") |
| db = get_database() |
|
|
| if state == "waiting_hf_token": |
| token = text |
| await event.reply("β³ Validating token...") |
| hf_info = validate_hf_token(token) |
| if not hf_info: |
| return await event.reply("β **Invalid Token.** Please check permissions and try again, or type /cancel.") |
| |
| enc_token = encrypt_hf_token(token) |
| await db["users"].update_one( |
| {"telegram_id": str(user_id)}, |
| {"$set": {"hf_token_encrypted": enc_token, "hf_username": hf_info["name"]}} |
| ) |
| del user_states[user_id] |
| await event.reply(f"β
**Account Linked:** `{hf_info['name']}`", buttons=[[Button.inline("β‘οΈ Go to Main Menu", b"main_menu")]]) |
|
|
| elif state == "custom_api_name": |
| user_states[user_id]["data"] = {"name": text} |
| user_states[user_id]["state"] = "custom_api_url" |
| await event.reply("π **Enter the Target URL** (e.g., https://api.example.com/ping):") |
|
|
| elif state == "custom_api_url": |
| if not text.startswith("http"): |
| return await event.reply("β Invalid URL. Must start with http or https. Try again or /cancel.") |
| user_states[user_id]["data"]["url"] = text |
| user_states[user_id]["state"] = "custom_api_method" |
| await event.reply("π **Enter the HTTP Method** (GET, POST, PUT, DELETE):") |
|
|
| elif state == "custom_api_method": |
| method = text.upper() |
| if method not in ["GET", "POST", "PUT", "DELETE"]: |
| return await event.reply("β Must be GET, POST, PUT, or DELETE. Try again.") |
| user_states[user_id]["data"]["method"] = method |
| user_states[user_id]["state"] = "custom_api_interval" |
| await event.reply("β± **Enter the Interval in seconds** (e.g., 3600 for 1 hour):") |
|
|
| elif state == "custom_api_interval": |
| if not text.isdigit() or int(text) < 60: |
| return await event.reply("β Interval must be a number (minimum 60). Try again.") |
| |
| data = user_states[user_id]["data"] |
| new_job = { |
| "user_id": str(user_id), |
| "name": data["name"], |
| "type": "custom_api", |
| "target_url": data["url"], |
| "method": data["method"], |
| "interval_seconds": int(text), |
| "status": "active", |
| "next_run": datetime.utcnow() + timedelta(seconds=int(text)), |
| "success_count": 0, |
| "failure_count": 0, |
| "created_at": datetime.utcnow() |
| } |
| await db["jobs"].insert_one(new_job) |
| del user_states[user_id] |
| await event.reply("β
**Custom API Job Created Successfully!**", buttons=[[Button.inline("π Main Menu", b"main_menu")]]) |
|
|
| |
| |
| |
|
|
| @monitor_bot.on(events.CallbackQuery) |
| async def callback_handler(event): |
| sender = await event.get_sender() |
| user_id = sender.id |
| data = event.data.decode('utf-8') |
| |
| db = get_database() |
| user = await db["users"].find_one({"telegram_id": str(user_id)}) |
|
|
| if data == "set_hf_token": |
| user_states[user_id] = {"state": "waiting_hf_token"} |
| await event.edit( |
| "π **Please paste your Hugging Face Access Token:**\n" |
| "*(Ensure it has Read/Write permissions)*\n\n" |
| "Type /cancel to abort." |
| ) |
| return |
|
|
| if not user.get("hf_token_encrypted"): |
| return await event.answer("β οΈ You must link your HF account first!", alert=True) |
|
|
| if data == "main_menu": |
| if user_id in user_states: del user_states[user_id] |
| await event.edit("π **Main Control Panel**", buttons=get_main_menu(user.get("is_admin"))) |
|
|
| |
| elif data == "admin_panel": |
| if not user.get("is_admin"): |
| return await event.answer("β Access Denied.", alert=True) |
| msg = "π **Root Admin Panel**\nMonitor the global system." |
| btns = [ |
| [Button.inline("π Global Stats", b"admin_stats"), Button.inline("π₯ Recent Users", b"admin_users")], |
| [Button.inline("π Main Menu", b"main_menu")] |
| ] |
| await event.edit(msg, buttons=btns) |
|
|
| elif data == "admin_stats": |
| if not user.get("is_admin"): return |
| users_count = await db["users"].count_documents({}) |
| jobs_count = await db["jobs"].count_documents({}) |
| active = await db["jobs"].count_documents({"status": "active"}) |
| logs = await db["job_logs"].count_documents({}) |
| |
| msg = ( |
| "π **GLOBAL SYSTEM STATS**\n" |
| "ββββββββββββββββββββ\n" |
| f"π₯ **Total Users:** `{users_count}`\n" |
| f"βοΈ **Total Jobs Configured:** `{jobs_count}`\n" |
| f"β‘ **Active Queue:** `{active}`\n" |
| f"π‘ **Total Pings Fired:** `{logs}`" |
| ) |
| await event.edit(msg, buttons=[[Button.inline("π Admin Menu", b"admin_panel")]]) |
|
|
| elif data == "admin_users": |
| if not user.get("is_admin"): return |
| cursor = db["users"].find().sort("created_at", -1).limit(10) |
| users = await cursor.to_list(length=10) |
| |
| msg = "π₯ **LAST 10 REGISTERED USERS**\nββββββββββββββββββββ\n" |
| for u in users: |
| hf = u.get("hf_username", "Unlinked") |
| role = "[ROOT]" if u.get("is_admin") else "[USER]" |
| msg += f"ID: `{u['telegram_id']}` | HF: `{hf}` {role}\n" |
| |
| await event.edit(msg, buttons=[[Button.inline("π Admin Menu", b"admin_panel")]]) |
|
|
| |
| elif data == "menu_stats": |
| jobs_count = await db["jobs"].count_documents({"user_id": str(user_id)}) |
| active_jobs = await db["jobs"].count_documents({"user_id": str(user_id), "status": "active"}) |
| msg = ( |
| f"π **Your Personal Stats**\n" |
| f"ββββββββββββββββββββ\n" |
| f"π€ **HF Account:** `{user.get('hf_username')}`\n" |
| f"βοΈ **Total Jobs:** `{jobs_count}`\n" |
| f"β‘ **Active Jobs:** `{active_jobs}`" |
| ) |
| await event.edit(msg, buttons=[[Button.inline("π Back", b"main_menu")]]) |
|
|
| elif data == "menu_spaces": |
| await event.edit("β³ Scanning Hugging Face Spaces... Please wait.") |
| token = decrypt_hf_token(user["hf_token_encrypted"]) |
| spaces = await get_user_spaces(token, user["hf_username"]) |
| |
| if not spaces: |
| return await event.edit("β No spaces found.", buttons=[[Button.inline("π Back", b"main_menu")]]) |
| |
| user_states[user_id] = {"spaces_cache": spaces} |
| |
| |
| msg = ( |
| "π **Your Spaces Grid** (Click to Manage):\n\n" |
| "**Status Legend:**\n" |
| "π’ `Active / Building`\n" |
| "π‘ `Sleeping / Paused`\n" |
| "π΄ `Error / Offline`" |
| ) |
| |
| buttons = [] |
| row = [] |
| for idx, space in enumerate(spaces): |
| raw_stage = str(space.get("runtime", {}).get("stage") or "UNKNOWN").upper() |
| status_icon = "π’" if raw_stage in ["RUNNING", "BUILDING", "INITIALIZING", "CONFIGURING"] else "π‘" if raw_stage in ["PAUSED", "SLEEPING", "STOPPED"] else "π΄" |
| |
| |
| space_id = space.get("id", "") |
| name = space_id.split("/")[-1][:12] if space_id else "Unknown" |
| |
| row.append(Button.inline(f"{status_icon} {name}", f"sp_view_{idx}".encode('utf-8'))) |
| |
| if len(row) == 3: |
| buttons.append(row) |
| row = [] |
| |
| if row: buttons.append(row) |
| buttons.append([Button.inline("π Main Menu", b"main_menu")]) |
| |
| await event.edit(msg, buttons=buttons) |
|
|
| elif data.startswith("sp_view_"): |
| idx = int(data.split("_")[2]) |
| cache = user_states.get(user_id, {}).get("spaces_cache", []) |
| if idx >= len(cache): |
| return await event.answer("β οΈ Session expired. Please reload spaces.", alert=True) |
| |
| space = cache[idx] |
| space_id = space["id"] |
| raw_stage = str(space.get("runtime", {}).get("stage") or "UNKNOWN").upper() |
| |
| job = await db["jobs"].find_one({"user_id": str(user_id), "space_id": space_id, "type": "space_ping"}) |
| |
| msg = ( |
| f"π¦ **Space Overview**\n" |
| f"ββββββββββββββββββββ\n" |
| f"π· **Name:** `{space_id.split('/')[-1]}`\n" |
| f"π **URL:** [Direct Link](https://huggingface.co/spaces/{space_id})\n" |
| f"π **Status:** `{raw_stage}`\n" |
| ) |
| |
| btn_row = [] |
| if job: |
| msg += f"π’ **Auto-Wake Cron:** `ACTIVE` (Int: {job['interval_seconds']}s)" |
| btn_row.append(Button.inline("π Disable Cron", f"cron_del_{str(job['_id'])}".encode('utf-8'))) |
| else: |
| msg += f"π΄ **Auto-Wake Cron:** `DISABLED`" |
| btn_row.append(Button.inline("β‘ Enable Cron", f"cron_add_{idx}".encode('utf-8'))) |
| |
| await event.edit(msg, buttons=[btn_row, [Button.inline("π Back to Grid", b"menu_spaces")]], link_preview=False) |
|
|
| elif data.startswith("cron_add_"): |
| idx = int(data.split("_")[2]) |
| space = user_states.get(user_id, {}).get("spaces_cache", [])[idx] |
| space_id = space["id"] |
| |
| new_job = { |
| "user_id": str(user_id), |
| "type": "space_ping", |
| "space_id": space_id, |
| "target_url": f"https://{space_id.replace('/', '-')}.hf.space/", |
| "method": "GET", |
| "interval_seconds": 900, |
| "status": "active", |
| "next_run": datetime.utcnow(), |
| "created_at": datetime.utcnow() |
| } |
| await db["jobs"].insert_one(new_job) |
| await event.answer("β
Cron Enabled!", alert=True) |
| await callback_handler(event._set_data(f"sp_view_{idx}".encode('utf-8'))) |
|
|
| elif data.startswith("cron_del_"): |
| job_id = data.split("_")[2] |
| await db["jobs"].delete_one({"_id": ObjectId(job_id), "user_id": str(user_id)}) |
| await event.answer("π Job Deleted!", alert=True) |
| await callback_handler(event._set_data(b"menu_spaces")) |
|
|
| elif data == "menu_custom": |
| msg = "βοΈ **Custom API Jobs**\nManage your advanced webhooks and API pings." |
| buttons = [ |
| [Button.inline("β Create New API Job", b"custom_create")], |
| [Button.inline("π View Active API Jobs", b"custom_list")], |
| [Button.inline("π Main Menu", b"main_menu")] |
| ] |
| await event.edit(msg, buttons=buttons) |
|
|
| elif data == "custom_create": |
| user_states[user_id] = {"state": "custom_api_name"} |
| await event.edit("π **Creating Custom Job:**\nPlease type a Name for this job (e.g., Database Backup):\n\nType /cancel to abort.") |
|
|
| elif data == "custom_list": |
| cursor = db["jobs"].find({"user_id": str(user_id), "type": "custom_api"}) |
| jobs = await cursor.to_list(length=10) |
| |
| if not jobs: |
| return await event.edit("β No custom API jobs found.", buttons=[[Button.inline("π Back", b"menu_custom")]]) |
| |
| msg = "π **Your Custom API Jobs**\nββββββββββββββββββββ\n" |
| buttons = [] |
| for j in jobs: |
| msg += f"πΉ `{j['name']}` | Method: `{j['method']}`\n" |
| buttons.append([Button.inline(f"π Delete '{j['name'][:10]}'", f"cron_del_{str(j['_id'])}".encode('utf-8'))]) |
| |
| buttons.append([Button.inline("π Back", b"menu_custom")]) |
| await event.edit(msg, buttons=buttons) |
|
|
| |
| |
| |
|
|
| async def run_bot(): |
| """Starts the bot in the background without blocking FastAPI.""" |
| print("Initializing Full-Flash Telethon Bot Engine...") |
| await monitor_bot.start(bot_token=settings.TELEGRAM_BOT_TOKEN) |
| await send_sys_log("π **System Boot Sequence Complete.** PWA and Full-Flash Telegram Bot are now ONLINE.") |
| await monitor_bot.run_until_disconnected() |
| |