2025-11-10 23:55:41 +00:00
|
|
|
|
# Telegram Bot Share Image Feature Plan
|
|
|
|
|
|
|
|
|
|
|
|
## Objetivo
|
|
|
|
|
|
Добавить в телеграм-бота команду `/share` которая генерирует красивое сообщение и изображение для приглашения друзей использовать бот и приложение.
|
|
|
|
|
|
|
|
|
|
|
|
## Требования
|
|
|
|
|
|
|
|
|
|
|
|
### 1. **Ограничение частоты запросов**
|
|
|
|
|
|
- Максимум 1 сообщение на пользователя в день
|
|
|
|
|
|
- Лимит должен быть настраиваемым через переменные окружения или config
|
|
|
|
|
|
- Хранение последних запросов пользователей в Isar БД
|
|
|
|
|
|
|
|
|
|
|
|
### 2. **Получение исходной карточки**
|
|
|
|
|
|
- Случайный выбор карточки из бэкенда (из всех доступных карточек)
|
|
|
|
|
|
- Получение через Isar (DBManager будет иметь доступ к карточкам через `isar.gameCardModels`)
|
|
|
|
|
|
- Если нет карточек, использовать placeholder или default изображение
|
|
|
|
|
|
|
|
|
|
|
|
### 3. **Обработка изображения**
|
|
|
|
|
|
- Загрузка оригинального PNG изображения карточки из файловой системы бэкенда
|
|
|
|
|
|
- Добавление красивой рамки вокруг изображения
|
|
|
|
|
|
- Размер рамки: ~30-50px с обеих сторон
|
|
|
|
|
|
- Цвет рамки: тёмный или с градиентом (TBD в процессе разработки)
|
|
|
|
|
|
- Замена текста на карточке или добавление наложения с названием приложения "mnemo cards"
|
|
|
|
|
|
|
|
|
|
|
|
### 4. **Формирование сообщения**
|
|
|
|
|
|
- Текст без эмодзи
|
|
|
|
|
|
- Включение referral code пользователя
|
|
|
|
|
|
- Профессиональный, дружеский тон
|
|
|
|
|
|
- Примерный формат:
|
|
|
|
|
|
```
|
|
|
|
|
|
Приветствую! Я тестирую приложение mnemo cards для изучения языков.
|
|
|
|
|
|
|
|
|
|
|
|
Присоединяйся и начни учиться вместе со мной!
|
|
|
|
|
|
|
|
|
|
|
|
Referral code: [CODE_HERE]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. **Отправка результата**
|
|
|
|
|
|
- Отправить сообщение с текстом
|
|
|
|
|
|
- Отправить сгенерированное изображение к сообщению
|
|
|
|
|
|
- Удобство: в одном сообщении или отдельно (TBD)
|
|
|
|
|
|
|
|
|
|
|
|
## Архитектура решения
|
|
|
|
|
|
|
|
|
|
|
|
### Структура данных Isar
|
|
|
|
|
|
```dart
|
|
|
|
|
|
// Для отслеживания количества поделиться за день
|
|
|
|
|
|
class ShareRequestModel {
|
|
|
|
|
|
Id? id;
|
|
|
|
|
|
late String telegramUserId;
|
|
|
|
|
|
late DateTime requestedAt;
|
|
|
|
|
|
|
|
|
|
|
|
// Возможные поля для будущего аналитика
|
|
|
|
|
|
late String? generatedCardId;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Компоненты для реализации
|
|
|
|
|
|
|
|
|
|
|
|
#### 1. **ImageGenerator** (`lib/image_generator.dart`)
|
|
|
|
|
|
Класс для генерации изображения с рамкой
|
|
|
|
|
|
- `Future<List<int>> generateShareImage(GameCardModel card)` - генерирует PNG с рамкой
|
|
|
|
|
|
- Использует `image` package для обработки изображений
|
|
|
|
|
|
- Работает с файловой системой для чтения оригинальных карточек
|
|
|
|
|
|
|
|
|
|
|
|
#### 2. **ReferralCodeManager** (в `db_manager.dart`)
|
|
|
|
|
|
Методы для работы с referral кодами
|
|
|
|
|
|
- `Future<String> getUserReferralCode(String telegramUserId)` - получить или сгенерировать код
|
|
|
|
|
|
- Хранение в Isar или вызов бэкенда
|
|
|
|
|
|
|
|
|
|
|
|
#### 3. **ShareRateLimiter** (в `db_manager.dart`)
|
|
|
|
|
|
Контроль частоты запросов
|
|
|
|
|
|
- `Future<bool> canShareToday(String telegramUserId)` - проверка лимита
|
|
|
|
|
|
- `Future<void> recordShareRequest(String telegramUserId, int? cardId)` - сохранение запроса
|
|
|
|
|
|
- Конфигурируемый лимит (дефолт 1 раз в день)
|
|
|
|
|
|
|
|
|
|
|
|
#### 4. **ShareCommand** (в `main.dart`)
|
|
|
|
|
|
Новая команда `/share`
|
|
|
|
|
|
- Обработка команды в `teledart.onCommand('share')`
|
|
|
|
|
|
- Проверка лимита
|
|
|
|
|
|
- Получение случайной карточки
|
|
|
|
|
|
- Генерация изображения
|
|
|
|
|
|
- Отправка сообщения с изображением
|
|
|
|
|
|
|
|
|
|
|
|
## Этапы реализации
|
|
|
|
|
|
|
|
|
|
|
|
### Этап 1: Подготовка инфраструктуры
|
|
|
|
|
|
1. Добавить зависимость `image: ^4.0.0` в pubspec.yaml
|
|
|
|
|
|
2. Создать миграцию Isar: добавить `ShareRequestModel`
|
|
|
|
|
|
3. Расширить `DBManager` методами для율 лимитирования и referral кодов
|
|
|
|
|
|
|
|
|
|
|
|
### Этап 2: Реализация обработки изображений
|
|
|
|
|
|
1. Создать `ImageGenerator` класс
|
|
|
|
|
|
2. Реализовать:
|
|
|
|
|
|
- Загрузку карточки из файловой системы
|
|
|
|
|
|
- Добавление рамки
|
|
|
|
|
|
- Добавление текста с названием приложения
|
|
|
|
|
|
3. Написать unit тесты
|
|
|
|
|
|
|
|
|
|
|
|
### Этап 3: Реализация rate limiting
|
|
|
|
|
|
1. Реализовать методы в `DBManager`
|
|
|
|
|
|
2. Написать unit тесты
|
|
|
|
|
|
|
|
|
|
|
|
### Этап 4: Реализация команды /share
|
|
|
|
|
|
1. Добавить команду в `main.dart`
|
|
|
|
|
|
2. Интегрировать все компоненты
|
|
|
|
|
|
3. Обработка ошибок
|
|
|
|
|
|
|
|
|
|
|
|
### Этап 5: Конфигурация
|
|
|
|
|
|
1. Добавить переменные окружения
|
|
|
|
|
|
2. Обновить `BotConfig`
|
|
|
|
|
|
3. Документация
|
|
|
|
|
|
|
|
|
|
|
|
### Этап 6: Тестирование и отладка
|
|
|
|
|
|
1. Ручное тестирование в Telegram
|
|
|
|
|
|
2. Проверка лимитирования
|
|
|
|
|
|
3. Проверка качества изображения
|
|
|
|
|
|
|
|
|
|
|
|
## Переменные окружения
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Количество поделиться в день (дефолт: 1)
|
|
|
|
|
|
BOT_SHARE_DAILY_LIMIT=1
|
|
|
|
|
|
|
|
|
|
|
|
# Путь к бэкенду для получения referral кода (опционально)
|
2025-11-16 16:31:22 +00:00
|
|
|
|
BACKEND_URL=http://localhost:8443
|
2025-11-10 23:55:41 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Возможные улучшения (Future)
|
|
|
|
|
|
- Выбор темы рамки (светлая/тёмная)
|
|
|
|
|
|
- Кастомизация текста приложения
|
|
|
|
|
|
- Сохранение сгенерированных изображений для кэширования
|
|
|
|
|
|
- Аналитика использования feature
|
|
|
|
|
|
- Поддержка мультиязычного текста
|
|
|
|
|
|
|
|
|
|
|
|
## Технические заметки
|
|
|
|
|
|
|
|
|
|
|
|
### Получение случайной карточки
|
|
|
|
|
|
```dart
|
|
|
|
|
|
final allCards = await isar.gameCardModels.where().findAll();
|
|
|
|
|
|
final random = Random();
|
|
|
|
|
|
final card = allCards[random.nextInt(allCards.length)];
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Пути к изображениям
|
|
|
|
|
|
- Оригинальные изображения хранятся в: `../mnemo_cards_backend/data/cards/`
|
|
|
|
|
|
- Имя файла в карточке: `GameCardModel.image` (например: "1234_word.png")
|
|
|
|
|
|
|
|
|
|
|
|
### Обработка изображений в Dart
|
|
|
|
|
|
- Package `image` для обработки PNG
|
|
|
|
|
|
- Методы: `copyResize()`, `drawString()`, `drawRect()` и т.д.
|
|
|
|
|
|
- Примеры использования есть в `mnemo_cards_backend/lib/packs/pack_manager.dart`
|
|
|
|
|
|
|
|
|
|
|
|
## Деньги на: Quality Assurance
|
|
|
|
|
|
- Проверить работу при отсутствии карточек
|
|
|
|
|
|
- Проверить работу при отсутствии файла изображения
|
|
|
|
|
|
- Проверить корректность rate limiting через несколько дней
|
|
|
|
|
|
- Проверить качество генерируемого изображения на мобильных устройствах
|
|
|
|
|
|
- Проверить производительность при работе с большим количеством карточек
|
|
|
|
|
|
|