Commit Graph

68 Commits

Author SHA1 Message Date
Kenik b766d445b4 Напоминалки: гейт часового пояса и для текстовой команды удаления
По ревью Task 4: команда 'напоминалка удалить <id>' была единственной точкой
входа в раздел, не защищённой гейтом _require_reminder_tz — админ без заданного
пояса мог через неё попасть в _send_reminders_admin и увидеть список с
подписью (UTC+0) по фолбэку, так и не указав реальный часовой пояс.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:49:17 +03:00
Kenik 3ff411b554 Напоминалки: гейт часового пояса, конвертация времени, состояние паузы
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:44:35 +03:00
Kenik 5ce69fb66c Напоминалки: кнопка паузы в клавиатуре раздела
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:42:10 +03:00
Kenik 79ec619360 Напоминалки: часовой пояс админов и пауза в database.py
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:39:54 +03:00
Kenik 40cfcbd45f Напоминалки: конвертация между часовыми поясами (reminders.py)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:37:26 +03:00
Kenik 5efc0aca8d Напоминалки: план реализации паузы и часового пояса (docs)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:35:13 +03:00
Kenik 4429b99a55 Напоминалки: спека паузы и часового пояса
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:29:01 +03:00
Kenik 19bade27b6 Напоминалки: нижняя клавиатура раздела вместо инлайн (не остаются старые кнопки)
Инлайн-клавиатура в _send_reminders_admin не заменяла нижнюю (reply) клавиатуру
предыдущего шага мастера — после создания напоминания кнопки «Разово / Каждую
неделю / …» оставались висеть внизу. Теперь раздел использует обычную нижнюю
клавиатуру get_reminders_admin_keyboard(), как и раздел «Быстрые ответы».

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:11:15 +03:00
Kenik fc79da8f83 Напоминалки: кнопка удаления списком и ФИО получателей вместо голых id
- В разделе «Напоминалки» добавлена кнопка «🗑 Удалить напоминание» с выбором
  из списка (как в разделе «Быстрые ответы»), не только текстовая команда.
- При выборе получателей и в списке напоминаний теперь показывается ФИО
  админа из VK рядом со ссылкой (если удалось получить), чтобы не кликать
  по каждой ссылке для опознания.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 14:08:49 +03:00
Kenik 6d4dd16caf Напоминалки: план реализации (docs) 2026-09-02 21:56:18 +03:00
Kenik 77f314be3f Напоминалки: сквозные тесты мастера создания и удаления 2026-09-02 21:53:31 +03:00
Kenik 5d88b8899e Напоминалки: фоновый планировщик отправки в срок
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 21:49:28 +03:00
Kenik 86f8115de1 Напоминалки: мастер создания, список и удаление в bot.py
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 21:44:23 +03:00
Kenik 0e162ac9a1 Напоминалки: кнопка в админ-панели и клавиатура выбора периода
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 21:40:30 +03:00
Kenik bf958e1c12 Напоминалки: таблица reminders и CRUD в database.py
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 21:37:26 +03:00
Kenik f5ce327bbf Напоминалки: чистая логика расчёта дат (reminders.py)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 21:33:56 +03:00
Kenik 4bf7f98540 Спека: настраиваемые напоминалки для админов 2026-09-02 21:23:47 +03:00
Kenik 577d342bdd Логотип: не долбить VK/лог при отказе загрузки фото (кэшируем неудачу)
В логах на каждое приветствие сыпалось [15] Access denied (у токена нет прав на
фото). Теперь неудача загрузки кэшируется — приветствие уходит без логотипа, без
повторных ошибок. (Чтобы логотип показывался — токену нужно право «Фотографии».)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 21:50:53 +03:00
Kenik f9cdaec75a Фикс: бот слал «не понял запрос» на беседы и пустые сообщения
Причина случайного фолбэка «Пока не получилось определить запрос»:
- бот реагировал на сообщения из бесед/групповых чатов (peer_id != from_id) и слал
  отправителю в ЛС фолбэк — теперь такие сообщения игнорируются (работаем только в личке);
- сообщения без текста (стикер/фото/голосовое/гифка) давали text="" → фолбэк в
  главном меню — теперь пустые сообщения игнорируются.

Тест: test_empty_message_ignored. pytest 44 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 21:45:23 +03:00
Kenik e509c0cfd1 Docker: Dockerfile + docker-compose.yml для запуска бота в контейнере
- Dockerfile (python:3.11-slim): установка зависимостей, запуск bot.py.
- docker-compose.yml: авто-перезапуск (restart: unless-stopped), настройки из .env
  (env_file), база в именованном volume (данные не теряются при пересборке).
- .dockerignore: в образ не тащим .git/тесты/докумен/базу/.env.
- bot.py: путь к БД через DB_PATH (для volume в Docker), по умолчанию — как раньше.
- requirements.txt: убраны неиспользуемые Pillow и openpyxl (образ легче).

pytest passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 22:32:15 +03:00
Kenik 8f3c3b8b83 .env как готовый шаблон в репозитории (ID вписаны, токен-заглушка)
Чтобы при передаче человеку не заполнять всё вручную: .env лежит в репозитории
с уже прописанными ID админов/оператора и рабочими ссылками. Заполнить нужно
только VK_TOKEN и VK_GROUP_ID (ключ и ID своего сообщества). Реальный токен —
только локально, в репозиторий не пушится.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 11:35:57 +03:00
Kenik 9ded7a513d .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>
2026-07-26 11:11:38 +03:00
Kenik d2ca750a2d Админка: показ/скрытие кнопок меню + экстренный стоп бота (/favi-stop)
1) Кнопки меню: раздел «Кнопки меню 🧩» в админке — показать/скрыть любую кнопку
   главного меню (Подобрать/Интенсив/Цены/Вопрос/Вебинар). Флаги в БД (bot_flags),
   дефолты в config.MENU_FEATURES (вебинар по умолчанию скрыт). Скрытый раздел не
   реагирует и на кодовые слова (интенсив выкл → «лето» игнорируется). Вебинар
   получил кнопку в меню (для теста ветки) + вход по callback из поста работает всегда.

2) Экстренное отключение (только супер-админ): /favi-stop → запрос пароля → бот
   уходит в аварийный режим и молчит для всех; /favi-start возвращает. Пароль хранится
   как PBKDF2-хэш в .env (FAVI_STOP_HASH), не в коде; сравнение константное, 3 попытки.

pytest 43 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 10:58:54 +03:00
Kenik 24daec1c09 Фикс: пустой ряд в клавиатуре ломал отправку («Задать вопрос» молчал) + vk.ru в резолвере
1) _kb при пустых рядах создавал ПУСТОЙ первый ряд (add_line до кнопок) — VK
   отклонял такую клавиатуру, из-за чего сообщения шага «Задать вопрос»,
   «другая игра», «нужен совет» не отправлялись (состояние при этом менялось).
   Теперь add_line ставится только между реальными кнопками — пустых рядов нет.
2) _resolve_vk_user_id теперь понимает домен vk.ru (и www./m.), а не только vk.com —
   ссылку https://vk.ru/screenname на добавление админа бот принимает.

Тесты: test_funnel_keyboards_no_empty_rows, test_resolve_vk_links. pytest 40 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 10:45:31 +03:00
Kenik 81c1162ca1 Админам: персональное отключение уведомлений от клиентов
В админ-панели кнопка «Уведомления: вкл 🔔 / выкл 🔕» — админ (в т.ч. из ADMIN_IDS/
супер-админ) может лично отключить приём уведомлений о заявках и сообщениях клиентов.
Флаг notify_muted хранится в профиле; _notify_operators пропускает замьюченных
получателей (у остальных операторов уведомления идут как обычно).

pytest 37 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 10:37:58 +03:00
Kenik f1c984ed69 Чистка репозитория: удалены неиспользуемые картинки + упрощён prewarm
Удалены изображения от удалённых фич (карусель услуг, карьера, веб-форма):
service_1/2/3/5/6/7.jpg, career_player/worker.jpg, bg.jpg. Остался только Logo.jpg
(приветствие). _prewarm_media упрощён — грузит только логотип.

pytest 36 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 10:31:51 +03:00
Kenik 348b944638 Дисциплина CS2 → «Counter-Strike 2» в текстах и кнопке выбора игры
Отображаемое название дисциплины расписано полностью: кнопка выбора игры,
приветствие, список направлений, вопрос об уровне, значение game, инфо интенсива,
описание услуги. Ввод «CS2» по-прежнему распознаётся (+ counter/strike).
Метка game_cs2 и UTM summer_intensive не тронуты (внутренние). Название продукта
«Летний интенсив CS2» оставлено как есть.

pytest 36 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 10:29:32 +03:00
Kenik 7caecb1c72 Тикеты заявок, «пробное занятие», доработка ветки вебинара
- Тикеты: add_lead возвращает id заявки; при передаче менеджеру клиент получает
  «🎫 Номер вашей заявки: №N», тот же номер — в карточке оператору и в письме.
  Один тикет на заход (сбрасывается при новом старте воронки/интенсива).
- Кнопка «Записаться на пробное» → «Записаться на пробное занятие» (лейблы + распознавание).
- Ветка вебинара: вход по callback-кнопке и по тексту «записаться на вебинар»,
  текст выровнен по ТЗ, после регистрации состояние FREE_CHAT — основное меню
  остаётся доступным (не блокирует продающую ветку). Дата/время — в config.

Тесты: test_baza_question_ticket, test_webinar_registration. pytest 36 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 10:04:19 +03:00
Kenik 7889a19744 Стата «Заявки» из воронки: запись лидов при конверсии
Воронка перестала писать в leads после ребрендинга — блок «Заявки» был всегда 0.
Теперь при конверсии (нажал оплату/пробное или передан менеджеру) бот фиксирует
заявку в leads (source=bot, имя из VK, услуга = тариф/формат/игра), один раз на заход
(флаг lead_recorded сбрасывается при новом старте воронки/интенсива). Разбивка «по
тарифу/формату» снова показывает реальные цифры.

Статистика почищена: убраны «из бота» (все заявки теперь из бота) и строка «согласны
на рассылку» (воронка не собирает это согласие) — не вводят в заблуждение.

Тест: test_baza_records_lead_once. pytest 34 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 20:27:21 +03:00
Kenik 72eeccdc3a Чистка хвостов веб-формы: убраны web_registrations и строка «с сайта» в стате
- database.py: удалены таблица web_registrations, методы add_web_registration и
  next_web_registration_id, поле from_web из get_lead_stats (форму убрали).
- bot.py: из статистики убрана строка «с сайта» (веб-заявки больше не пишутся).

pytest 33 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 20:23:36 +03:00
Kenik 196a488560 Удалена папка form/ — веб-форма вынесена из репозитория бота
Форма записи/оплаты живёт на сайте (infocyber.pro/form/), бот лишь ссылается на неё
кнопками. Локальные исходники формы в репозитории бота не нужны — репозиторий теперь
только про бота. Ссылки-URL и слой БД не тронуты (кнопки продолжают вести на сайт).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 20:20:12 +03:00
Kenik 12ce9c0807 Умный пропуск шагов воронки при уже сохранённых данных (§15)
- _baza_advance: воронка переходит к первому НЕзаполненному шагу, пропуская роль/
  возраст/игру/уровень, если они уже известны; формат (выбор действия) спрашивается всегда.
- На повторном входе — короткая подсказка, что известные ответы не переспрашиваются
  и их можно изменить кнопкой «Назад» (back-навигация остаётся линейной = override).
- Интенсив: известный возраст (из подбора) не переспрашивается — сразу уровень CS2.
- Данные из ветки «лето» сохраняются и переиспользуются в подборе, и наоборот.

Тесты: test_baza_smart_skip_known_fields, test_baza_intensive_skips_known_age. pytest 33 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 20:10:15 +03:00
Kenik 4095b2ec61 Чистка «лишнего»: остатки ИКП→БАЗА, мёртвый код, новый логотип
- Пользовательские сообщения и подписи с «ИКП» переименованы в «Кибершкола БАЗА»
  (права админа, стартовый пинг, отправитель писем, докстроки).
- Удалён мёртвый код: метод _notify_allowed + связанные _last_notify/NOTIFY_COOLDOWN_SEC
  (нигде не вызывались), осиротевшие комментарии-заголовки от удалённой карьеры,
  лишние пустые строки.
- Удалена скрытая фича «Наши соцсети» (нет в ТЗ, вела на старые ИКП-ссылки) + её клавиатура.
- Обновлён логотип приветствия (help_img/Logo.jpg).

Не тронуто намеренно: веб-форма (form/server.py) — отдельный компонент; слой БД.
pytest 31 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 20:04:55 +03:00
Kenik a5a96f31f5 Фикс: убран дубликат «Спасибо! Передаю запрос менеджеру» в ветке «Другая игра»
Полный прогон всех веток по ТЗ: тексты/кнопки/подтверждения на месте. Единственная
находка — двойное «Спасибо! Передаю запрос менеджеру» при выборе другой игры; второе
сообщение заменено на нейтральное уведомление о передаче менеджеру.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:48:24 +03:00
Kenik 261e5c2da0 Тексты воронки по ТЗ + смена ссылок из админки
Тексты:
- «Сколько лет игроку?» (было «…будущему ученику?») во всех местах;
- сообщение для «Младше 12 лет» приведено дословно к ТЗ (§4);
- убраны отсебятины-преамбулы, которых нет в ТЗ (приветствие, старт воронки,
  цены «Что дальше?», интенсив «Хотите записаться?»); кнопка младше-12 «Вернуться назад».

Смена ссылок в админке:
- таблица bot_links (key, url) + методы get_link/get_all_links/set_link;
- _link(key): БД-переопределение → дефолт из config/.env; используется на шагах оплаты;
- раздел «Ссылки 🔗» в админ-панели: список текущих адресов + «✏️ Изменить ссылку»
  (выбор из 8 кнопок → ввод URL с валидацией http/https). UTM добавляются автоматически.

Тесты: добавлен test_admin_edit_link. pytest 31 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:45:47 +03:00
Kenik fac2e3808b Фикс запуска: bot.py сам добавляет свою папку в sys.path
py -3.11 на машине резолвится в sandbox-сборку Python (ExamPython311), которая не
добавляет директорию скрипта в sys.path — из-за этого при запуске через start_bot.bat
падало «ModuleNotFoundError: No module named 'database'». Теперь bot.py в самом начале
вставляет свой каталог в sys.path, поэтому запускается любым Python и из любой папки.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:24:55 +03:00
Kenik 741a89f458 Ссылки БАЗА: реальные URL записи/оплаты + сохранение якоря в UTM
- Кнопки записи/оплаты ведут на форму сайта infocyber.pro (service_id web_1..web_5);
  тарифы — на главную с якорем #prices; пробное и интенсив — на общую форму записи
  (отдельной страницы интенсива на сайте пока нет).
- _utm(): UTM вставляется ДО якоря (?utm...#prices), иначе браузер не доскроллит
  до раздела. Значения ссылок вынесены в .env / задокументированы в .env.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:12:20 +03:00
Kenik 7a59b035ce Воронка БАЗА: приведение к ТЗ (метки, сохранённые данные, тексты, шаги)
Закрыты расхождения с ТЗ:
- Метки (§12) переименованы под спецификацию: role_player, game_dota2, format_help,
  interest_trial, interest_summer_intensive, manager_requested, source_main_menu,
  source_keyword_summer; убраны служебные age_*/level_* метки.
- Сохранённые данные (§13): кодовое слово, дата запуска бота (started_at), дата
  передачи менеджеру (manager_at), интересы (пробное/интенсив). Карточка менеджеру
  дополнена этими полями, заголовок «Новый запрос из бота».
- «Пока не знаю, нужен совет» (§7): показ собранных данных + свободный текст → менеджеру.
- «Задать вопрос» (§9): промпт «напишите одним сообщением» → BAZA_QUESTION → передача.
- Летний интенсив: свой набор уровней (§10.3), экран младше-12 (Передать менеджеру/
  Другие тренировки), двухшаговая оплата (Оплатить интенсив → ссылка) (§10.4),
  различение запуска по кодовому слову vs меню.
- Индивидуальная ветка без «пробного» (§6). Fallback-текст дословно по §15.
- «Выбрать абонемент» ведёт на страницу тарифов ссылкой (§8). Тексты веток — по ТЗ.

Тесты воронки обновлены и дополнены (интенсив-оплата, младше-12 интенсив, свободный
вопрос, «нужен совет»). pytest 30 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 13:55:34 +03:00
Kenik 04d5b0487d docs: ТЗ на настройку бота (БАЗА) + описание приёма оплаты в боте
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 18:36:39 +03:00
Kenik 74a855819d Чистка старого ИКП-флоу: удалены форма-заявка, карьера/вакансии, меню FAQ и осиротевшая админка
Из ТЗ Кибершколы БАЗА эти сценарии заменены воронкой подбора, поэтому убран мёртвый код:
- клиентские FSM: FORM_* (форма-заявка, возвращающийся клиент, редактирование, согласия,
  выбор услуги, карусель) и VAC_* (карьера: игроки/сотрудники);
- меню «Частые вопросы» и config.FAQ_ANSWERS;
- осиротевшая админка: управление услугами + карусель, вакансии, кандидаты
  (в панели и в мастере ADMIN_SVC_*/ADMIN_VAC_*), блок статистики по откликам;
- старый _handoff_to_operator и _notify_operator_about_lead (заменены _baza_to_manager);
- неиспользуемые клавиатуры (форма/услуги/вакансии/согласия) и импорты (validators, random, string).

Оставлено (используется/по ТЗ): воронка БАЗА, быстрые ответы (custom_faq), стата по лидам,
рассылка, управление админами, чат с оператором, логотип. Слой БД не тронут — существующие
установки не ломаются (таблицы services/applications/vacancy_options просто не используются).

bot.py: -1490 строк. Тесты: pytest 28 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 18:36:38 +03:00
Kenik 60199fb47b Ребрендинг БАЗА: новое меню + воронка подбора, интенсив, оплата, карточка менеджеру
Меню Кибершколы БАЗА (4 кнопки): Подобрать тренировку / Летний интенсив CS2 /
Посмотреть цены / Задать вопрос.

Воронка «Подобрать тренировку» (FSM BAZA_*): для кого → возраст → игра → уровень →
формат → групповые / индивидуальные / нужен совет. На каждом шаге — «Назад» и «В
главное меню», ветки: младше 12 и «другая игра» уводят к менеджеру.

Ветка «Летний интенсив CS2»: инфо → возраст → уровень → оплата. Запуск по кнопке и
по кодовым словам (лето/интенсив), основные триггеры и приветствие — из config.

Шаг оплаты: инлайн-кнопка «Перейти к оплате» (ссылки-плейсхолдеры из config.LINKS +
UTM), «Проблема с оплатой» и «Задать вопрос менеджеру» уводят к оператору.

Карточка менеджеру собирается из профиля воронки (пустые поля пропускаются) + метки;
дублируется на почту. Данные не переспрашиваются, после передачи менеджеру бот не
вмешивается (OPERATOR_CHAT). Тесты воронки — pytest (30 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 18:20:59 +03:00
Kenik 06847fa87e start_bot.bat: запуск бота на Python 3.11 (py -3.11)
Переустановлен Python 3.11 (в прежней установке пропал python.exe), зависимости
поставлены в него. .bat теперь использует py -3.11 для запуска и pip, чтобы бот
стабильно работал на 3.11 независимо от того, куда указывает системный python.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 18:07:48 +03:00
Kenik f6a635cc2e Ребрендинг БАЗА (фундамент): конфиг + профиль воронки в БД
Фаза 1 — config: BRAND «Кибершкола БАЗА», цены/тексты по ТЗ (приветствие,
прайс, интенсив), 8 ссылок-плейсхолдеров с UTM, триггеры (основные/лето).
Фаза 2 — database: JSON-профиль воронки (роль/возраст/игра/уровень/формат/
метки/…) + методы get/set/clear + add_metka. Живой флоу пока не затронут.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:58:00 +03:00
Kenik ce2860aec9 start_bot.bat: авто-подготовка окружения при первом запуске
- проверка наличия Python в PATH;
- создание .env из .env.example, если его нет (с открытием на заполнение);
- установка зависимостей из requirements.txt;
- далее как прежде: глушение дублей + цикл авто-перезапуска.
bot_database.db создаётся кодом автоматически (с сидом услуг).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:20:24 +03:00
Kenik 0aaf285d54 Соцсети: Discord заменён на Lolka (новая ссылка через vk away)
Кнопка соцсетей и текст «О компании» теперь ведут на Lolka:
https://vk.com/away.php?to=https%3A%2F%2Flolka.gg%2FlNfM3F9DD&utf=1

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:58:05 +03:00
Kenik ffdd7fc1fc Seed: зашиты все 6 услуг (включая групповые) для свежих установок
Чтобы при запуске из репозитория услуги были сразу, а не только дефолтные 3.
Заявки/персональные данные по-прежнему только в локальной БД (не в git).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:53:34 +03:00
Kenik 26b6df77ef удаление документа "Dogovor_oferty_kibersport_versia_izmenennaya.docx" и добавление новых изображений для помощи в сервисе. 2026-06-26 17:00:41 +03:00
Kenik f14b8769e5 Добавление админа по ссылке VK (не только числовой ID)
Бот принимает ссылку (https://vk.com/gruzdevas), короткое имя (gruzdevas),
@имя или числовой ID и сам определяет user_id (короткое имя — через VK API
users.get). Резолвер _resolve_vk_user_id применён к добавлению и удалению админа.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 19:06:45 +03:00
Kenik 0ec849d80f Соцсети: добавлена кнопка-ссылка на сайт infocyber.pro
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:21:52 +03:00
Kenik fc3361c7ea Фикс клавиатуры возвращающегося клиента + защита от двух экземпляров
- Возвращающийся клиент: «Да/Отмена» — нижняя клавиатура, а «Сменить имя/
  телефон/Заполнить заново» — отдельные инлайн-кнопки под сообщением (ровно 3,
  как просил).
- start_bot.bat: перед запуском убивает старые экземпляры бота — устраняет
  «рандомные» цвета от нескольких параллельных longpoll-инстансов.
- Маска телефона в приветствии возвращающегося клиента.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:14:57 +03:00