Система для организации и проведения многоэтапных голосований через веб-интерфейс и Telegram-бота.
Публичная обезличенная версия коммерческого проекта. Сведения о заказчике, реальные данные, пользовательские идентификаторы, секреты и production-конфигурация не публикуются.
Система автоматизирует создание кампаний и раундов голосования, управление участниками, приём голосов через Telegram и отображение текущих результатов в веб-интерфейсе.
В публичной версии сохранены основные архитектурные и технические решения. Названия, идентификаторы пользователей и демонстрационные данные изменены или удалены.
- несколько независимых кампаний;
- стандартные и индивидуальные раунды;
- голосование через inline-кнопки Telegram;
- защита от повторного голоса;
- проверка принадлежности участника выбранному раунду;
- публикация и скрытие результатов;
- автоматический подсчёт голосов и определение победителей;
- перенос участников между раундами;
- отображение результатов на веб-странице;
- обновление результатов без полной перезагрузки страницы.
Через Telegram-бота администратор может:
- создавать кампании;
- запускать и завершать раунды;
- добавлять и удалять участников;
- выбирать текущий отображаемый раунд;
- задавать количество победителей;
- переносить победителей в следующий раунд;
- восстанавливать завершённые раунды;
- экспортировать результаты в CSV.
- Token Authentication между Telegram-ботом и Django API;
- разграничение ролей администраторов;
- ограничение частоты обращений к API;
- anti-flood middleware Telegram-бота;
- проверка повторных голосов на уровне приложения и базы данных;
- защита CSV от formula injection;
- хранение конфигурации в переменных окружения;
- ротация логов Django и Telegram-бота.
flowchart LR
User[Telegram user]
Admin[Telegram administrator]
Bot[Telegram bot<br/>aiogram]
API[Django REST API]
DB[(PostgreSQL)]
Web[Web results page]
User -->|Vote| Bot
Admin -->|Manage campaigns and rounds| Bot
Bot -->|Token-authenticated HTTP requests| API
API --> DB
DB --> Web
Проект состоит из трёх сервисов:
- Django-приложение — REST API и веб-страница результатов.
- Telegram-бот — пользовательское голосование и административное управление.
- PostgreSQL — хранение кампаний, раундов, участников и голосов.
Telegram-бот взаимодействует с Django через асинхронные HTTP-запросы и Token Authentication.
| Компонент | Технология |
|---|---|
| Backend | Python, Django |
| REST API | Django REST Framework |
| Telegram-бот | aiogram, aiohttp |
| База данных | PostgreSQL |
| Локальная БД | SQLite |
| Application server | Gunicorn |
| Static files | WhiteNoise |
| Конфигурация | python-decouple |
| Контейнеризация | Docker, Docker Compose |
| Логирование | logging, RotatingFileHandler |
voting_site/
├── core/ # настройки и маршрутизация Django
├── voting/ # модели, API и логика голосования
├── tg_bot/ # Telegram-бот и Django API client
├── templates/ # HTML-шаблоны
├── static/ # CSS, изображения и JavaScript
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── manage.py
Создайте файл .env на основе .env.example:
cp .env.example .envДля Windows PowerShell:
Copy-Item .env.example .envОсновные переменные:
| Переменная | Описание |
|---|---|
SECRET_KEY |
Секретный ключ Django |
DEBUG |
Режим отладки |
ALLOWED_HOSTS |
Разрешённые домены |
DB_ENGINE |
postgres или sqlite |
POSTGRES_DB |
Название базы данных |
POSTGRES_USER |
Пользователь PostgreSQL |
POSTGRES_PASSWORD |
Пароль PostgreSQL |
POSTGRES_HOST |
Адрес PostgreSQL |
POSTGRES_PORT |
Порт PostgreSQL |
TELEGRAM_TOKEN |
Токен Telegram-бота |
DJANGO_API_TOKEN |
DRF-токен Telegram-бота |
DJANGO_API_BASE |
Адрес Django API |
FULL_ADMIN_IDS |
Telegram ID главных администраторов |
LIMITED_ADMIN_IDS |
Telegram ID модераторов |
Не публикуйте настоящий .env, Telegram-токен, Django-токен
и Telegram ID пользователей.
git clone https://github.com/BulatKSMNT/voting_site.git
cd voting_sitecp .env.example .envЗаполните необходимые значения в .env.
docker compose up -d --build db webdocker compose exec web python manage.py migratedocker compose exec web python manage.py createsuperuserdocker compose exec web python manage.py drf_create_token <username>Сохраните полученное значение в .env:
DJANGO_API_TOKEN=your-django-api-tokendocker compose up -d botDjango:
docker compose logs -f webTelegram-бот:
docker compose logs -f bothttp://127.0.0.1/
Страница результатов:
http://127.0.0.1/voting/results/
Django Admin:
http://127.0.0.1/admin/
docker compose downДля удаления локальной базы данных:
docker compose down -vКоманда
docker compose down -vудаляет PostgreSQL volume и все локальные данные.
python -m venv .venvLinux/macOS:
source .venv/bin/activateWindows PowerShell:
.venv\Scripts\Activate.ps1Установите зависимости:
pip install -r requirements.txtПодготовьте .env и примените миграции:
python manage.py migrate
python manage.py runserverДля локального запуска Telegram-бота укажите:
DJANGO_API_BASE=http://127.0.0.1:8000/voting/apiЗатем в отдельном терминале:
python tg_bot/bot.pyОсновные сущности:
Campaign— кампания голосования;Round— раунд и его состояние;Participant— участник определённого раунда;Vote— голос пользователя за участника.
На уровне базы данных ограничивается повторное голосование одного пользователя за одного участника в рамках одного раунда.
Репозиторий является обезличенной публичной версией коммерческой системы.
В нём отсутствуют:
- сведения о заказчике;
- реальные имена участников;
- результаты реальных голосований;
- Telegram ID пользователей и администраторов;
- API-токены и другие секреты;
- production-домен и инфраструктурная конфигурация.
Перед публикацией дополнительных изменений необходимо проверять код, миграции, историю Git и демонстрационные файлы на наличие закрытых данных.
Булат Хатыпов
- GitHub: BulatKSMNT
- Telegram: @khat911