import asyncio import logging import time import os from bot.telegram_api import send_message, edit_message from bot.onboarding import ( handle_start, handle_token_command, handle_reset, handle_help, handle_stats, ) from bot.streaming import stream_reply from db import models as dbm log = logging.getLogger("webhook") _last_msg = {} RATE_SECONDS = 2.0 ADMIN_TELEGRAM_IDS = { int(x.strip()) for x in os.environ.get("ADMIN_TELEGRAM_IDS", "").split(",") if x.strip().isdigit() } async def handle_update(update: dict): msg = update.get("message") or update.get("edited_message") if not msg: return chat = msg.get("chat", {}) chat_id = chat.get("id") from_user = msg.get("from", {}) user_id = from_user.get("id") username = from_user.get("username") first_name = from_user.get("first_name") if chat_id is None or user_id is None: return text = (msg.get("text") or "").strip() if not text: await send_message(chat_id, "⚠️ Only text messages are supported.") return dbm.upsert_user(user_id, username, first_name) if text.startswith("/start"): await handle_start(chat_id, user_id, username) return if text.startswith("/token"): parts = text.split(maxsplit=1) arg = parts[1].strip() if len(parts) > 1 else "" await handle_token_command(chat_id, user_id, arg) return if text.startswith("/reset"): await handle_reset(chat_id, user_id) return if text.startswith("/help"): await handle_help(chat_id) return if text.startswith("/stats"): await handle_stats(chat_id, user_id) return if text.startswith("/admin"): if user_id in ADMIN_TELEGRAM_IDS: await send_message( chat_id, "**Admin panel:** open the Space URL and switch to the 🔐 Admin Panel tab.", ) else: await send_message(chat_id, "⛔ You are not an admin.") return now = time.time() last = _last_msg.get(user_id, 0) if now - last < RATE_SECONDS: await send_message(chat_id, "⏳ Slow down a moment.") return _last_msg[user_id] = now if not dbm.user_has_valid_token(user_id): await send_message( chat_id, "🔒 You need a valid access token.\n" "Send `/token YOUR_TOKEN_HERE` to activate.", ) return try: daily_limit = int(dbm.get_setting("daily_turn_limit", "100")) except Exception: daily_limit = 100 user = dbm.get_user(user_id) if user and user.get("total_turns", 0) >= daily_limit: await send_message( chat_id, "⚠️ Daily message limit reached. Try again tomorrow.", ) return # ---- Persist user turn ---- dbm.add_message(user_id, "user", text) dbm.archive_append(user_id, "user", text) try: await stream_reply(chat_id, user_id, text) except Exception: log.exception("stream_reply crashed") try: await send_message(chat_id, "⚠️ Something went wrong generating a reply.") except Exception: pass