149 lines
5.8 KiB
Python
149 lines
5.8 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import Any
|
|
import os
|
|
import shutil
|
|
from datetime import datetime
|
|
|
|
from dotenv import dotenv_values, load_dotenv, set_key
|
|
|
|
from parsers import parser_sources
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
ENV_PATH = PROJECT_ROOT / ".env"
|
|
|
|
|
|
def _field(key: str, label: str, value: str = "", *, field_type: str = "text", options: list[dict] | None = None, help_text: str = "", wide: bool = False) -> dict[str, Any]:
|
|
return {
|
|
"key": key,
|
|
"label": label,
|
|
"value": value or "",
|
|
"type": field_type,
|
|
"options": options or [],
|
|
"help": help_text,
|
|
"wide": wide,
|
|
}
|
|
|
|
|
|
def _source_field_key(source_key: str, field: str) -> str:
|
|
return f"{source_key}_{field}"
|
|
|
|
|
|
def get_env_file_path() -> Path:
|
|
return ENV_PATH
|
|
|
|
|
|
def _dotenv_values() -> dict[str, str]:
|
|
if not ENV_PATH.exists():
|
|
return {}
|
|
raw = dotenv_values(ENV_PATH)
|
|
return {key: str(value or "") for key, value in raw.items() if key}
|
|
|
|
|
|
def build_env_settings_context() -> dict[str, Any]:
|
|
"""Данные для формы редактирования безопасных ключей .env."""
|
|
env_values = _dotenv_values()
|
|
sources = parser_sources.list_parser_sources()
|
|
source_options = [
|
|
{"value": source["key"], "label": source.get("title") or source["key"]}
|
|
for source in sources
|
|
]
|
|
|
|
groups: list[dict[str, Any]] = [
|
|
{
|
|
"title": "Общие настройки источников",
|
|
"subtitle": "Эти значения влияют на выбор активного турнира по умолчанию и базовый сайт RFS.",
|
|
"fields": [
|
|
_field(
|
|
"DATA_EVENT_CODE",
|
|
"Активный источник по умолчанию",
|
|
parser_sources.get_default_source_key(),
|
|
field_type="select",
|
|
options=source_options,
|
|
help_text="Используется, если парсер запускается без выбора источника.",
|
|
),
|
|
_field(
|
|
"RFS_BASE_URL",
|
|
"Базовый URL RFS/WFL",
|
|
parser_sources.RFS_BASE_URL,
|
|
help_text="Обычно https://wfl.rfs.ru",
|
|
wide=True,
|
|
),
|
|
],
|
|
}
|
|
]
|
|
|
|
for source in sources:
|
|
source_key = source["key"]
|
|
title = source.get("title") or source_key
|
|
groups.append(
|
|
{
|
|
"title": title,
|
|
"subtitle": f"Ключ источника: {source_key}",
|
|
"fields": [
|
|
_field(_source_field_key(source_key, "EVENT_NAME"), "Название в интерфейсе", source.get("title", "")),
|
|
_field(_source_field_key(source_key, "SEASON"), "Сезон", source.get("season", "")),
|
|
_field(_source_field_key(source_key, "TOURNAMENT_ID"), "Tournament ID", source.get("tournament_id", "")),
|
|
_field(_source_field_key(source_key, "ROUND_ID"), "Round ID", source.get("round_id", "")),
|
|
_field(
|
|
_source_field_key(source_key, "CALENDAR_TYPE"),
|
|
"Тип календаря",
|
|
source.get("calendar_type", "tours"),
|
|
field_type="select",
|
|
options=[
|
|
{"value": "tours", "label": "tours — туры"},
|
|
{"value": "stages", "label": "stages — стадии"},
|
|
],
|
|
),
|
|
_field(_source_field_key(source_key, "LOGO_BASE_PATH"), "Папка логотипов", source.get("logo_base_path", ""), wide=True),
|
|
_field(_source_field_key(source_key, "TEAMS_URL"), "Ссылка на команды", source.get("teams_url", ""), wide=True),
|
|
_field(_source_field_key(source_key, "SCHEDULE_URL"), "Ссылка на расписание", source.get("schedule_url", ""), wide=True),
|
|
_field(_source_field_key(source_key, "STANDINGS_URL"), "Ссылка на турнирку", source.get("standings_url", ""), wide=True),
|
|
_field(_source_field_key(source_key, "MATCH_BASE_URL"), "Базовая ссылка матча", source.get("match_base_url", ""), wide=True),
|
|
],
|
|
}
|
|
)
|
|
|
|
editable_keys = [field["key"] for group in groups for field in group["fields"]]
|
|
|
|
return {
|
|
"env_path": str(ENV_PATH),
|
|
"groups": groups,
|
|
"editable_keys": editable_keys,
|
|
"raw_values": env_values,
|
|
}
|
|
|
|
|
|
def get_editable_env_keys() -> set[str]:
|
|
context = build_env_settings_context()
|
|
return set(context["editable_keys"])
|
|
|
|
|
|
def save_env_settings(form_values: dict[str, str]) -> list[str]:
|
|
"""Сохраняет только разрешённые ключи в .env и обновляет os.environ."""
|
|
editable_keys = get_editable_env_keys()
|
|
updates: list[str] = []
|
|
|
|
ENV_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
if not ENV_PATH.exists():
|
|
ENV_PATH.write_text("", encoding="utf-8")
|
|
|
|
backup_path = ENV_PATH.with_suffix(".env.bak")
|
|
try:
|
|
shutil.copy2(ENV_PATH, backup_path)
|
|
except Exception:
|
|
# Бэкап полезен, но не должен ломать сохранение настроек.
|
|
pass
|
|
|
|
for key in sorted(editable_keys):
|
|
if key not in form_values:
|
|
continue
|
|
value = str(form_values.get(key) or "").strip()
|
|
set_key(str(ENV_PATH), key, value, quote_mode="always")
|
|
os.environ[key] = value
|
|
updates.append(key)
|
|
|
|
load_dotenv(ENV_PATH, override=True)
|
|
return updates
|