.env.example: понятная инструкция по активации + защита config от пустых значений

- .env.example переписан как пошаговый гид: разделы (подключение к сообществу,
  кому приходят заявки, почта, ссылки, /favi-stop), пометки «ОБЯЗАТЕЛЬНО»,
  правила заполнения (без инлайн-комментариев, числа не оставлять пустыми).
- config: безопасный разбор чисел (_int_env) — пустое/кривое VK_GROUP_ID/порт/часы
  больше не роняют бот при старте, откатываются на дефолт. '#' в значениях (URL
  #prices) не трогаем.

pytest 43 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenik
2026-07-26 11:11:38 +03:00
parent d2ca750a2d
commit 9ded7a513d
2 changed files with 89 additions and 33 deletions
+18 -6
View File
@@ -23,14 +23,26 @@ def _load_env():
_load_env()
def _int_env(key: str, default) -> int:
"""Безопасно читает целое из .env: пустое/кривое значение → default (без краха)."""
raw = os.getenv(key, None)
if raw is None or str(raw).strip() == "":
return int(default)
try:
return int(str(raw).strip())
except (ValueError, TypeError):
return int(default)
# VK API Configuration
# In production, these should be loaded from environment variables or a secure .env file.
VK_TOKEN = os.getenv("VK_TOKEN", "your_vk_community_token_here")
GROUP_ID = int(os.getenv("VK_GROUP_ID", "0")) # Community ID (must be integer)
VK_TOKEN = os.getenv("VK_TOKEN", "your_vk_community_token_here") or "your_vk_community_token_here"
GROUP_ID = _int_env("VK_GROUP_ID", 0) # Community ID (must be integer)
# Operator / Admin configuration
# ID of the user or chat where notifications about new leads and operator requests will be sent
OPERATOR_PEER_ID = int(os.getenv("OPERATOR_PEER_ID", "12345678")) # Change to actual VK user ID of operator
OPERATOR_PEER_ID = _int_env("OPERATOR_PEER_ID", 12345678) # Change to actual VK user ID of operator
# Parse ADMIN_IDS as a list of integers from comma-separated env values
admin_ids_raw = os.getenv("ADMIN_IDS")
@@ -69,8 +81,8 @@ else:
OPERATOR_PEER_IDS = [OPERATOR_PEER_ID]
# Часы работы (для статуса оператора). Вне этого интервала — «ответим утром».
WORK_HOUR_START = int(os.getenv("WORK_HOUR_START", "9"))
WORK_HOUR_END = int(os.getenv("WORK_HOUR_END", "21"))
WORK_HOUR_START = _int_env("WORK_HOUR_START", 9)
WORK_HOUR_END = _int_env("WORK_HOUR_END", 21)
# Разрешённый источник (Origin) для CORS веб-формы. '*' допустим только для локальной отладки.
ALLOWED_ORIGIN = os.getenv("ALLOWED_ORIGIN", "https://infocyber.pro")
@@ -81,7 +93,7 @@ PROMO_ENABLED = os.getenv("PROMO_ENABLED", "false").strip().lower() in ("1", "tr
# Email (SMTP) configuration для уведомлений о заявках
SMTP_HOST = os.getenv("SMTP_HOST", "")
SMTP_PORT = int(os.getenv("SMTP_PORT", "465"))
SMTP_PORT = _int_env("SMTP_PORT", 465)
SMTP_USER = os.getenv("SMTP_USER", "")
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")
MAIL_FROM = os.getenv("MAIL_FROM", "") or SMTP_USER