162 lines
6.2 KiB
Python
162 lines
6.2 KiB
Python
import json
|
|
import os
|
|
from typing import Any, Iterator
|
|
|
|
from telebot.types import CallbackQuery, InlineQuery, Message
|
|
|
|
from models import logger
|
|
|
|
from .schedule import (
|
|
Schedule,
|
|
ScheduleAPIError,
|
|
ScheduleTarget,
|
|
get_schedule,
|
|
group_target,
|
|
normalize_target,
|
|
target_key,
|
|
)
|
|
|
|
|
|
class User:
|
|
def __init__(self, userID: int) -> None:
|
|
self.id = userID
|
|
try:
|
|
with open(f"./users/{self.id}.json", "r", encoding="utf-8") as file:
|
|
self.data: dict[str, Any] = json.load(file)
|
|
except FileNotFoundError:
|
|
self.data = {}
|
|
except (json.JSONDecodeError, OSError):
|
|
logger.error("Bot", f'INVALID "{userID}" SAVED DATA! RESET!')
|
|
self.data = {}
|
|
|
|
self.state: str | bool | None = self.data.get("state")
|
|
legacy_group = self.data.get("group")
|
|
self.active_target = normalize_target(self.data.get("active_schedule"))
|
|
if self.active_target is None and isinstance(legacy_group, str) and legacy_group:
|
|
self.active_target = group_target(legacy_group)
|
|
|
|
saved = [normalize_target(value) for value in self.data.get("saved_schedules", [])]
|
|
self.saved_schedules: list[ScheduleTarget] = [value for value in saved if value]
|
|
for name in self.data.get("saved_groups", []):
|
|
if isinstance(name, str) and name:
|
|
self._append_saved(group_target(name))
|
|
if self.active_target:
|
|
self._append_saved(self.active_target)
|
|
|
|
self.view_target = normalize_target(self.data.get("view_schedule"))
|
|
self.search_kind = self.data.get("search_kind")
|
|
results = [normalize_target(value) for value in self.data.get("search_results", [])]
|
|
self.search_results: list[ScheduleTarget] = [value for value in results if value]
|
|
|
|
self.notifications: list[str] = self.data.get("notifications", [])
|
|
self.valid = bool(self.data.get("valid", True))
|
|
self.user: dict[str, Any] = self.data.get("user", {})
|
|
self.usage: dict[str, Any] = self.data.get(
|
|
"usage", {"count": -1, "date": None, "time": None}
|
|
)
|
|
self.flags: list[str] = self.data.get("flags", [])
|
|
|
|
if self.data.get("notifyEvening") and "evening" not in self.notifications:
|
|
self.notifications.append("evening")
|
|
if self.data.get("notifyBeforeLesson") and "lesson" not in self.notifications:
|
|
self.notifications.append("lesson")
|
|
self.save()
|
|
|
|
@property
|
|
def group(self) -> str | None:
|
|
return self.active_target["name"] if self.active_target else None
|
|
|
|
@group.setter
|
|
def group(self, name: str | None) -> None:
|
|
self.active_target = group_target(name) if name else None
|
|
|
|
@property
|
|
def saved_groups(self) -> list[str]:
|
|
return [target["name"] for target in self.saved_schedules if target["kind"] == "group"]
|
|
|
|
@saved_groups.setter
|
|
def saved_groups(self, names: list[str]) -> None:
|
|
non_groups = [target for target in self.saved_schedules if target["kind"] != "group"]
|
|
self.saved_schedules = non_groups + [group_target(name) for name in names if name]
|
|
|
|
def _append_saved(self, target: ScheduleTarget) -> None:
|
|
if not any(target_key(value) == target_key(target) for value in self.saved_schedules):
|
|
self.saved_schedules.append(target)
|
|
|
|
def is_saved(self, target: ScheduleTarget | None) -> bool:
|
|
return bool(
|
|
target
|
|
and any(target_key(value) == target_key(target) for value in self.saved_schedules)
|
|
)
|
|
|
|
def save_schedule(self, target: ScheduleTarget, make_active: bool = True) -> None:
|
|
self._append_saved(target)
|
|
if make_active:
|
|
self.active_target = target
|
|
self.save()
|
|
|
|
def remove_schedule(self, target: ScheduleTarget) -> None:
|
|
key = target_key(target)
|
|
self.saved_schedules = [value for value in self.saved_schedules if target_key(value) != key]
|
|
if self.active_target and target_key(self.active_target) == key:
|
|
self.active_target = self.saved_schedules[-1] if self.saved_schedules else None
|
|
self.save()
|
|
|
|
def keep_only_active(self) -> None:
|
|
self.saved_schedules = [self.active_target] if self.active_target else []
|
|
self.save()
|
|
|
|
def find_saved(self, name: str) -> ScheduleTarget | None:
|
|
return next((target for target in self.saved_schedules if target["name"] == name), None)
|
|
|
|
def schedule(self, target: ScheduleTarget | None = None) -> Schedule | None:
|
|
selected = target or self.active_target
|
|
if not selected:
|
|
return None
|
|
try:
|
|
return get_schedule(selected)
|
|
except (ValueError, ScheduleAPIError) as error:
|
|
logger.error("Schedule", f"[{self.id}] {error}")
|
|
return None
|
|
|
|
def setState(self, newState: str) -> None:
|
|
self.state = newState
|
|
self.save()
|
|
|
|
def save(self) -> None:
|
|
with open(f"./users/{self.id}.json", "w", encoding="utf-8") as file:
|
|
json.dump(
|
|
{
|
|
"state": self.state,
|
|
"group": self.group,
|
|
"active_schedule": self.active_target,
|
|
"saved_groups": self.saved_groups,
|
|
"saved_schedules": self.saved_schedules,
|
|
"view_schedule": self.view_target,
|
|
"search_kind": self.search_kind,
|
|
"search_results": self.search_results,
|
|
"notifications": self.notifications,
|
|
"valid": self.valid,
|
|
"user": self.user,
|
|
"usage": self.usage,
|
|
"flags": self.flags,
|
|
},
|
|
file,
|
|
ensure_ascii=False,
|
|
indent=4,
|
|
)
|
|
|
|
|
|
def validate(ctx: Message | InlineQuery | CallbackQuery) -> User:
|
|
try:
|
|
return User(ctx.from_user.id) # type: ignore
|
|
except Exception as error:
|
|
logger.error("Bot", f'INVALID "{ctx.from_user.id}" VALIDATION! {error}')
|
|
return False # type: ignore
|
|
|
|
|
|
def getAllUsers() -> Iterator[User]:
|
|
for _, _, filenames in os.walk("./users"):
|
|
for userFile in filenames:
|
|
if userFile.endswith(".json"):
|
|
yield User(int(userFile.removesuffix(".json")))
|