0ec849d80f
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
147 lines
8.5 KiB
Python
147 lines
8.5 KiB
Python
import os
|
||
|
||
# Load environment variables from .env in the project root
|
||
def _load_env():
|
||
# Find the project root (the directory containing config.py)
|
||
root_dir = os.path.dirname(os.path.abspath(__file__))
|
||
dotenv_path = os.path.join(root_dir, ".env")
|
||
if os.path.exists(dotenv_path):
|
||
try:
|
||
with open(dotenv_path, "r", encoding="utf-8") as f:
|
||
for line in f:
|
||
line = line.strip()
|
||
if not line or line.startswith("#"):
|
||
continue
|
||
if "=" in line:
|
||
key, val = line.split("=", 1)
|
||
val = val.strip().strip('"').strip("'")
|
||
# Не перетираем переменные, уже заданные в реальном окружении
|
||
# (на проде токены приходят из env, .env — лишь фолбэк).
|
||
os.environ.setdefault(key.strip(), val)
|
||
except Exception as e:
|
||
print(f"Warning: Failed to load .env file: {e}")
|
||
|
||
_load_env()
|
||
|
||
# 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)
|
||
|
||
# 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
|
||
|
||
# Parse ADMIN_IDS as a list of integers from comma-separated env values
|
||
admin_ids_raw = os.getenv("ADMIN_IDS")
|
||
if admin_ids_raw:
|
||
try:
|
||
ADMIN_IDS = [int(x.strip()) for x in admin_ids_raw.split(",") if x.strip().isdigit()]
|
||
except Exception:
|
||
ADMIN_IDS = [OPERATOR_PEER_ID]
|
||
else:
|
||
ADMIN_IDS = [OPERATOR_PEER_ID]
|
||
|
||
# ============================================================
|
||
# СУПЕР-АДМИН. Меняется ТОЛЬКО ЗДЕСЬ, в коде (не через .env, не через бота).
|
||
# Супер-админ может добавлять/удалять обычных администраторов прямо из бота.
|
||
# Чтобы сменить/добавить супер-админа — впишите сюда VK ID (числом):
|
||
SUPER_ADMIN_IDS = [350793273]
|
||
# ============================================================
|
||
|
||
# Ссылки на юридические документы (инлайн-кнопки в боте)
|
||
OFFER_URL = os.getenv("OFFER_URL", "https://infocyber.pro/form/Dogovor_oferty_kibersport_versia_izmenennaya.pdf")
|
||
POLICY_URL = os.getenv("POLICY_URL", "https://infocyber.pro/form/Политика%20ПД.pdf")
|
||
|
||
# Несколько операторов: уведомления о заявках/откликах/вызовах уходят ВСЕМ из списка.
|
||
# По умолчанию = один OPERATOR_PEER_ID. Задать через .env: OPERATOR_PEER_IDS=111,222,333
|
||
_op_ids_raw = os.getenv("OPERATOR_PEER_IDS")
|
||
if _op_ids_raw:
|
||
OPERATOR_PEER_IDS = [int(x.strip()) for x in _op_ids_raw.split(",") if x.strip().lstrip("-").isdigit()]
|
||
if not OPERATOR_PEER_IDS:
|
||
OPERATOR_PEER_IDS = [OPERATOR_PEER_ID]
|
||
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"))
|
||
|
||
# Разрешённый источник (Origin) для CORS веб-формы. '*' допустим только для локальной отладки.
|
||
ALLOWED_ORIGIN = os.getenv("ALLOWED_ORIGIN", "https://infocyber.pro")
|
||
|
||
# Промокоды на скидку. Пока ВЫКЛЮЧЕНЫ — включить можно, задав PROMO_ENABLED=true в .env.
|
||
# Когда выключено: бот и форма не показывают промокод, в уведомлениях/письмах его нет.
|
||
PROMO_ENABLED = os.getenv("PROMO_ENABLED", "false").strip().lower() in ("1", "true", "yes")
|
||
|
||
# Email (SMTP) configuration для уведомлений о заявках
|
||
SMTP_HOST = os.getenv("SMTP_HOST", "")
|
||
SMTP_PORT = int(os.getenv("SMTP_PORT", "465"))
|
||
SMTP_USER = os.getenv("SMTP_USER", "")
|
||
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")
|
||
MAIL_FROM = os.getenv("MAIL_FROM", "") or SMTP_USER
|
||
# Куда отправлять уведомления о новых заявках (можно несколько через запятую)
|
||
MAIL_TO = os.getenv("MAIL_TO", "group-zakaz@infocyber.pro")
|
||
# Куда отправлять отклики на вакансии / набор в состав.
|
||
# TODO: пока совпадает с MAIL_TO; возможно вынести на отдельный HR-адрес (напр. hr@infocyber.pro) — задать HR_MAIL_TO в .env.
|
||
HR_MAIL_TO = os.getenv("HR_MAIL_TO", "") or MAIL_TO
|
||
# True — порт 465 (SSL), False — STARTTLS (обычно порт 587)
|
||
SMTP_USE_SSL = os.getenv("SMTP_USE_SSL", "true").strip().lower() in ("1", "true", "yes")
|
||
|
||
# Standard replies and patterns
|
||
FAQ_ANSWERS = {
|
||
"цены": (
|
||
"💰 Тарифы ИКП на тренировки (направления: CS2, Dota 2, World of Tanks):\n\n"
|
||
"• Разовая тренировка — 870 ₽\n"
|
||
"• Абонемент на 4 занятия (групповой) — 2 790 ₽\n"
|
||
"• Абонемент на 8 занятий (групповой) — 4 990 ₽\n"
|
||
"• Абонемент на 4 занятия (индивидуальный) — 3 290 ₽\n"
|
||
"• Абонемент на 8 занятий (индивидуальный) — 5 990 ₽\n\n"
|
||
"Оставьте заявку через меню — менеджер подберёт оптимальный формат и направление!"
|
||
),
|
||
"контакты": (
|
||
"📞 Связаться с ИКП:\n"
|
||
"• Email (поддержка): support@infocyber.pro\n"
|
||
"• Заявки: group-zakaz@infocyber.pro\n"
|
||
"• Telegram: @ikp_team\n"
|
||
"• Сайт: https://infocyber.pro/"
|
||
),
|
||
"услуги": (
|
||
"⚙️ ИКП — тренировки по киберспортивным дисциплинам:\n\n"
|
||
"1. Counter-Strike 2 — aim, раскидки гранат, командная тактика\n"
|
||
"2. Dota 2 — разбор реплеев, позиционка, фарм и тимплей\n"
|
||
"3. World of Tanks — позиционирование, сведение, тактика боёв\n\n"
|
||
"Форматы: разовые занятия, групповые и индивидуальные абонементы (4 и 8 занятий)."
|
||
),
|
||
"о компании": (
|
||
"🏢 ИКП — Игра. Киберспорт. Профессионалы.\n\n"
|
||
"Мощная экосистема для взрывного роста игроков: лучшие тренеры и глубокая data-аналитика. "
|
||
"Организация основана 1 сентября 2025 года.\n\n"
|
||
"Мы на площадках:\n"
|
||
"• ВКонтакте: https://vk.com/ikpro\n"
|
||
"• VK Live (трансляции): https://live.vkvideo.ru/ikp\n"
|
||
"• Telegram: https://t.me/ikp_team\n"
|
||
"• Discord: https://discord.gg/z92mAw7KEe"
|
||
)
|
||
}
|
||
|
||
# Доступные услуги (направления) для выбора в форме заявки
|
||
SERVICES = {
|
||
"1": {
|
||
"name": "Counter-Strike 2 🔫",
|
||
"price": "от 870 ₽ / занятие",
|
||
"description": "Тренировки по CS2: aim, раскидки гранат, командная тактика. Разовое занятие 870 ₽, абонементы от 2 790 ₽."
|
||
},
|
||
"2": {
|
||
"name": "Dota 2 🎮",
|
||
"price": "от 870 ₽ / занятие",
|
||
"description": "Тренировки по Dota 2: разбор реплеев, позиционка, фарм и тимплей. Разовое занятие 870 ₽, абонементы от 2 790 ₽."
|
||
},
|
||
"3": {
|
||
"name": "World of Tanks 🛡️",
|
||
"price": "от 870 ₽ / занятие",
|
||
"description": "Тренировки по World of Tanks: позиционирование, сведение, тактика боёв. Разовое занятие 870 ₽, абонементы от 2 790 ₽."
|
||
}
|
||
}
|
||
|