✅ Регистрация и верификация жильцов ✅ Рейтинг активности (уровни) ✅ Детект шпионов (Score 0-100) ✅ Анти-мат система (3 предупреждения → бан) ✅ Админ-панель с рассылкой ✅ Учёт квартир (несколько жильцов) ✅ Телефоны экстренных служб и мастеров ✅ Еженедельный экспорт JSON ✅ Прокси (socks5) для обхода РКН Бекап: backups/versions/v1.0_mvp_2026-02-26/ Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
415 lines
12 KiB
Markdown
415 lines
12 KiB
Markdown
# 📊 Опросы и голосования — v1.1
|
||
|
||
**Версия:** v1.1
|
||
**Дата:** 26 февраля 2026 г.
|
||
**Статус:** ✅ Реализовано
|
||
|
||
---
|
||
|
||
## 📋 Описание
|
||
|
||
Система создания и проведения опросов в чате дома. Позволяет администраторам создавать голосования с inline-кнопками, жильцы голосуют анонимно, результаты отображаются в реальном времени.
|
||
|
||
---
|
||
|
||
## 🎯 Возможности
|
||
|
||
- ✅ Создание опросов с 2-10 вариантами ответов
|
||
- ✅ Inline-кнопки для голосования
|
||
- ✅ Подсчёт голосов в реальном времени
|
||
- ✅ Отображение результатов в процентах
|
||
- ✅ Визуальная шкала (████░░░░░░)
|
||
- ✅ Закрытие опроса админом
|
||
- ✅ Защита от повторного голосования (1 человек = 1 голос)
|
||
- ✅ Только админы могут создавать опросы
|
||
|
||
---
|
||
|
||
## 📱 Команды
|
||
|
||
### Для администраторов:
|
||
|
||
| Команда | Описание | Пример |
|
||
|---------|----------|--------|
|
||
| `/poll_create "Вопрос" "Вариант 1" "Вариант 2"` | Создать опрос | `/poll_create "За какой цвет?" "Бежевый" "Зелёный"` |
|
||
| `/poll_create` (в диалоге) | Пошаговое создание | Бот спросит вопрос, потом варианты |
|
||
| `/poll_end <ID>` | Закрыть опрос | `/poll_end 5` |
|
||
| `/polls` | Список активных опросов | `/polls` |
|
||
|
||
### Для жильцов:
|
||
|
||
| Действие | Описание |
|
||
|----------|----------|
|
||
| **Нажать кнопку** | Проголосовать за вариант |
|
||
| `/polls` | Посмотреть активные опросы |
|
||
|
||
---
|
||
|
||
## 🎯 Сценарии использования
|
||
|
||
### Сценарий 1: Быстрое создание (с аргументами)
|
||
|
||
**Админ пишет в чат:**
|
||
```
|
||
/poll_create "За какой цвет покрасить подъезд?" "Бежевый" "Зелёный" "Серый" "Белый"
|
||
```
|
||
|
||
**Бот создаёт опрос:**
|
||
```
|
||
📊 ОПРОС
|
||
|
||
За какой цвет покрасить подъезд?
|
||
|
||
Голосуйте кнопками ниже! 👇
|
||
|
||
[🔘 Бежевый]
|
||
[🔘 Зелёный]
|
||
[🔘 Серый]
|
||
[🔘 Белый]
|
||
```
|
||
|
||
**Ответ бота (в личку админу):**
|
||
```
|
||
✅ Опрос создан!
|
||
|
||
Вопрос: За какой цвет покрасить подъезд?
|
||
Вариантов: 4
|
||
|
||
Для закрытия: /poll_end 1
|
||
```
|
||
|
||
---
|
||
|
||
### Сценарий 2: Пошаговое создание (в диалоге)
|
||
|
||
**1. Админ пишет:**
|
||
```
|
||
/poll_create
|
||
```
|
||
|
||
**2. Бот просит:**
|
||
```
|
||
📊 Создание опроса
|
||
|
||
Отправьте вопрос опроса (или используйте команду с аргументами):
|
||
/poll_create "За какой цвет покрасить подъезд?" "Бежевый" "Зелёный" "Серый"
|
||
```
|
||
|
||
**3. Админ отправляет:**
|
||
```
|
||
Когда провести субботник?
|
||
```
|
||
|
||
**4. Бот просит:**
|
||
```
|
||
📝 Теперь отправьте варианты ответов через запятую:
|
||
|
||
Вариант 1, Вариант 2, Вариант 3
|
||
|
||
Или отмените: /cancel
|
||
```
|
||
|
||
**5. Админ отправляет:**
|
||
```
|
||
5 марта, 12 марта, 19 марта
|
||
```
|
||
|
||
**6. Бот создаёт опрос** (как в Сценарии 1)
|
||
|
||
---
|
||
|
||
### Сценарий 3: Голосование жильца
|
||
|
||
**1. Жилец видит опрос в чате:**
|
||
```
|
||
📊 ОПРОС
|
||
|
||
За какой цвет покрасить подъезд?
|
||
|
||
Голосуйте кнопками ниже! 👇
|
||
|
||
[🔘 Бежевый]
|
||
[🔘 Зелёный]
|
||
[🔘 Серый]
|
||
[🔘 Белый]
|
||
```
|
||
|
||
**2. Жилец нажимает кнопку** `[🔘 Зелёный]`
|
||
|
||
**3. Бот отвечает (в личку):**
|
||
```
|
||
✅ Ваш голос учтён!
|
||
```
|
||
|
||
**4. В чат отправляются результаты:**
|
||
```
|
||
📊 Результаты голосования
|
||
|
||
█████░░░░░ Бежевый: 3 (15%)
|
||
██████████ Зелёный: 10 (50%)
|
||
████░░░░░░ Серый: 2 (10%)
|
||
█████░░░░░ Белый: 5 (25%)
|
||
|
||
👥 Всего голосов: 20
|
||
```
|
||
|
||
---
|
||
|
||
### Сценарий 4: Повторное голосование
|
||
|
||
**Если жилец передумал и нажал другую кнопку:**
|
||
|
||
1. Старый голос **автоматически удаляется**
|
||
2. Новый голос **учитывается**
|
||
3. Результаты **обновляются**
|
||
|
||
**Пример:**
|
||
- Жилец нажал «Зелёный» → +1 к Зелёному
|
||
- Через час нажал «Бежевый» → -1 у Зелёного, +1 к Бежевому
|
||
|
||
---
|
||
|
||
### Сценарий 5: Закрытие опроса
|
||
|
||
**Админ:**
|
||
```
|
||
/poll_end 1
|
||
```
|
||
|
||
**Бот публикует в чат:**
|
||
```
|
||
🔒 ОПРОС ЗАКРЫТ
|
||
|
||
Вопрос: За какой цвет покрасить подъезд?
|
||
|
||
██████████ Бежевый: 5 (25%)
|
||
██████████ Зелёный: 10 (50%)
|
||
████░░░░░░ Серый: 2 (10%)
|
||
█████░░░░░ Белый: 3 (15%)
|
||
|
||
👥 Всего голосов: 20
|
||
```
|
||
|
||
**Опрос больше не принимает голоса** (кнопки не работают).
|
||
|
||
---
|
||
|
||
### Сценарий 6: Просмотр списка опросов
|
||
|
||
**Жилец:**
|
||
```
|
||
/polls
|
||
```
|
||
|
||
**Бот:**
|
||
```
|
||
📊 Активные опросы
|
||
|
||
1. За какой цвет покрасить подъезд?... (20 голосов) 🟢 Активен
|
||
2. Когда провести субботник?... (15 голосов) 🟢 Активен
|
||
|
||
💡 Для голосования нажмите на кнопку в сообщении с опросом
|
||
```
|
||
|
||
---
|
||
|
||
## 🛡️ Защита и ограничения
|
||
|
||
### Кто может создавать опросы:
|
||
- ✅ **Только администраторы**
|
||
- ❌ Обычные пользователи — команда не доступна
|
||
|
||
### Кто может голосовать:
|
||
- ✅ **Все жильцы** (даже неверифицированные)
|
||
- ✅ Один голос от человека
|
||
- ✅ Можно поменять голос
|
||
|
||
### Максимум вариантов:
|
||
- **10 вариантов** (если больше — обрежутся)
|
||
|
||
### Где работают опросы:
|
||
- ✅ **В общем чате** (создание и голосование)
|
||
- ❌ В личке — только справка
|
||
|
||
---
|
||
|
||
## 🗄️ База данных
|
||
|
||
### Таблица `polls`:
|
||
|
||
```sql
|
||
CREATE TABLE polls (
|
||
poll_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
message_id BIGINT NOT NULL, -- ID сообщения в Telegram
|
||
chat_id BIGINT NOT NULL, -- ID чата
|
||
question TEXT NOT NULL, -- Вопрос
|
||
options TEXT NOT NULL, -- JSON: ["В1", "В2", ...]
|
||
votes TEXT, -- JSON: {"0": [uid1, uid2], "1": [uid3]}
|
||
created_by BIGINT NOT NULL, -- ID создателя
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
is_active BOOLEAN DEFAULT 1, -- Активен ли
|
||
closed_at TIMESTAMP, -- Дата закрытия
|
||
FOREIGN KEY (created_by) REFERENCES users(user_id)
|
||
)
|
||
```
|
||
|
||
### Индексы:
|
||
- `ix_polls_chat_active` — для быстрого поиска по чату
|
||
- `ix_polls_created_at` — для сортировки по дате
|
||
|
||
---
|
||
|
||
## 🧪 Тестирование
|
||
|
||
### Чек-лист проверки:
|
||
|
||
#### 1. Создание опроса
|
||
```bash
|
||
# В тестовой группе (админ):
|
||
/poll_create "Тест?" "Да" "Нет"
|
||
```
|
||
- [ ] Опрос появился в чате
|
||
- [ ] Кнопки отображаются
|
||
- [ ] Бот прислал номер опроса
|
||
|
||
#### 2. Голосование
|
||
```bash
|
||
# С другого аккаунта (друг):
|
||
# Нажать кнопку "Да"
|
||
```
|
||
- [ ] Голос засчитался
|
||
- [ ] Результаты показали проценты
|
||
- [ ] В БД обновилось
|
||
|
||
#### 3. Повторное голосование
|
||
```bash
|
||
# Нажать другую кнопку
|
||
```
|
||
- [ ] Старый голос снялся
|
||
- [ ] Новый засчитался
|
||
- [ ] Всего голосов не изменилось
|
||
|
||
#### 4. Закрытие опроса
|
||
```bash
|
||
# Админ:
|
||
/poll_end 1
|
||
```
|
||
- [ ] Опрос закрыт
|
||
- [ ] Кнопки не работают
|
||
- [ ] Финальные результаты показаны
|
||
|
||
#### 5. Список опросов
|
||
```bash
|
||
/polls
|
||
```
|
||
- [ ] Показывает активные опросы
|
||
- [ ] Количество голосов верно
|
||
|
||
---
|
||
|
||
## 📁 Изменённые файлы
|
||
|
||
| Файл | Изменения |
|
||
|------|-----------|
|
||
| `database/models.py` | Добавлена модель `Poll` |
|
||
| `database/migrate_add_polls.py` | Миграция БД (создание таблицы) |
|
||
| `handlers/polls.py` | Новый хендлер (создание, голосование, результаты) |
|
||
| `keyboards/inline.py` | Кнопки для опросов |
|
||
| `handlers/__init__.py` | Импорт `polls_router` |
|
||
| `main.py` | Регистрация `polls_router` |
|
||
|
||
---
|
||
|
||
## 🚀 Как использовать
|
||
|
||
### Для админа:
|
||
|
||
1. **Создать опрос (быстро):**
|
||
```
|
||
/poll_create "Вопрос?" "Вариант 1" "Вариант 2" "Вариант 3"
|
||
```
|
||
|
||
2. **Создать опрос (пошагово):**
|
||
```
|
||
/poll_create
|
||
```
|
||
Далее следуй инструкциям бота.
|
||
|
||
3. **Закрыть опрос:**
|
||
```
|
||
/poll_end 1
|
||
```
|
||
(где `1` — номер опроса из ответа бота)
|
||
|
||
4. **Посмотреть опросы:**
|
||
```
|
||
/polls
|
||
```
|
||
|
||
### Для жильца:
|
||
|
||
1. **Проголосовать:**
|
||
- Нажать кнопку в сообщении с опросом
|
||
|
||
2. **Посмотреть результаты:**
|
||
- После голосования бот покажет результаты
|
||
- Или `/polls` — список активных
|
||
|
||
---
|
||
|
||
## 💡 Советы
|
||
|
||
### Хорошие вопросы:
|
||
✅ «За какой цвет покрасить подъезд?»
|
||
✅ «Когда провести субботник?»
|
||
✅ «Нужно ли видеонаблюдение?»
|
||
|
||
### Плохие вопросы:
|
||
❌ «Кто хороший?» (субъективно)
|
||
❌ «Голосуйте!» (нет вариантов)
|
||
|
||
### Лучшие практики:
|
||
- 3-5 вариантов — оптимально
|
||
- Варианты должны быть взаимно исключающими
|
||
- Закрывайте опрос когда голосов достаточно
|
||
|
||
---
|
||
|
||
## 🔧 Отладка
|
||
|
||
### Посмотреть опросы в БД:
|
||
```bash
|
||
cd /home/matrixhasyou/domovoy_bot
|
||
source venv/bin/activate
|
||
sqlite3 database/domovoy.db
|
||
|
||
SELECT * FROM polls ORDER BY created_at DESC LIMIT 10;
|
||
```
|
||
|
||
### Логи:
|
||
```bash
|
||
tail -f logs/bot.log | grep poll
|
||
```
|
||
|
||
### Ошибки:
|
||
- «Опрос не найден» — проверьте номер
|
||
- «Опрос уже закрыт» — используйте `/polls` для поиска активных
|
||
- «Нужно минимум 2 варианта» — добавьте ещё один
|
||
|
||
---
|
||
|
||
## ✅ Преимущества
|
||
|
||
| Было | Стало |
|
||
|------|-------|
|
||
| Опросы в словах | **Inline-кнопки** |
|
||
| Ручной подсчёт | **Автоматически** |
|
||
| Не видно кто голосовал | **Анонимно** |
|
||
| Нельзя поменять голос | **Можно переголосовать** |
|
||
| Нет истории | **Сохранение в БД** |
|
||
|
||
---
|
||
|
||
**Опросы готовы! 🎉**
|
||
|
||
*Следующий шаг: тестирование на тестовой группе и фиксация версии v1.1*
|