File size: 3,255 Bytes
7564bb1
 
 
aa85742
7564bb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d4c7ab3
 
 
 
 
 
7564bb1
 
 
 
 
 
 
 
 
 
 
 
 
d4c7ab3
 
 
7564bb1
d4c7ab3
7564bb1
 
 
 
 
 
 
 
 
d4c7ab3
7564bb1
 
 
 
 
d4c7ab3
7564bb1
 
 
d4c7ab3
7564bb1
 
 
d4c7ab3
7564bb1
 
 
 
d4c7ab3
 
 
 
 
 
 
 
 
 
7564bb1
 
 
 
 
 
 
 
d4c7ab3
 
 
 
 
 
7564bb1
 
 
 
 
d4c7ab3
7564bb1
 
d4c7ab3
 
 
 
7564bb1
 
aa85742
7564bb1
aa85742
7564bb1
d4c7ab3
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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