Spaces:
Running
Running
SilverElixir commited on
Commit ·
fe3cf23
1
Parent(s): 3704a0f
stats: active chats counted over trailing 24h, total kept
Browse files- lumen_commands.py +7 -1
- tests/test_bot_commands.py +36 -0
lumen_commands.py
CHANGED
|
@@ -419,6 +419,12 @@ async def cmd_stats(message: Message) -> None:
|
|
| 419 |
bot._reset_quota_if_new_day()
|
| 420 |
|
| 421 |
total_chats = len(bot.chat_state)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
uptime_sec = int(time.monotonic() - bot._PROCESS_START_MONOTONIC)
|
| 423 |
uptime_str = f"{uptime_sec // 3600}ч {(uptime_sec % 3600) // 60}м"
|
| 424 |
|
|
@@ -459,7 +465,7 @@ async def cmd_stats(message: Message) -> None:
|
|
| 459 |
|
| 460 |
text = (
|
| 461 |
f"<b>Статистика Lumen</b>\n\n"
|
| 462 |
-
f"Активных чатов: {total_chats}\n"
|
| 463 |
f"Аптайм процесса: {uptime_str}\n"
|
| 464 |
f"Счётчики квоты за сутки: {quota_day} (America/Los_Angeles, сбрасываются автоматически)\n\n"
|
| 465 |
f"<b>Gemini — запросов по моделям:</b>\n{gemini_text}\n\n"
|
|
|
|
| 419 |
bot._reset_quota_if_new_day()
|
| 420 |
|
| 421 |
total_chats = len(bot.chat_state)
|
| 422 |
+
# "Активные" — с живой активностью за сутки, а не все записи в памяти (те копятся до пруна на 5000).
|
| 423 |
+
_active_cutoff = time.monotonic() - 24 * 3600
|
| 424 |
+
active_chats = sum(
|
| 425 |
+
1 for s in bot.chat_state.values()
|
| 426 |
+
if isinstance(s, dict) and s.get("last_activity", 0) >= _active_cutoff
|
| 427 |
+
)
|
| 428 |
uptime_sec = int(time.monotonic() - bot._PROCESS_START_MONOTONIC)
|
| 429 |
uptime_str = f"{uptime_sec // 3600}ч {(uptime_sec % 3600) // 60}м"
|
| 430 |
|
|
|
|
| 465 |
|
| 466 |
text = (
|
| 467 |
f"<b>Статистика Lumen</b>\n\n"
|
| 468 |
+
f"Активных чатов (24ч): {active_chats} (всего: {total_chats})\n"
|
| 469 |
f"Аптайм процесса: {uptime_str}\n"
|
| 470 |
f"Счётчики квоты за сутки: {quota_day} (America/Los_Angeles, сбрасываются автоматически)\n\n"
|
| 471 |
f"<b>Gemini — запросов по моделям:</b>\n{gemini_text}\n\n"
|
tests/test_bot_commands.py
CHANGED
|
@@ -56,6 +56,42 @@ def test_cmd_logs_flushes_the_listeners_real_handlers_not_root():
|
|
| 56 |
bot._LOG_LISTENER = original_listener
|
| 57 |
|
| 58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
def test_cmd_stats_hides_idle_models_and_shows_totals():
|
| 60 |
# Проф-вид /stats: нули по мёртвым моделям не мусорят, у каждого провайдера итог и остаток лимита.
|
| 61 |
chat_id = 999811
|
|
|
|
| 56 |
bot._LOG_LISTENER = original_listener
|
| 57 |
|
| 58 |
|
| 59 |
+
def test_cmd_stats_counts_only_recently_active_chats():
|
| 60 |
+
# "Активных" — с активностью за 24ч: молчащий год чат в счёт не идёт, но виден в "всего".
|
| 61 |
+
chat_id = 999812
|
| 62 |
+
incoming = _FakeIncomingMessage(chat_id)
|
| 63 |
+
incoming.from_user = SimpleNamespace(id=777002)
|
| 64 |
+
sent = {}
|
| 65 |
+
|
| 66 |
+
async def fake_tg_call(method, *args, **kwargs):
|
| 67 |
+
sent["text"] = args[0] if args else kwargs.get("text", "")
|
| 68 |
+
return SimpleNamespace()
|
| 69 |
+
|
| 70 |
+
original_owner = bot.OWNER_ID
|
| 71 |
+
original_tg_call = bot._tg_call
|
| 72 |
+
real_quota = dict(bot.GLOBAL_QUOTA)
|
| 73 |
+
real_states = dict(bot.chat_state)
|
| 74 |
+
now = time.monotonic()
|
| 75 |
+
bot.OWNER_ID = 777002
|
| 76 |
+
bot._tg_call = fake_tg_call
|
| 77 |
+
bot.GLOBAL_QUOTA.clear()
|
| 78 |
+
bot.GLOBAL_QUOTA.update({"quota_day": bot._current_quota_day()})
|
| 79 |
+
bot.chat_state.clear()
|
| 80 |
+
bot.chat_state.update({
|
| 81 |
+
111: {"history": [], "last_activity": now - 3600},
|
| 82 |
+
222: {"history": [], "last_activity": now - 25 * 3600},
|
| 83 |
+
})
|
| 84 |
+
try:
|
| 85 |
+
asyncio.run(bot.cmd_stats(incoming))
|
| 86 |
+
assert "Активных чатов (24ч): 1 (всего: 2)" in sent["text"]
|
| 87 |
+
finally:
|
| 88 |
+
bot.OWNER_ID = original_owner
|
| 89 |
+
bot._tg_call = original_tg_call
|
| 90 |
+
bot.GLOBAL_QUOTA.clear()
|
| 91 |
+
bot.GLOBAL_QUOTA.update(real_quota)
|
| 92 |
+
bot.chat_state.clear()
|
| 93 |
+
bot.chat_state.update(real_states)
|
| 94 |
+
# Проф-вид /stats: нули по мёртвым моделям не мусорят, у каждого провайдера итог и остаток лимита.
|
| 95 |
def test_cmd_stats_hides_idle_models_and_shows_totals():
|
| 96 |
# Проф-вид /stats: нули по мёртвым моделям не мусорят, у каждого провайдера итог и остаток лимита.
|
| 97 |
chat_id = 999811
|