DispelEvilBot/admin/forms.py

99 lines
3.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Проверка и разбор форм админки (чистые функции — без HTTP и БД)."""
from __future__ import annotations
from typing import Any
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
WEEKDAY_NAMES: dict[int, str] = {
1: "Пн",
2: "Вт",
3: "Ср",
4: "Чт",
5: "Пт",
6: "Сб",
7: "Вс",
}
MAX_DESCRIPTION_LENGTH = 200
def format_weekdays(days: list[int] | tuple[int, ...] | None) -> str:
"""Человеческое описание дней ISO: ``1,3,5`` -> ``Пн, Ср, Пт``."""
if not days:
return "каждый день"
return ", ".join(WEEKDAY_NAMES[day] for day in sorted(set(days)) if day in WEEKDAY_NAMES)
def parse_schedule_fields(
*,
template_key: str,
hour: str,
minute: str,
weekdays: list[str],
timezone: str,
description: str,
enabled: bool,
) -> tuple[dict[str, Any] | None, list[str]]:
"""Собрать данные расписания из полей формы.
Возвращает ``(data, errors)``: при ошибках ``data is None`` и заполнен ``errors``.
"""
errors: list[str] = []
try:
hour_value = int(hour)
except (TypeError, ValueError):
hour_value = -1
errors.append("Час должен быть числом")
try:
minute_value = int(minute)
except (TypeError, ValueError):
minute_value = -1
errors.append("Минуты должны быть числом")
if not 0 <= hour_value <= 23 and "Час должен быть числом" not in errors:
errors.append("Час должен быть от 0 до 23")
if not 0 <= minute_value <= 59 and "Минуты должны быть числом" not in errors:
errors.append("Минуты должны быть от 0 до 59")
days: list[int] = []
for raw in weekdays:
try:
day = int(raw)
except (TypeError, ValueError):
errors.append(f"Некорректный день недели: {raw}")
continue
if 1 <= day <= 7:
days.append(day)
else:
errors.append("День недели должен быть от 1 (Пн) до 7 (Вс)")
tz_name = (timezone or "").strip() or "Europe/Moscow"
try:
ZoneInfo(tz_name)
except (ZoneInfoNotFoundError, ValueError):
errors.append(f"Неизвестная таймзона: {tz_name}")
if not template_key.strip():
errors.append("Выберите шаблон сообщения")
if len(description) > MAX_DESCRIPTION_LENGTH:
errors.append(f"Описание длиннее {MAX_DESCRIPTION_LENGTH} символов")
if errors:
return None, errors
return (
{
"template_key": template_key,
"hour": hour_value,
"minute": minute_value,
"weekdays": sorted(set(days)),
"timezone": tz_name,
"enabled": enabled,
"description": description.strip(),
},
[],
)