# 🦋 Fly-Fly Team Bot

Telegram-бот для детской игровой программы **«Ловец бабочек»** — образовательная игра с рейтингом, стаями и школой бабочковода для детей 9–12 лет.

Бот: [@fly_fly_team_bot](https://t.me/fly_fly_team_bot)

---

## 📋 Содержание

- [Описание](#описание)
- [Возможности](#возможности)
- [Архитектура проекта](#архитектура-проекта)
- [Установка](#установка)
- [Конфигурация](#конфигурация)
- [Запуск](#запуск)
- [Как пользоваться ботом](#как-пользоваться-ботом)
- [Система очков](#система-очков)
- [Школа бабочковода](#школа-бабочковода)
- [Стаи](#стаи)
- [Реферальная система](#реферальная-система)
- [Модерация фото](#модерация-фото)
- [Проверка подписки на группу](#проверка-подписки-на-группу)
- [База данных](#база-данных)
- [Зависимости](#зависимости)
- [Структура проекта](#структура-проекта)
- [Лицензия](#лицензия)

---

## Описание

**Fly-Fly Team Bot** — это Telegram-бот, который:

- Проводит детей через **5-урочную «Школу бабочковода»** с образовательными текстами и вопросами
- Позволяет создавать **стаи (команды)** и соревноваться в рейтинге
- Начисляет **очки** за прохождение школы, приглашение друзей и другие действия
- Проверяет **подписку на группу** Telegram перед доступом к функциям
- Отправляет **фото на модерацию** администратору для ручного начисления очков

---

## Возможности

| Возможность | Описание |
|---|---|
| 📚 **Школа бабочковода** | 5 уроков о бабочках с вопросами и объяснениями |
| 🦋 **Поймай друга** | Отправка GIF-анимации с реферальной ссылкой |
| 🏆 **Рейтинг** | Топ-10 пользователей и рейтинг стай |
| 📌 **Стая** | Создание/вступление в стаю, управление участниками |
| ⚙️ **Управление стаей** | Переименование, исключение участников, роспуск стаи |
| 📊 **Мои очки** | Персональная статистика + топ-10 ловцов |
| 🛒 **Бабочкарий** | Ссылка на покупку продукта |
| 🔒 **Проверка подписки** | Обязательная подписка на группу для доступа к функциям |
| 📸 **Модерация фото** | Фото → модератор → кнопки начисления 5/15 очков |
| 🎁 **Реферальный бонус** | +5 очков за каждого приглашённого друга |

---

## Архитектура проекта

```
main.py
  └── src/bot.py          # Основная логика бота (telebot)
        ├── database.py   # Работа с JSON-базой данных
        ├── school.py     # Учебная программа (5 вопросов)
        ├── admin_tools.py# Инструменты администратора
        └── utils.py      # Утилиты (валидаторы, форматирование)
  └── config/config.py    # Конфигурация (токен, очки, ID)
        └── .env          # Секреты (токен бота, ID группы)
```

**Ключевые технологии:**
- **pyTelegramBotAPI (telebot)** — библиотека для Telegram Bot API
- **JSON-файлы** — хранение данных пользователей
- **python-dotenv** — загрузка переменных окружения

---

## Установка

### 1. Клонирование репозитория

```bash
git clone <repository-url>
cd fly-fly-team-bot
```

### 2. Создание виртуального окружения

```bash
python -m venv venv
```

**Windows:**
```bash
venv\Scripts\activate
```

**Linux/macOS:**
```bash
source venv/bin/activate
```

### 3. Установка зависимостей

```bash
pip install pyTelegramBotAPI python-dotenv requests
```

### 4. Настройка конфигурации

```bash
# Скопируйте пример конфигурации
cp config/.env.example config/.env
# Или используйте корневой .env
cp .env.example .env
```

Заполните `.env` своими значениями (см. [Конфигурация](#конфигурация)).

---

## Конфигурация

### Переменные окружения (`.env`)

| Переменная | Описание | Пример |
|---|---|---|
| `TELEGRAM_BOT_TOKEN` | Токен бота от @BotFather | `123456:ABC-DEF...` |
| `ADMIN_ID` | Telegram ID администратора-модератора | `7665285886` |
| `REQUIRED_GROUP_CHAT_ID` | ID группы для проверки подписки | `-1002395700013` |
| `TELEGRAM_PROXY_URL` | Прокси для Telegram API (опционально) | `socks5://user:pass@host:port` |
| `TELEGRAM_CONNECT_TIMEOUT` | Таймаут подключения (сек) | `30` |
| `TELEGRAM_READ_TIMEOUT` | Таймаут чтения (сек) | `120` |
| `DEBUG` | Режим отладки | `False` |
| `LOG_LEVEL` | Уровень логирования | `INFO` |

### Константы системы (`config/config.py`)

| Константа | Значение | Описание |
|---|---|---|
| `POINTS_SCHOOL_COMPLETE` | `10` | Очков за прохождение школы |
| `POINTS_REFERRAL_BONUS` | `5` | Очков за приглашённого друга |
| `POINTS_BUTTERFLY_ACTIVATION` | `30` | Очков за активацию Бабочкария |
| `REQUIRED_GROUP_LINK` | `https://t.me/+2RjGyDueqqAyM2Ey` | Ссылка на группу |

---

## Запуск

### Основной способ

```bash
python main.py
```

### Альтернативный запуск (напрямую из src)

```bash
python -m src.bot
```

### Вывод при запуске

```
🦋 Бот Fly-Fly запущен!
🤖 @fly_fly_team_bot
Ожидаю сообщений...
```

### Остановка

`Ctrl+C` в терминале.

---

## Как пользоваться ботом

### Первый запуск

1. Пользователь отправляет `/start` боту
2. Бот создаёт профиль пользователя
3. Отправляется приветственное сообщение с требованием подписки на группу
4. Пользователь подписывается и отправляет **«Готово»**
5. Бот подтверждает участие в конкурсе

### Главное меню

| Кнопка | Описание |
|---|---|
| 📚 Школа бабочковода | Пройти 5 уроков (если не пройдено) |
| 🦋 Поймать друга | Отправить реферальную ссылку друзьям |
| 📊 Мои очки | Персональная статистика + топ-10 |
| 🏆 Рейтинг | Общий топ-10 ловцов |
| 📌 Стая | Информация о стае (если участник) |
| ⚙️ Управлять стаей | Управление (только капитан) |
| 🛒 Купить Бабочкарий | Ссылка на покупку |
| ❓ Справка | Правила игры |

---

## Система очков

| Действие | Очки |
|---|---|
| Прохождение школы | +10 ⭐ |
| Приглашение друга | +5 ⭐ |
| Фото одобрено модератором | +5 или +15 ⭐ |
| Активация Бабочкария | +30 ⭐ |

Очки суммируются и определяют позицию в рейтинге.

---

## Школа бабочковода

5 уроков о бабочках:

| Урок | Тема |
|---|---|
| 1 | Кто такие бабочки? (4 крыла) |
| 2 | Что едят бабочки? (хоботок) |
| 3 | Жизненный цикл бабочки (4 стадии) |
| 4 | Где живут бабочки? |
| 5 | Как стать ловцом бабочек? |

Каждый урок состоит из:
- **Обучающего текста** с интересными фактами
- **Вопроса** с 4 вариантами ответа
- **Объяснения** правильного/неправильного ответа

После прохождения всех 5 вопросов пользователь получает **+10 очков** и отметку `school_completed`.

---

## Стаи

### Создание стаи

> ⚠️ Возможность создания стаи отключена в текущей версии. Стаи создаются автоматически при определённых условиях.

### Вступление в стаю

Пользователь переходит по реферальной ссылке `/start <team_id>` и автоматически вступает в стаю.

### Управление стаей (капитан)

| Действие | Описание |
|---|---|
| ✏️ Изменить название | Переименовать стаю (до 30 символов) |
| 👥 Исключить участника | Удалить участника из стаи |
| 📊 Рейтинг участников | Внутренний рейтинг стаи |
| 🚫 Разойти стаю | Распустить стаю (все участники выходят) |

### Выход из стаи (участник)

Участник может покинуть стаю через меню **«📌 Стая → 🚪 Выйти из стаи»** с подтверждением.

**Капитан не может покинуть стаю** — только распустить её.

---

## Реферальная система

### Как работает

1. Пользователь нажимает **«🦋 Поймать друга»**
2. Получает GIF + реферальную ссылку вида:
   ```
   https://t.me/fly_fly_team_bot?start=<telegram_id>
   ```
3. Друг переходит по ссылке и регистрируется
4. Бот проверяет условия:
   - Пригласитель существует
   - Приглашённый ещё не учтён в `invited_friends`
   - Если задан `REQUIRED_GROUP_CHAT_ID` — приглашённый состоит в группе
5. Пригласителю начисляется **+5 очков**

### Проверка членства в группе

При реферальном начислении бот проверяет, что приглашённый является участником группы через `bot.get_chat_member()`.

---

## Модерация фото

### Процесс

1. Пользователь находится в состоянии `awaiting_photo` (ожидание фото)
2. Отправляет фото боту
3. Бот пересылает фото **администратору** (`ADMIN_ID`) с inline-кнопками:
   - **«Дать 15 баллов»** — начислить +15 очков
   - **«Дать 5 баллов»** — начислить +5 очков
   - **«Отклонить»** — отклонить фото
4. Администратор нажимает кнопку
5. Бот начисляет очки пользователю и уведомляет обоих

### Callback-данные кнопок

| Callback | Действие |
|---|---|
| `award_15_<user_id>` | Начислить 15 очков |
| `award_5_<user_id>` | Начислить 5 очков |
| `award_reject_<user_id>` | Отклонить фото |

---

## Проверка подписки на группу

### Механизм

Бот проверяет подписку пользователя на группу перед каждым действием:

```python
def is_user_subscribed(telegram_id, chat_id) -> bool:
    if not check_user_in_group(telegram_id):
        send_subscription_required(chat_id)
        return False
    return True
```

### Проверка членства

```python
def check_user_in_group(telegram_id) -> bool:
    member = bot.get_chat_member(REQUIRED_GROUP_CHAT_ID, telegram_id)
    return member.status in ['member', 'administrator', 'creator']
```

### Подтверждение подписки

Пользователь отправляет **«Готово»** — бот повторно проверяет подписку и подтверждает участие.

---

## База данных

### Тип: JSON-файл

Данные хранятся в `data/users.json` в формате:

```json
{
  "123456789": {
    "telegram_id": 123456789,
    "first_name": "Иван",
    "username": null,
    "is_butterfly_owner": false,
    "school_completed": true,
    "total_points": 45,
    "team_id": null,
    "team_name": null,
    "created_at": "2025-01-15T10:30:00",
    "last_activation_date": null,
    "invited_friends": [],
    "referred_by": 987654321,
    "profile_updated": false
  }
}
```

### Класс `Database`

| Метод | Описание |
|---|---|
| `get_user(telegram_id)` | Получить пользователя |
| `create_user(...)` | Создать пользователя |
| `update_user(telegram_id, **kwargs)` | Обновить данные |
| `add_points(telegram_id, points)` | Добавить очки |
| `get_team_members(team_id)` | Участники стаи |
| `get_users_ranking()` | Топ-10 пользователей |
| `get_teams_ranking()` | Топ-10 стай |
| `create_team(captain_id, team_name)` | Создать стаю |
| `get_team(team_id)` | Информация о стае |
| `add_member_to_team(team_id, user_id)` | Добавить в стаю |
| `remove_member_from_team(team_id, user_id)` | Удалить из стаи |
| `update_team_name(team_id, new_name)` | Переименовать стаю |
| `disband_team(team_id)` | Распустить стаю |
| `mark_school_completed(telegram_id)` | Отметить школу пройденной |

### Дополнительные файлы

- `data/points_log.json` — лог начислений очков (валидация повторных начислений)
- `data/teams.json` — данные о стаях (через `TeamManager`)

---

## Зависимости

| Пакет | Версия | Описание |
|---|---|---|
| `pyTelegramBotAPI` | любая | Telegram Bot API клиент |
| `python-dotenv` | любая | Загрузка .env файлов |
| `requests` | любая | HTTP-запросы (для прокси) |

---

## Структура проекта

```
fly-fly-team-bot/
├── main.py                    # Точка входа (запуск bot.infinity_polling())
├── README.md                  # Документация
├── bot-cat.mp4                # GIF-анимация для «Поймай друга»
├── bot-cat.gif                # GIF-анимация (альтернатива)
│
├── config/
│   ├── __init__.py            # Экспорт конфигурации
│   ├── config.py              # Загрузка .env и константы
│   ├── .env                   # Секреты (не коммитить!)
│   └── .env.example           # Пример конфигурации
│
├── src/
│   ├── __init__.py            # Экспорт bot и Database
│   ├── bot.py                 # Основная логика бота (~1140 строк)
│   ├── database.py            # Класс Database (модель данных, CRUD)
│   ├── school.py              # SCHOOL_CURRICULUM (5 вопросов)
│   ├── admin_tools.py         # AdminTools, DebugTools
│   └── utils.py               # PointsValidator, TeamManager, MessageFormatter
│
├── data/
│   ├── users.json             # База пользователей
│   └── points_log.json        # Лог начислений очков
│
└── docs/                      # Дополнительная документация
```

---

## Команды бота

| Команда | Описание |
|---|---|
| `/start` | Регистрация / приветствие |
| `/start 0` | Регистрация как владелец Бабочкария |
| `/start <id>` | Регистрация по реферальной ссылке |

---

## Обработчики сообщений

### Команды
- `/start` — регистрация

### Текстовые кнопки
- `📚 Школа бабочковода флай-флай` — начало школы
- `🦋 Поймать друга` — реферальная ссылка + GIF
- `📊 Мои очки` — статистика
- `🏆 Рейтинг` — топ-10
- `📌 Стая` — меню стаи
- `⚙️ Управлять стаей` — управление (капитан)
- `🛒 Купить Бабочкарий` — ссылка на покупку
- `❓ Справка` — правила игры
- `Готово` — подтверждение подписки

### Callback-запросы (inline-кнопки)
- `answer_<num>_<idx>` — ответ на вопрос школы
- `team_members`, `team_stats`, `team_link` — меню стаи
- `leave_team`, `leave_confirm`, `leave_cancel` — выход из стаи
- `award_15_<id>`, `award_5_<id>`, `award_reject_<id>` — модерация фото
- `manage_rename`, `manage_remove`, `manage_rating`, `manage_disband` — управление стаей
- `remove_<user_id>` — исключить участника
- `disband_confirm` — подтвердить роспуск
- `back_menu`, `back_to_main`, `back_to_main_menu` — назад

### Контент
- **Фото** — пересылка модератору (если ожидается фото)

---

## Лицензия

© Fly-Fly Team. Все права защищены.
