From 7e030d105916dbc8d2a80c3296d72e951b88beea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D1=81=D0=B8=D0=BD=D0=B5=D1=87=D0=BA=D0=B0=20=E2=99=A1?= <63897347+ktnk-dev@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:04:59 +0000 Subject: [PATCH] log schedule search requests --- .gitignore | 1 + bot/main/register_user.py | 9 ++++++++ bot/schedule/search.py | 8 ++++++- models/schedule_request_log.py | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 models/schedule_request_log.py diff --git a/.gitignore b/.gitignore index 6129f42..44945fe 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ schedule_client.py config.py .env .venv +/schedule_requests.json* diff --git a/bot/main/register_user.py b/bot/main/register_user.py index b9cac5f..8a2fdc0 100644 --- a/bot/main/register_user.py +++ b/bot/main/register_user.py @@ -13,6 +13,7 @@ from models.schedule import ( group_target, search_targets, ) +from models.schedule_request_log import append_schedule_request from models.user import getAllUsers, validate from utils import convert @@ -33,6 +34,10 @@ def start(message: Message): if not search_target_kind: return send(message, "Не удалось определить тип расписания по ссылке.") search_query = convert.decode(query[3:]) + try: + append_schedule_request(search_query) + except (OSError, ValueError) as error: + logger.error("Schedule", f"[{user.id}] Failed to save request: {error}") try: results = search_targets(search_target_kind, search_query, limit=10) except ScheduleAPIError as error: @@ -123,6 +128,10 @@ def _finish_registration(message: Message, group_name: str) -> None: ) def selectGroupState(message: Message): query = (message.text or "").strip() + try: + append_schedule_request(query) + except (OSError, ValueError) as error: + logger.error("Schedule", f"[{message.from_user.id}] Failed to save request: {error}") try: matches = find_main_groups(query) if len(matches) == 1 and group_exists(query): diff --git a/bot/schedule/search.py b/bot/schedule/search.py index 0ab56cd..ae791f5 100644 --- a/bot/schedule/search.py +++ b/bot/schedule/search.py @@ -9,6 +9,7 @@ from models.schedule import ( generateWeekSchedule, search_targets, ) +from models.schedule_request_log import append_schedule_request from models.user import User, validate @@ -108,8 +109,13 @@ def search_query(message: Message): return open_schedule_viewer(message, selected) kind = str(user.state).partition(":")[2] + query = message.text or "" try: - results = search_targets(kind, message.text or "", limit=10) # type: ignore + append_schedule_request(query) + except (OSError, ValueError) as error: + logger.error("Schedule", f"[{user.id}] Failed to save request: {error}") + try: + results = search_targets(kind, query, limit=10) # type: ignore except ScheduleAPIError as error: logger.error("Schedule", f"[{user.id}] {error}") return send(message, "Сервер расписания сейчас недоступен. Попробуй ещё раз позже.") diff --git a/models/schedule_request_log.py b/models/schedule_request_log.py new file mode 100644 index 0000000..30dc19f --- /dev/null +++ b/models/schedule_request_log.py @@ -0,0 +1,41 @@ +import datetime +import json +import os +import threading +from pathlib import Path +from zoneinfo import ZoneInfo + + +_MOSCOW = ZoneInfo("Europe/Moscow") +_LOG_PATH = Path("schedule_requests.json") +_LOCK = threading.RLock() + + +def append_schedule_request(request: str) -> None: + """Append a user-entered schedule search to the persistent JSON history.""" + value = request.strip() + if not value: + return + + with _LOCK: + try: + with _LOG_PATH.open("r", encoding="utf-8") as file: + history = json.load(file) + except FileNotFoundError: + history = [] + + if not isinstance(history, list): + raise ValueError(f"{_LOG_PATH} must contain a JSON list") + + history.append( + { + "time": datetime.datetime.now(_MOSCOW).isoformat(timespec="seconds"), + "request": value, + } + ) + + temporary_path = _LOG_PATH.with_suffix(".json.tmp") + with temporary_path.open("w", encoding="utf-8") as file: + json.dump(history, file, ensure_ascii=False, indent=2) + file.write("\n") + os.replace(temporary_path, _LOG_PATH)