Нормализовать переводы строк в LF

Решение по TD-STYLE-ANALYZERS: LF — инструменты проекта (Python/Node) пишут LF,
CRLF-.sh не работают на Linux CI (sh scripts/ci.sh), большинство файлов уже были
LF. Добавлен .gitattributes (* text=auto eol=lf, бинарные исключения),
.editorconfig переведён на lf, 1029 файлов конвертированы, git add --renormalize.
Из индекса убраны закравшиеся archive/**/__pycache__/*.pyc.
This commit is contained in:
Rustam Khalimov
2026-09-11 19:01:42 +03:00
parent 39c9bdc1b7
commit 713d554dc2
751 changed files with 94507 additions and 94486 deletions
+99 -99
View File
@@ -1,99 +1,99 @@
"""Конфигурация из переменных окружения.
По ТЗ в env выносятся ТОЛЬКО неконфиденциальные параметры:
порты, пути к БД/данным/сессиям. Секреты (Telegram api_id/hash,
ключи AI, пароль дашборда) живут в базе и задаются через UI.
"""
from __future__ import annotations
import os
from pathlib import Path
def _bool(name: str, default: bool = False) -> bool:
raw = os.getenv(name)
if raw is None:
return default
return raw.strip().lower() in {"1", "true", "yes", "on"}
def _int(name: str, default: int) -> int:
try:
return int(os.getenv(name, str(default)))
except ValueError:
return default
# Корень данных (том в docker-compose). Внутри лежат leadradar.duckdb,
# telegram-сессии, файлы вложений (позже — MinIO), секрет подписи сессий.
DATA_DIR = Path(os.getenv("LEADRADAR_DATA", str(Path(__file__).resolve().parent.parent / "data"))).resolve()
DB_PATH = DATA_DIR / os.getenv("LEADRADAR_DB_NAME", "leadradar.duckdb")
SESSIONS_DIR = DATA_DIR / "telegram_sessions"
FILES_DIR = DATA_DIR / "attachments"
SECRET_FILE = DATA_DIR / "session_secret.key"
# Хост/порт HTTP-сервера
HOST = os.getenv("LEADRADAR_HOST", "0.0.0.0")
PORT = _int("LEADRADAR_PORT", 8000)
# Через env допустимо задать стартовый секрет (например, из секрет-менеджера),
# но если он не задан — будет создан случайный и сохранён в SECRET_FILE.
SESSION_SECRET = os.getenv("LEADRADAR_SESSION_SECRET", "") or None
# Учётные данные первого входа можно выставить и в env (удобно для развёртывания),
# НО по умолчанию система стартует с admin/admin и требует смены пароля.
BOOTSTRAP_LOGIN = os.getenv("LEADRADAR_BOOTSTRAP_LOGIN", "admin")
BOOTSTRAP_PASSWORD = os.getenv("LEADRADAR_BOOTSTRAP_PASSWORD", "admin")
# Шифрование секретов в БД. По договорённости ключ живёт в env;
# при локальной разработке без env создаётся файл data/encryption.key.
ENCRYPTION_KEY = os.getenv("LEADRADAR_ENCRYPTION_KEY", "") or None
ENCRYPTION_KEY_FILE = DATA_DIR / "encryption.key"
# MinIO (вложения; креды по договорённости — в env)
MINIO_ENDPOINT = os.getenv("LEADRADAR_MINIO_ENDPOINT", "")
MINIO_ACCESS_KEY = os.getenv("LEADRADAR_MINIO_ACCESS_KEY", "")
MINIO_SECRET_KEY = os.getenv("LEADRADAR_MINIO_SECRET_KEY", "")
MINIO_BUCKET = os.getenv("LEADRADAR_MINIO_BUCKET", "leadradar")
MINIO_SECURE = _bool("LEADRADAR_MINIO_SECURE", False)
# Автономный ML-сервис (отдельный контейнер). Если недоступен — модель не
# используется в пайплайне, а события обучения копятся в outbox до его возврата.
ML_URL = os.getenv("LEADRADAR_ML_URL", "http://127.0.0.1:8100").rstrip("/")
ML_TIMEOUT = _int("LEADRADAR_ML_TIMEOUT", 30) # обучение батчами — тяжёлое, таймаут щедрый
# Куки
COOKIE_NAME = "leadradar_session"
SESSION_DAYS = 30
# Telegram-сессия (Telethon)
SESSION_PREFIX = "user"
# Путь к статике фронтенда (собранный dist). Если папки нет — API работает
# отдельно (фронт поднимается dev-сервером), статика просто не раздаётся.
FRONTEND_DIST = Path(os.getenv("LEADRADAR_FRONTEND_DIST", str(Path(__file__).resolve().parent.parent.parent / "frontend" / "dist"))).resolve()
# Логи
LOG_LEVEL = os.getenv("LEADRADAR_LOG_LEVEL", "INFO")
# Демо-эндпоинты (simulate-lead, age-lead). В проде выключено;
# включается только для локальных тестов разработчика: LEADRADAR_DEMO=1
DEMO_ENABLED = _bool("LEADRADAR_DEMO", False)
def ensure_dirs() -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
SESSIONS_DIR.mkdir(parents=True, exist_ok=True)
FILES_DIR.mkdir(parents=True, exist_ok=True)
def get_or_create_secret() -> str:
if SESSION_SECRET:
return SESSION_SECRET
if SECRET_FILE.exists():
return SECRET_FILE.read_text(encoding="utf-8").strip()
import secrets
secret = secrets.token_hex(32)
SECRET_FILE.write_text(secret, encoding="utf-8")
return secret
"""Конфигурация из переменных окружения.
По ТЗ в env выносятся ТОЛЬКО неконфиденциальные параметры:
порты, пути к БД/данным/сессиям. Секреты (Telegram api_id/hash,
ключи AI, пароль дашборда) живут в базе и задаются через UI.
"""
from __future__ import annotations
import os
from pathlib import Path
def _bool(name: str, default: bool = False) -> bool:
raw = os.getenv(name)
if raw is None:
return default
return raw.strip().lower() in {"1", "true", "yes", "on"}
def _int(name: str, default: int) -> int:
try:
return int(os.getenv(name, str(default)))
except ValueError:
return default
# Корень данных (том в docker-compose). Внутри лежат leadradar.duckdb,
# telegram-сессии, файлы вложений (позже — MinIO), секрет подписи сессий.
DATA_DIR = Path(os.getenv("LEADRADAR_DATA", str(Path(__file__).resolve().parent.parent / "data"))).resolve()
DB_PATH = DATA_DIR / os.getenv("LEADRADAR_DB_NAME", "leadradar.duckdb")
SESSIONS_DIR = DATA_DIR / "telegram_sessions"
FILES_DIR = DATA_DIR / "attachments"
SECRET_FILE = DATA_DIR / "session_secret.key"
# Хост/порт HTTP-сервера
HOST = os.getenv("LEADRADAR_HOST", "0.0.0.0")
PORT = _int("LEADRADAR_PORT", 8000)
# Через env допустимо задать стартовый секрет (например, из секрет-менеджера),
# но если он не задан — будет создан случайный и сохранён в SECRET_FILE.
SESSION_SECRET = os.getenv("LEADRADAR_SESSION_SECRET", "") or None
# Учётные данные первого входа можно выставить и в env (удобно для развёртывания),
# НО по умолчанию система стартует с admin/admin и требует смены пароля.
BOOTSTRAP_LOGIN = os.getenv("LEADRADAR_BOOTSTRAP_LOGIN", "admin")
BOOTSTRAP_PASSWORD = os.getenv("LEADRADAR_BOOTSTRAP_PASSWORD", "admin")
# Шифрование секретов в БД. По договорённости ключ живёт в env;
# при локальной разработке без env создаётся файл data/encryption.key.
ENCRYPTION_KEY = os.getenv("LEADRADAR_ENCRYPTION_KEY", "") or None
ENCRYPTION_KEY_FILE = DATA_DIR / "encryption.key"
# MinIO (вложения; креды по договорённости — в env)
MINIO_ENDPOINT = os.getenv("LEADRADAR_MINIO_ENDPOINT", "")
MINIO_ACCESS_KEY = os.getenv("LEADRADAR_MINIO_ACCESS_KEY", "")
MINIO_SECRET_KEY = os.getenv("LEADRADAR_MINIO_SECRET_KEY", "")
MINIO_BUCKET = os.getenv("LEADRADAR_MINIO_BUCKET", "leadradar")
MINIO_SECURE = _bool("LEADRADAR_MINIO_SECURE", False)
# Автономный ML-сервис (отдельный контейнер). Если недоступен — модель не
# используется в пайплайне, а события обучения копятся в outbox до его возврата.
ML_URL = os.getenv("LEADRADAR_ML_URL", "http://127.0.0.1:8100").rstrip("/")
ML_TIMEOUT = _int("LEADRADAR_ML_TIMEOUT", 30) # обучение батчами — тяжёлое, таймаут щедрый
# Куки
COOKIE_NAME = "leadradar_session"
SESSION_DAYS = 30
# Telegram-сессия (Telethon)
SESSION_PREFIX = "user"
# Путь к статике фронтенда (собранный dist). Если папки нет — API работает
# отдельно (фронт поднимается dev-сервером), статика просто не раздаётся.
FRONTEND_DIST = Path(os.getenv("LEADRADAR_FRONTEND_DIST", str(Path(__file__).resolve().parent.parent.parent / "frontend" / "dist"))).resolve()
# Логи
LOG_LEVEL = os.getenv("LEADRADAR_LOG_LEVEL", "INFO")
# Демо-эндпоинты (simulate-lead, age-lead). В проде выключено;
# включается только для локальных тестов разработчика: LEADRADAR_DEMO=1
DEMO_ENABLED = _bool("LEADRADAR_DEMO", False)
def ensure_dirs() -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
SESSIONS_DIR.mkdir(parents=True, exist_ok=True)
FILES_DIR.mkdir(parents=True, exist_ok=True)
def get_or_create_secret() -> str:
if SESSION_SECRET:
return SESSION_SECRET
if SECRET_FILE.exists():
return SECRET_FILE.read_text(encoding="utf-8").strip()
import secrets
secret = secrets.token_hex(32)
SECRET_FILE.write_text(secret, encoding="utf-8")
return secret