Ребрендинг БАЗА (фундамент): конфиг + профиль воронки в БД
Фаза 1 — config: BRAND «Кибершкола БАЗА», цены/тексты по ТЗ (приветствие, прайс, интенсив), 8 ссылок-плейсхолдеров с UTM, триггеры (основные/лето). Фаза 2 — database: JSON-профиль воронки (роль/возраст/игра/уровень/формат/ метки/…) + методы get/set/clear + add_metka. Живой флоу пока не затронут. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -88,6 +88,63 @@ 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")
|
||||
|
||||
# ============================================================
|
||||
# КИБЕРШКОЛА БАЗА — бренд, цены, ссылки, триггеры (по ТЗ)
|
||||
# Всё редактируемое собрано здесь, чтобы менять без правки логики.
|
||||
# ============================================================
|
||||
BRAND = "Кибершкола БАЗА"
|
||||
|
||||
# --- Ссылки на оплату/запись (ПЛЕЙСХОЛДЕРЫ — заменить на реальные) ---
|
||||
# UTM добавляются автоматически там, где ссылка ведёт наружу.
|
||||
UTM_MAIN = "utm_source=vk&utm_medium=bot&utm_campaign=main_bot"
|
||||
UTM_SUMMER = "utm_source=vk&utm_medium=bot&utm_campaign=summer_intensive"
|
||||
LINKS = {
|
||||
"trial": os.getenv("LINK_TRIAL", "https://infocyber.pro/"), # запись на пробное
|
||||
"tariffs": os.getenv("LINK_TARIFFS", "https://infocyber.pro/"), # страница с тарифами
|
||||
"group_4": os.getenv("LINK_GROUP_4", "https://infocyber.pro/"), # групповой абонемент 4
|
||||
"group_8": os.getenv("LINK_GROUP_8", "https://infocyber.pro/"), # групповой абонемент 8
|
||||
"individual_1": os.getenv("LINK_IND_1", "https://infocyber.pro/"), # индивидуальная 1
|
||||
"individual_4": os.getenv("LINK_IND_4", "https://infocyber.pro/"), # индивидуальные 4
|
||||
"individual_8": os.getenv("LINK_IND_8", "https://infocyber.pro/"), # индивидуальные 8
|
||||
"summer": os.getenv("LINK_SUMMER", "https://infocyber.pro/"), # оплата летнего интенсива
|
||||
}
|
||||
|
||||
# --- Триггеры запуска (регистронезависимо) ---
|
||||
MAIN_TRIGGERS = ["начать", "тренировки", "занятия", "цена", "стоимость", "записаться",
|
||||
"привет", "здравствуйте", "старт", "меню"]
|
||||
SUMMER_TRIGGERS = ["лето", "интенсив", "летний интенсив", "интенсив cs2", "хочу на интенсив"]
|
||||
|
||||
# --- Тексты (по ТЗ, редактируемые) ---
|
||||
GREETING_BAZA = (
|
||||
"Привет! Это Кибершкола БАЗА 🎮\n\n"
|
||||
"Мы проводим онлайн-тренировки по CS2, Dota 2 и World of Tanks для подростков 12+.\n"
|
||||
"Помогу подобрать подходящий формат, посмотреть цены или записаться на тренировку."
|
||||
)
|
||||
|
||||
PRICES_TEXT = (
|
||||
"Стоимость тренировок в Кибершколе БАЗА:\n\n"
|
||||
"🧑🤝🧑 Групповые тренировки:\n"
|
||||
"• 4 занятия — 2 790 ₽\n"
|
||||
"• 8 занятий — 4 990 ₽\n\n"
|
||||
"👤 Индивидуальные тренировки:\n"
|
||||
"• 1 занятие — 870 ₽\n"
|
||||
"• 4 занятия — 3 290 ₽\n"
|
||||
"• 8 занятий — 5 990 ₽\n\n"
|
||||
"Все занятия проходят онлайн с тренером."
|
||||
)
|
||||
|
||||
INTENSIVE_PRICE = "1 990 ₽"
|
||||
INTENSIVE_INFO = (
|
||||
"Привет! Вы написали кодовое слово «лето» — рассказываю про летний интенсив по CS2 🔥\n\n"
|
||||
"Это 4 онлайн-тренировки по 90 минут с тренером.\n"
|
||||
"На интенсиве участники будут:\n"
|
||||
"— разбирать роли и командную игру;\n"
|
||||
"— тренировать аим, дуэли и контрстрейфы;\n"
|
||||
"— разбирать игровые моменты и демозаписи;\n"
|
||||
"— изучать гранаты, мувмент и полезные игровые приёмы.\n\n"
|
||||
f"Стоимость участия — {INTENSIVE_PRICE} за все 4 тренировки."
|
||||
)
|
||||
|
||||
# Standard replies and patterns
|
||||
FAQ_ANSWERS = {
|
||||
"цены": (
|
||||
|
||||
+48
-1
@@ -30,7 +30,7 @@ class DatabaseManager:
|
||||
""")
|
||||
|
||||
# Migration checks for existing databases
|
||||
for col in ["consent_1", "consent_2", "consent_3", "call_time", "vac_data"]:
|
||||
for col in ["consent_1", "consent_2", "consent_3", "call_time", "vac_data", "profile"]:
|
||||
try:
|
||||
cursor.execute(f"ALTER TABLE user_states ADD COLUMN {col} TEXT")
|
||||
except sqlite3.OperationalError:
|
||||
@@ -475,6 +475,53 @@ class DatabaseManager:
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
# --- Профиль воронки БАЗА (JSON в user_states.profile) ---
|
||||
def get_profile(self, user_id: int) -> Dict[str, Any]:
|
||||
"""Профиль пользователя из воронки (роль/возраст/игра/уровень/формат/метки/…)."""
|
||||
with self._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT profile FROM user_states WHERE user_id = ?", (user_id,))
|
||||
row = cursor.fetchone()
|
||||
if row and row[0]:
|
||||
try:
|
||||
return json.loads(row[0])
|
||||
except (ValueError, TypeError):
|
||||
return {}
|
||||
return {}
|
||||
|
||||
def set_profile_field(self, user_id: int, key: str, value: Any):
|
||||
"""Обновить одно поле профиля (не спрашиваем повторно то, что уже есть)."""
|
||||
data = self.get_profile(user_id)
|
||||
data[key] = value
|
||||
with self._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"INSERT INTO user_states (user_id, profile) VALUES (?, ?) "
|
||||
"ON CONFLICT(user_id) DO UPDATE SET profile = excluded.profile, last_updated = CURRENT_TIMESTAMP",
|
||||
(user_id, json.dumps(data, ensure_ascii=False))
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
def add_metka(self, user_id: int, metka: str):
|
||||
"""Добавить метку пользователю (хранится списком в профиле, без повторов)."""
|
||||
data = self.get_profile(user_id)
|
||||
metki = data.get("metki", [])
|
||||
if metka not in metki:
|
||||
metki.append(metka)
|
||||
data["metki"] = metki
|
||||
self.set_profile_field(user_id, "metki", metki)
|
||||
|
||||
def clear_profile(self, user_id: int):
|
||||
"""Полностью очистить профиль воронки."""
|
||||
with self._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"INSERT INTO user_states (user_id, profile) VALUES (?, NULL) "
|
||||
"ON CONFLICT(user_id) DO UPDATE SET profile = NULL, last_updated = CURRENT_TIMESTAMP",
|
||||
(user_id,)
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
# --- Вакансии (направления игроков / должности сотрудников) ---
|
||||
def get_vacancy_options(self, track: str) -> list:
|
||||
"""Активные опции для трека ('player'|'worker') как список (id, label)."""
|
||||
|
||||
Reference in New Issue
Block a user