Skip to content

About

Бот заявок для технической поддержки в чатах телеграм

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Telegram-бот заявок техподдержки

Python 3.11–3.12, aiogram 3, SQLite. Сообщения клиента собираются в одно обращение. Если за RESPONSE_TIMEOUT секунд специалист не ответил в клиентском чате, бот создаёт заявку в рабочем чате. Есть роли, статистика, Excel-выгрузки, объявления, напоминания и автоочистка.

Автоматическая установка на сервер

Поддерживаются Debian 12 и Ubuntu 24.04, Python 3.11–3.12, systemd. Нужны интернет, права sudo и интерактивный терминал. Для Windows ниже приведён ручной запуск; установщик службы предназначен для Linux.

Скачайте установщик, просмотрите его и запустите:

sudo apt-get update && sudo apt-get install -y curl
curl --fail --location --output install.sh https://raw.githubusercontent.com/IndeecDen/tg_ts_ticket_bot/main/install.sh
less install.sh
sudo bash install.sh --branch main

Установщик скачивает проект из GitHub, устанавливает системные и Python-зависимости в отдельное окружение, создаёт пользователя ticketbot, службу tg_ts_ticket_bot и включает запуск при загрузке сервера. При установке он запросит:

  1. BOT_TOKEN из BotFather; ввод скрыт.
  2. WORK_CHAT_ID — отрицательный ID рабочего группового чата специалистов.
  3. Время ожидания ответа в секундах (по умолчанию 300).

Проверяется формат значений. Действительность токена и права в чате нужно проверить после запуска через Telegram и журнал службы. Токен не передаётся аргументом командной строки. Настройки доступны только пользователю службы и root. База создаётся автоматически при первом запуске: исходная база с заявками, роли и личные настройки в репозитории отсутствуют.

Путь Содержимое
/opt/tg_ts_ticket_bot Исходники и .venv, принадлежат root
/var/lib/tg_ts_ticket_bot/.env Токен и настройки, права 600
/var/lib/tg_ts_ticket_bot/bot.db База новой установки
/var/log/tg_ts_ticket_bot/bot.log Журнал с ротацией
/etc/systemd/system/tg_ts_ticket_bot.service Служба и автозапуск

Дайджесты и автоочистка используют часовой пояс сервера (timedatectl). Таймеры рассылок используют отдельную настройку TIMEZONE (по умолчанию UTC). Код защищён от записи пользователем службы; база, настройки и журнал размещены отдельно.

sudo systemctl status tg_ts_ticket_bot
sudo journalctl -u tg_ts_ticket_bot -f
sudo systemctl restart tg_ts_ticket_bot
sudo systemctl stop tg_ts_ticket_bot
# Отключить автозапуск и остановить:
sudo systemctl disable --now tg_ts_ticket_bot

Для изменения токена или рабочего чата остановите службу, отредактируйте sudo nano /var/lib/tg_ts_ticket_bot/.env и запустите sudo systemctl start tg_ts_ticket_bot. Команда бота /set_timeout сохраняет таймаут в этот же файл.

Повторная установка поверх существующих каталогов, пользователя или службы запрещена. При ошибке установщик оставляет созданные файлы для диагностики и не удаляет данные. Исправьте причину по сообщению ошибки; не удаляйте существующую базу ради повторного запуска установщика.

Обновление установки со службой

Остановите службу и сделайте резервную копию всего /var/lib/tg_ts_ticket_bot в закрытом каталоге. Затем:

sudo systemctl stop tg_ts_ticket_bot
sudo git -C /opt/tg_ts_ticket_bot pull --ff-only
sudo /opt/tg_ts_ticket_bot/.venv/bin/python -m pip install -r /opt/tg_ts_ticket_bot/requirements.txt
sudo systemctl start tg_ts_ticket_bot
sudo systemctl status tg_ts_ticket_bot

Обновление исходников не затрагивает /var/lib/tg_ts_ticket_bot. Общие правила миграции и отката приведены ниже.

Ручная установка

Создайте новое виртуальное окружение для своей ОС. Папка venv, перенесённая с Linux, не подходит для Windows.

Windows PowerShell:

py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
Copy-Item .env.example .env  # только при первой установке, если .env ещё нет
.\.venv\Scripts\python.exe main.py

Linux:

python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
cp -n .env.example .env
.venv/bin/python main.py

В .env укажите BOT_TOKEN из BotFather и WORK_CHAT_ID рабочего чата. Добавьте бота в рабочий и клиентские чаты. Чтобы получать обычные сообщения групп, настройте доступ бота к сообщениям группы; для проверки участников и очистки нужны соответствующие права администратора.

Параметры:

Переменная Назначение По умолчанию
BOT_TOKEN Токен Telegram-бота Обязателен
WORK_CHAT_ID Рабочий чат специалистов Обязателен
RESPONSE_TIMEOUT Ожидание ответа перед созданием заявки, секунды 300
DATABASE_PATH Путь к SQLite bot.db
LOG_LEVEL Уровень журнала INFO
LOG_PATH Файл журнала bot.log
TIMEZONE Часовой пояс IANA для рассылок, например Europe/Moscow UTC
BROADCAST_SEND_INTERVAL Пауза между отправками рассылок, секунды, от 0.05 до 60 0.05
BOT_ENV_FILE Путь к файлу настроек; задаётся в окружении процесса до запуска .env в папке проекта

Относительные пути базы и журнала считаются от папки проекта, а не текущей папки запуска. Файл настроек выбирается через BOT_ENV_FILE, по умолчанию .env читается из папки проекта. Переменные окружения процесса имеют приоритет над файлом. Если RESPONSE_TIMEOUT задан в окружении службы, обновляйте его там: /set_timeout сохраняет значение в выбранный файл настроек и памяти текущего процесса. Изменение применяется к новым обращениям.

Расписание напоминаний и исторические даты заявок используют локальное время сервера. Настройте его часовой пояс до запуска и не меняйте его при работе с существующей историей. Рассылки сохраняют время в UTC и показывают в явно указанном TIMEZONE; неверный пояс останавливает запуск с ошибкой конфигурации. Зависимость tzdata обеспечивает работу IANA-поясов в том числе в Windows.

Роли и команды

Администраторы рабочего чата и зарегистрированные ботадмины могут управлять настройками, в том числе в личной переписке. Специалисты и ботадмины добавляются командами /add_spec <user_id> и /add_botadm <user_id>. Полный список — /help.

  • Клиент: описание проблемы, /cancel, кнопка отмены созданной заявки.
  • Специалист: взять заявку, завершить свою заявку, /my_active_requests, /my_stats.
  • Администратор: /stats, /export, настройки, /close_all.
  • /assign_request <номер> <ID специалиста> — назначить исполнителя существующей заявки в работе, в том числе восстановить привязку старой заявки без ID. Только для администратора.
  • /cancel во время диалога настройки отменяет этот диалог; кнопка «Назад» также очищает состояние диалога.

Права повторно проверяются при нажатии кнопок статистики и действиях с заявками. Закрытие и личная статистика используют неизменяемый Telegram ID, а не отображаемое имя.

Обновление существующей установки

  1. Остановите старый процесс бота. Запускайте один экземпляр с одним токеном и одной базой.
  2. Сохраните .env и базу. Не заменяйте их примерами из проекта.
  3. Обновите исходники и установите зависимости в окружение нужной ОС.
  4. Запустите main.py. Перед обновлением схемы до версии 2 бот автоматически создаст согласованную SQLite-копию bot.db.backup-<дата-время> (имя зависит от DATABASE_PATH). Затем добавит таблицы очередей, рассылок и индексы без удаления заявок.
  5. Проверьте журнал, /open_requests и доставку тестового обращения.

Старые незаконченные доставки активных заявок будут поставлены в очередь автоматически. Старые записи active_timers сохраняются с предупреждением в журнале: прежняя версия не записывала тексты ожидающих сообщений на диск, поэтому восстановить уже потерянные тексты невозможно. Новые ожидающие обращения сохраняются целиком в pending_requests.

Старые заявки без specialist_id не привязываются по совпадению имени. Для активных используйте /assign_request; архивные записи остаются в общей статистике с пометкой «архив без ID» и не включаются в личную статистику.

Для отката остановите бот и восстановите резервную копию вместе с предыдущими исходниками. Не подменяйте файл работающей SQLite. Для регулярных резервных копий работающей базы используйте SQLite Backup API; простое копирование только .db при активном WAL может пропустить последние изменения.

📣 Массовые рассылки

Откройте личный диалог → /start → 📣 Рассылки (также есть в «⚙️ Настройки» и по /broadcast). Доступ имеют ботадмины и администраторы рабочего чата; права проверяются при каждом действии и перед запуском таймера.

  1. Нажмите «✏ Новая рассылка» и пришлите одно сообщение: текст, фото, документ, видео или аудио. Подпись необязательна. Альбомы, анимации, стикеры, голосовые и другие типы отклоняются целиком.
  2. Выделяйте текст средствами Telegram: жирный, курсив, подчёркивание, зачёркивание, спойлер, ссылки, код, цитаты. Бот сохраняет entities/caption_entities и UTF-16-смещения, включая эмодзи. Написанные вручную HTML-теги остаются обычным текстом.
  3. Лимиты: 4096 символов текста, 1024 символа подписи после разбора сущностей. Смещения форматирования считаются отдельно в UTF-16. Превышение лимита отклоняется без обрезки. Составные эмодзи могут содержать несколько Unicode-символов.
  4. Бот показывает сохранённое сообщение и новое сообщение ниже него с тремя кнопками: «🚀 Отправить сейчас», «🕒 По таймеру», «✖ Отменить». До подтверждения сообщений в группы нет. Число известных групп предварительное: окончательные адресаты фиксируются при запуске.
  5. Таймер принимает 30 (минуты от текущего момента, 1–525600) или 2030-01-02 10:00. Используется показанный TIMEZONE. Прошедшее, несуществующее и неоднозначное местное время отклоняется. При ошибке черновик и кнопка отмены сохраняются.
  6. «📋 Список рассылок» → «📋 Открыть #…»: автор, статус, даты и пояс, счётчики, обновление и ошибки по группам с пагинацией. Через «Предпросмотр» можно снова открыть черновик после перезапуска или неудачного предпросмотра.

«✖ Отменить» и /cancel отменяют текущую подготовку, включая этап после предпросмотра. Запланированную рассылку можно отменить из списка до запуска. После запуска отмена уже доставленных сообщений не выполняется. Кнопка «Назад» закрывает диалог; сохранённый черновик доступен в списке. Действия создания, планирования, запуска и отмены записываются в broadcast_audit.

Группы-получатели

Постоянный реестр пополняется входящими сообщениями групп и my_chat_member; старые ID восстанавливаются из заявок и ожидающих обращений с проверкой типа чата, членства и права отправки. Личные чаты, каналы, рабочий чат из текущей конфигурации и группы с удалённым/ограниченным ботом исключаются. Права проверяются также перед доставкой; изменение прав уже после проверки может дать отдельную ошибку Telegram.

Telegram не выдаёт полный список чатов бота. Если старая группа ещё неизвестна, отправьте в ней /whoami@ИмяВашегоБота. Такая адресованная команда работает при privacy mode; выдавать права администратора только ради регистрации необязательно, но нужно разрешение отправлять сообщения. Пересылка в личный диалог исходную группу не регистрирует. После восстановления прав повторите /whoami либо обновите членство бота.

Миграция в супергруппу обрабатывается по обоим служебным полям сообщения и ответу API: сохраняется соответствие старого/нового ID, меняется адрес будущей доставки, исходный чат существующих заявок сохраняется отдельно. История результатов отправки не удаляется.

Очередь, восстановление и ограничения

  • Черновики, содержимое, file_id, расписания, адресаты, результаты и задержки находятся в той же SQLite. Новые таблицы broadcast_* используют существующий AsyncDatabase; очередь карточек заявок delivery_queue остаётся специализированной для их ревизий.
  • Отправка выполняется фоновым работником. Создание уникальных заданий «рассылка — чат» и фиксация адресатов транзакционные. Повторное подтверждение не создаёт вторую рассылку. SQL выполняется вне event loop; сетевых запросов внутри транзакций нет.
  • Сохранённые таймеры запускаются после восстановления, включая пропущенное время. Отзыв роли автора отменяет расписание; временная ошибка проверки роли откладывает запуск.
  • Скорость рассылок — не более 20 отправок/с по умолчанию, в одну группу — не чаще раза в 3.1 с между любыми рассылками. 429 сохраняет общую паузу очереди рассылок и задержку задания. Другие функции бота также расходуют лимит Telegram: при совместной нагрузке возможны дополнительные 429.
  • Ошибки одного адресата не останавливают остальных. Сетевой обрыв, 5xx и прерванная при остановке отправка получают «Неопределённый результат»: автоматически повторно не отправляются. Откройте «Ошибки», вручную проверьте группу и решите, нужна ли отдельная новая рассылка. Гарантии «ровно один раз» нет.
  • Один процесс на одну базу: запуск защищён OS-блокировкой <DATABASE_PATH>.lock, автоматически освобождаемой при остановке/аварии. Удалять файл блокировки во время работы нельзя. Для нескольких серверов/сетевой файловой системы этот режим не предназначен.
  • Поддерживается одно вложение и разовый таймер. file_id принадлежит текущему боту; смена токена на другого бота может сделать старые вложения недоступными. Telegram может ограничивать отдельные сущности (например, custom emoji); ошибка предпросмотра показывается явно. Платные рассылки и Stars не используются.

Лимиты методов сверены 08.10.2026 по актуальным описаниям aiogram и исходникам Telegram/TDLib. Для новой загрузки: фото до 10 МБ, документ/видео/аудио до 50 МБ; эта функция повторно отправляет уже загруженные файлы по file_id, не скачивает и не загружает их заново. Прямая страница core.telegram.org была недоступна из среды проверки. Предпросмотр и доставка используют один отправитель и одинаковые параметры, включая спойлер/расположение подписи.

Сохранность и доставка

  • Текст, идентификаторы сообщений и медиа сохраняются до ожидания таймаута. Одновременно принимаются обращения разных пользователей одного чата.
  • Создание заявки и заданий доставки выполняется одной транзакцией. Повторная обработка сохранённого обращения не создаёт вторую заявку.
  • Рабочий чат и клиент уведомляются независимо. Сбой одного направления не отменяет сохранённую заявку.
  • Очередь delivery_queue хранит попытки, время следующей попытки и последнюю ошибку. Сетевые ошибки повторяются с увеличением задержки до часа; RetryAfter учитывается, недоступный чат повторяется через час.
  • Изменение статуса также ставит обновления обоих чатов в очередь. Ошибка редактирования не оставляет статус только в БД навсегда.
  • SQLite работает вне основного цикла событий. Сетевые операции разных заявок выполняются с ограничением параллельности; общего замка на сетевые запросы нет.
  • Описания полностью сохраняются в БД. Карточка показывает сокращённый текст и первое поддерживаемое вложение, как и прежняя версия; полное описание закрытых заявок доступно в /export. Длинные отчёты разбиваются на сообщения с корректным HTML.

Telegram не предоставляет ключ идемпотентности для отправки: при обрыве соединения после приёма сообщения Telegram, но до получения ответа ботом повторная попытка может создать повторное уведомление. Сама заявка в БД при этом остаётся одна. Невозможно программно исправить блокировку бота пользователем, отсутствие прав или недоступность сети; очередь сохраняет уведомления для повторов.

Структура

  • main.py — запуск, зависимости, остановка фоновых задач.
  • handlers/common.py — роли и общие состояния диалогов.
  • handlers/commands.py — команды клиентов/специалистов и ввод дат.
  • handlers/admin.py — администрирование и настройки.
  • handlers/callbacks_requests.py — разрешённые переходы статусов.
  • handlers/callbacks_stats.py, handlers/keyboards.py — отчёты и меню.
  • services/requests.py — обработка сохранённых обращений и доставка.
  • services/scheduler.py — дайджесты и автоочистка.
  • handlers/broadcast.py, services/broadcasts.py, db/broadcast_store.py — диалоги, валидация, реестр, расписание и постоянная очередь рассылок.
  • utils/process_lock.py — защита запуска второго процесса на той же базе.
  • db/database.py, db/request_store.py — SQL, миграции и транзакции.
  • db/async_database.py — выполнение SQL в рабочих потоках.
  • utils/ — ограничение длины/HTML, Telegram, Excel и журнал.
  • tests/ — регрессионные проверки без реальных запросов Telegram.

Проверки

После установки зависимостей:

python -m unittest discover -s tests -v

Тесты создают отдельные базы в .test-data, имитируют Telegram и проверяют обработчики через настоящий диспетчер aiogram. Если рядом есть bot.db, один тест открывает её только для чтения, создаёт копию и проверяет миграцию и сохранение заявок на копии. Исходная база, .env и рабочий журнал не изменяются.

.env, базы, резервные копии, журналы и виртуальные окружения исключены через .gitignore. Не публикуйте их вместе с исходниками.

About

Бот заявок для технической поддержки в чатах телеграм

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages