50 KiB
| name | overview | todos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Telegram Bot Product Features | Добавление продуктовых фич в Telegram бот для повышения вовлеченности пользователей и создания привычки ежедневного обучения. Фокус на простых, но эффективных механиках для MVP стадии. |
|
План продуктовых фич для Telegram бота Mnemo Cards
Обзор
Текущий бот выполняет технические функции (бэкап, авторизация, админ-панель) и имеет базовую команду /share. Предлагается добавить продуктовые фичи для вовлечения и контента, которые помогут:
- Создать привычку ежедневного использования
- Повысить удержание пользователей
- Предоставить дополнительную ценность помимо основного приложения
- Собрать аналитику вовлеченности
Приоритетные фичи (MVP)
1. 🎴 Карточка дня (/daily команда)
Описание: Пользователь получает случайную карточку для изучения
UX Flow:
Пользователь: /daily
Бот:
[Красивое изображение карточки]
🇪🇸 el perro
🇷🇺 собака
💡 Мнемоника: [mnemo text]
🔊 Транскрипция: [transcription]
Хочешь проверить себя? Нажми /quiz
Реализация:
- Новая команда в
bin/main.dart→teledart.onCommand('daily') - Использовать существующий
BackendClient.getRandomCard() - Повторно использовать
ImageGeneratorиз/shareкоманды - Отправлять фото + caption с информацией о карточке
Backend изменения:
- Endpoint уже есть:
/api/v2/telegram-bot/random-card - Добавить опциональный параметр
?userId=для персонализации (учитывать уже изученные карточки)
2. 📊 Статистика и стрики (/stats команда)
Описание: Показать пользователю его прогресс и мотивационные метрики
UX Flow:
Пользователь: /stats
Бот:
📈 Твоя статистика
🔥 Стрик: 7 дней
📚 Изучено карточек: 42
✅ Завершено тестов: 5
⏱ Последняя активность: 2 часа назад
Так держать! Продолжай в том же духе! 💪
Реализация:
- Новая команда
/statsвbin/main.dart - Новый метод в
lib/backend_client.dart:Future<UserStats?> getUserStats(String telegramUserId)
Backend изменения:
- Новый endpoint:
GET /api/v2/telegram-bot/users/:telegramUserId/stats - Использовать существующую логику из
lib/statistics/statistics_calculator.dart - Добавить tracking стриков (consecutive days of activity)
- Новая таблица
user_streaksв PostgreSQL:CREATE TABLE user_streaks ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), telegram_user_id TEXT, current_streak INTEGER DEFAULT 0, longest_streak INTEGER DEFAULT 0, last_activity_date DATE, created_at TIMESTAMP DEFAULT NOW() );
3. ⏰ Ежедневные напоминания
Описание: Бот отправляет напоминание о занятиях в выбранное время
UX Flow:
Пользователь: /reminders
Бот:
⏰ Настрой напоминания
[Inline keyboard:]
- 09:00 утра
- 12:00 день
- 18:00 вечер
- 21:00 ночь
- 🚫 Отключить
После выбора:
Бот: ✅ Буду напоминать тебе каждый день в 18:00!
---
В выбранное время:
Бот:
👋 Время изучать новые слова!
Попробуй карточку дня → /daily
Или пройди быстрый квиз → /quiz
Реализация:
- Новая команда
/remindersс inline keyboard (используяteledart.sendMessageсreplyMarkup) - Хранение настроек в БД (новая таблица
user_reminder_settings) - Cron job в
lib/cron/для отправки напоминаний:// lib/cron/send_reminders.dart class SendRemindersTask extends Task { @override String get name => 'Send Reminders'; @override Duration get interval => const Duration(minutes: 30); @override Future<void> run() async { // Проверять каждые 30 минут, кому нужно отправить // Отправлять через Telegram Bot API } }
Backend изменения:
- Новый endpoint:
POST /api/v2/telegram-bot/reminders/set - Новый endpoint:
GET /api/v2/telegram-bot/reminders/pending - Новая таблица:
CREATE TABLE user_reminder_settings ( id SERIAL PRIMARY KEY, telegram_user_id TEXT UNIQUE, reminder_time TIME, -- время в UTC timezone TEXT, -- часовой пояс пользователя enabled BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW() );
4. 🎯 Мини-квиз (/quiz команда)
Описание: Быстрая проверка знаний из 3-5 вопросов прямо в боте
UX Flow:
Пользователь: /quiz
Бот:
🎯 Быстрый квиз
Вопрос 1/3
Как переводится "el perro"?
[Inline keyboard:]
A) кошка
B) собака ✅
C) птица
D) рыба
После ответа:
Бот:
✅ Правильно! (или ❌ Неправильно, правильный ответ: собака)
[Следующий вопрос...]
После завершения:
Бот:
🎉 Квиз завершен!
Правильных ответов: 2/3
Твой результат: 67%
Продолжай практиковаться → /daily
Реализация:
- Новая команда
/quizс inline keyboard - Состояние квиза хранить в памяти (Map с ключом chat_id)
- Использовать
teledart.onCallbackQueryдля обработки нажатий кнопок - Генерировать вопросы на бэкенде:
- Правильный ответ
- 3 неправильных варианта из других карточек
Backend изменения:
-
Новый endpoint:
POST /api/v2/telegram-bot/quiz/generate- Параметр:
userId(опционально, для персонализации) - Параметр:
count(количество вопросов, default: 3)
- Параметр:
-
Endpoint возвращает:
{ "quizId": "uuid", "questions": [ { "questionId": "uuid", "question": "Как переводится 'el perro'?", "options": ["кошка", "собака", "птица", "рыба"], "correctIndex": 1 } ] } -
Новый endpoint:
POST /api/v2/telegram-bot/quiz/submit- Записывать результаты квиза для статистики
5. 🎊 Мотивационные события (автоматические)
Описание: Бот автоматически поздравляет с достижениями
События:
- 🔥 Стрик 3 дня: "Отличное начало! Продолжай в том же духе!"
- 🔥 Стрик 7 дней: "Целая неделя! Ты молодец! 🎉"
- 🔥 Стрик 14 дней: "Две недели ежедневных занятий! Потрясающе!"
- 🔥 Стрик 30 дней: "Месяц без перерывов! Ты легенда! 🏆"
- 📚 Изучено 10/50/100 карточек
- ✅ Завершено 5/10/20 тестов
Реализация:
- Webhook или cron job для проверки достижений
- Новый cron task:
CheckAchievementsTaskкаждый час - При достижении milestone → отправить сообщение пользователю
Backend изменения:
-
Новая таблица
user_achievements:CREATE TABLE user_achievements ( id SERIAL PRIMARY KEY, telegram_user_id TEXT, achievement_type TEXT, -- 'streak_3', 'streak_7', 'cards_10', etc. achieved_at TIMESTAMP DEFAULT NOW(), notified BOOLEAN DEFAULT false ); -
Endpoint для получения новых достижений:
GET /api/v2/telegram-bot/achievements/pending
6. 🃏 Коллекционные карточки (Collectible Cards System)
Описание: Система коллекционирования карточек с разными уровнями редкости. Одно и то же слово может иметь несколько вариантов карточек с разными изображениями и редкостью.
Концепция редкости
Три уровня редкости:
-
🟢 Common (Обычная)
- Базовое изображение карточки
- Серая рамка
- Получение: автоматически при изучении слова или через
/daily
-
🔵 Rare (Редкая)
- Улучшенное/детальное изображение
- Синяя рамка с эффектом свечения
- Получение: за достижения (стрик 7 дней, квиз 100%, и т.д.)
-
🟣 Legendary (Легендарная)
- Уникальное артовое изображение
- Золотая рамка с блеском и эффектами
- Получение: за высокие достижения (стрик 30+ дней, особые награды)
Пример: слово "el perro"
el perro (собака)
├─ 🟢 Common ✅ Получена 15.12.2024
├─ 🔵 Rare ✅ Получена 20.12.2024 (стрик 7 дней)
└─ 🟣 Legendary 🔒 Требуется: стрик 30 дней (текущий: 12)
UX Flow
Команда /collection - просмотр коллекции:
Пользователь: /collection
Бот:
📚 Твоя коллекция
📊 Общий прогресс: 45/450 карточек (10%)
🟢 Common: 15/150 слов (10%)
🔵 Rare: 8/150 слов (5%)
🟣 Legendary: 2/150 слов (1%)
[Inline keyboard:]
- 📖 По словам
- 🎨 По редкости
- 📦 По пакам
- 🔍 Поиск слова
При выборе "По словам":
🇪🇸 Испанский (15 слов)
📝 el perro (собака)
✅🟢 ✅🔵 🔒🟣
📝 el gato (кот)
✅🟢 🔒🔵 🔒🟣
📝 la casa (дом)
✅🟢 🔒🔵 🔒🟣
[Кнопка: Показать детали]
Команда /showcase [слово] - детали карточки:
Пользователь: /showcase el perro
Бот:
[Отправляет изображение Common версии с серой рамкой]
🟢 COMMON
🇪🇸 el perro
🇷🇺 собака
✅ В коллекции с 15.12.2024
[Отправляет изображение Rare версии с синей рамкой]
🔵 RARE
🇪🇸 el perro
🇷🇺 собака
✅ Получена за стрик 7 дней (20.12.2024)
[Placeholder для Legendary]
🟣 LEGENDARY
🇪🇸 el perro
🇷🇺 собака
🔒 Как получить: стрик 30 дней
📊 Твой прогресс: 12/30 дней (осталось 18)
Обновленная команда /daily с коллекционированием:
Пользователь: /daily
Бот:
[Красивое изображение карточки с рамкой редкости]
🎴 Карточка дня
🇪🇸 el perro
🇷🇺 собака
💡 Мнемоника: [текст]
🔊 Транскрипция: [текст]
📦 Коллекция:
✅ 🟢 Common - уже в коллекции
🔒 🔵 Rare - пройди квиз на 100%
🔒 🟣 Legendary - стрик 30 дней
Хочешь проверить себя? → /quiz
Посмотреть коллекцию → /collection
Получение редкой карточки (событие):
[После достижения стрика 7 дней]
Бот:
🎉 ПОЗДРАВЛЯЕМ!
🔥 Ты держишь стрик 7 дней подряд!
🎁 Награда: случайная RARE карточка!
[Анимация/эффект открытия "пака"]
[Задержка 1-2 секунды]
[Отправляет изображение с синей рамкой и блеском]
✨ 🔵 RARE CARD! ✨
🇪🇸 el perro
🇷🇺 собака
Это улучшенная версия карточки!
Теперь у тебя 2/3 версии этого слова!
Посмотри свою коллекцию → /collection
Обновленная команда /stats с коллекцией:
Пользователь: /stats
Бот:
📈 Твоя статистика
🔥 Стрик: 12 дней
📚 Изучено слов: 42
✅ Завершено тестов: 5
📦 Коллекция карточек:
🟢 Common: 42/150 (28%)
🔵 Rare: 8/150 (5%)
🟣 Legendary: 2/150 (1%)
🏆 Ближайшие награды:
- 🔥 Стрик 14 дней → 1 Rare карточка (через 2 дня)
- 🔥 Стрик 30 дней → 1 Legendary! (через 18 дней)
- 🎯 Квиз 100% → Rare версия карточки из квиза
Продолжай в том же духе! 💪
Условия получения карточек
🟢 Common (автоматически):
- Изучил слово в основном приложении
- Получил через
/daily(первый раз) - Прошел тест, где встретилось слово
🔵 Rare (за активность):
- 🔥 Стрик 7 дней → 1 случайная Rare
- 🔥 Стрик 14 дней → 2 случайные Rare
- 🎯 Квиз 100% правильных → Rare версия одной карточки из квиза
- 📅 Использовал
/daily10 раз → выбери любую Rare - ⭐ Завершил пак полностью → все карточки пака в Rare версии
- 📚 Изучил 50 карточек → 3 Rare на выбор
🟣 Legendary (за высокие достижения):
- 🔥 Стрик 30 дней → 1 случайная Legendary
- 🔥 Стрик 60 дней → 2 случайные Legendary
- 🔥 Стрик 100 дней → 5 Legendary на выбор
- 🎯 Прошел 50 квизов → 1 Legendary на выбор
- 🎯 10 квизов подряд на 100% → 2 Legendary
- 📚 Завершил 5 паков → 3 Legendary на выбор
- 🏆 Топ-10 в месячном рейтинге активности → 2 Legendary
Визуальные отличия
Генерация изображений с разными рамками:
// Обновленный ImageGenerator
class ImageGenerator {
Future<Uint8List?> generateCardImage({
required GameCardModel card,
required CardRarity rarity,
}) async {
final baseImage = await _loadCardImage(card.image);
final frame = _getFrameForRarity(rarity);
final effects = _getEffectsForRarity(rarity);
return _composeImage(baseImage, frame, effects);
}
FrameStyle _getFrameForRarity(CardRarity rarity) {
switch (rarity) {
case CardRarity.common:
return FrameStyle(
color: 0xFF808080, // Серый
width: 40,
glowIntensity: 0,
);
case CardRarity.rare:
return FrameStyle(
color: 0xFF4169E1, // Синий
width: 50,
glowIntensity: 0.3,
glowColor: 0xFF6495ED,
);
case CardRarity.legendary:
return FrameStyle(
color: 0xFFFFD700, // Золотой
width: 60,
glowIntensity: 0.6,
glowColor: 0xFFFFA500,
sparkles: true,
gradient: true,
);
}
}
}
Цветовая схема:
- 🟢 Common: #808080 (серый)
- 🔵 Rare: #4169E1 (royal blue) + свечение
- 🟣 Legendary: #FFD700 (золотой) + градиент + блестки
Социальный аспект
Команда /share_card [слово] - поделиться карточкой:
Пользователь: /share_card el perro
Бот:
Какую версию карточки хочешь показать?
[Inline keyboard:]
- 🟢 Common
- 🔵 Rare ✅
- 🟣 Legendary 🔒
После выбора Rare:
[Генерирует красивое изображение с синей рамкой]
Вот твоя RARE карточка! 🔵
Ты можешь поделиться ей:
- Отправь друзьям в Telegram
- Опубликуй в соц. сетях
💬 Сообщение для друзей:
"Смотри какую редкую карточку я собрал в Mnemo Cards! 🔵
Присоединяйся и собери свою коллекцию!
[ссылка на бота]"
Техническая реализация
Новые таблицы PostgreSQL:
-- Варианты карточек (все возможные collectibles)
CREATE TABLE card_variants (
id SERIAL PRIMARY KEY,
card_id TEXT NOT NULL, -- ID основной карточки
rarity TEXT NOT NULL, -- 'common', 'rare', 'legendary'
image_variant TEXT, -- Путь к альтернативному изображению
-- Если NULL, используется базовое с рамкой
frame_color TEXT NOT NULL, -- HEX цвет рамки
frame_width INTEGER DEFAULT 40, -- Ширина рамки в px
has_glow BOOLEAN DEFAULT false, -- Эффект свечения
has_sparkles BOOLEAN DEFAULT false, -- Эффект блесток
unlock_condition TEXT, -- Условие получения
description TEXT, -- Описание варианта
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(card_id, rarity)
);
CREATE INDEX idx_variants_card_id ON card_variants(card_id);
CREATE INDEX idx_variants_rarity ON card_variants(rarity);
-- Коллекция пользователя
CREATE TABLE user_card_collection (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT NOT NULL,
card_variant_id INTEGER REFERENCES card_variants(id),
obtained_at TIMESTAMP DEFAULT NOW(),
obtained_via TEXT, -- 'daily', 'quiz', 'streak_7', 'achievement', etc.
UNIQUE(telegram_user_id, card_variant_id)
);
CREATE INDEX idx_collection_user ON user_card_collection(telegram_user_id);
CREATE INDEX idx_collection_obtained ON user_card_collection(obtained_at);
-- Прогресс коллекции (кэш для быстрого доступа)
CREATE TABLE user_collection_progress (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT UNIQUE NOT NULL,
total_cards INTEGER DEFAULT 0,
common_count INTEGER DEFAULT 0,
rare_count INTEGER DEFAULT 0,
legendary_count INTEGER DEFAULT 0,
updated_at TIMESTAMP DEFAULT NOW()
);
Backend endpoints:
GET /api/v2/telegram-bot/collection/:telegramUserId
- Получить коллекцию пользователя
- Query params: ?rarity=common|rare|legendary, ?pack_id=X
POST /api/v2/telegram-bot/collection/add
- Добавить карточку в коллекцию
- Body: { telegramUserId, cardId, rarity, obtainedVia }
GET /api/v2/telegram-bot/card-variants/:cardId
- Получить все варианты карточки (common, rare, legendary)
GET /api/v2/telegram-bot/collection/:telegramUserId/progress
- Получить статистику коллекции
POST /api/v2/telegram-bot/collection/award-rare
- Наградить случайной rare карточкой
- Body: { telegramUserId, reason }
POST /api/v2/telegram-bot/collection/award-legendary
- Наградить legendary карточкой
- Body: { telegramUserId, cardId (optional), reason }
Изменения в боте:
mnemo_cards_telegram_bot/
├── lib/
│ ├── backend_client.dart [ОБНОВИТЬ]
│ │ + getCollection()
│ │ + getCardVariants()
│ │ + addToCollection()
│ │ + getCollectionProgress()
│ │ + awardRareCard()
│ │ + awardLegendaryCard()
│ │
│ ├── image_generator.dart [ОБНОВИТЬ]
│ │ + generateCardImage(card, rarity)
│ │ + _getFrameForRarity()
│ │ + _addGlowEffect()
│ │ + _addSparkles()
│ │
│ └── models/
│ ├── card_rarity.dart [НОВЫЙ]
│ ├── card_variant.dart [НОВЫЙ]
│ └── user_collection.dart [НОВЫЙ]
│
└── bin/
└── main.dart [ОБНОВИТЬ]
+ onCommand('collection')
+ onCommand('showcase')
+ onCommand('share_card')
+ обновить onCommand('daily') - показывать прогресс коллекции
+ обновить onCommand('stats') - добавить статистику коллекции
Изменения в бэкенде:
mnemo_cards_backend/
├── lib/
│ ├── api/v2/
│ │ └── telegram_bot_api_v2.dart [ОБНОВИТЬ]
│ │ + GET /telegram-bot/collection/:id
│ │ + POST /telegram-bot/collection/add
│ │ + GET /telegram-bot/card-variants/:cardId
│ │ + POST /telegram-bot/collection/award-rare
│ │ + POST /telegram-bot/collection/award-legendary
│ │
│ ├── database/tables/
│ │ ├── card_variants.dart [НОВЫЙ]
│ │ ├── user_card_collection.dart [НОВЫЙ]
│ │ └── user_collection_progress.dart [НОВЫЙ]
│ │
│ ├── collection/
│ │ ├── collection_manager.dart [НОВЫЙ]
│ │ │ - Логика добавления карточек
│ │ │ - Проверка условий unlock
│ │ │ - Награждение карточками
│ │ │
│ │ └── rarity_calculator.dart [НОВЫЙ]
│ │ - Определение редкости при награждении
│ │ - Случайный выбор карточек для наград
│ │
│ └── cron/
│ └── collection_rewards.dart [НОВЫЙ]
- Автоматическое награждение за стрики/достижения
- Интеграция с системой достижений
Геймификация и мотивация
Прогресс-системы:
-
Коллекционирование по пакам:
- "Собери все Common карточки пака 'Животные'" → награда: 1 Rare любой карточки пака
- "Собери все Rare карточки пака" → награда: 1 Legendary из пака
-
Коллекционирование по редкости:
- "Собери 10 Rare карточек" → награда: 1 Legendary на выбор
- "Собери первую Legendary" → достижение + особая награда
-
Тематические коллекции:
- "Собери все карточки с животными" → награда
- "Собери все карточки с едой" → награда
Лидерборд коллекционеров (опционально):
Команда: /leaderboard collection
Бот:
🏆 Топ коллекционеров
🥇 @username1 - 145/450 (32%)
🟣 15 Legendary
🥈 @username2 - 132/450 (29%)
🟣 12 Legendary
🥉 @username3 - 128/450 (28%)
🟣 10 Legendary
...
🔹 Ты - #15 - 45/450 (10%)
🟣 2 Legendary
Канал (если будет)
Еженедельный пост "Карточка недели":
🌟 КАРТОЧКА НЕДЕЛИ
[Изображение Legendary карточки с золотой рамкой]
🟣 LEGENDARY
🇪🇸 el perro (собака)
Это одна из самых популярных легендарных карточек!
💎 Как получить:
- 🔥 Стрик 30 дней
- 🎯 Завершить 3 пака подряд
📊 Статистика:
- У 5% пользователей есть эта карточка
- Средний срок получения: 45 дней
Сколько Legendary карточек у тебя? 👇
Событие "Редкие выходные":
🎉 СОБЫТИЕ: РЕДКИЕ ВЫХОДНЫЕ!
В эти выходные (23-24 декабря):
- 🔵 Шанс получить Rare увеличен вдвое!
- 🎁 Каждый квиз на 80%+ даёт Rare карточку
- 🎯 /daily даёт Rare вместо Common
Не упусти шанс! Время ограничено! ⏰
Дальнейшее развитие (Phase 3)
Обмен карточками между пользователями:
/trade @username
- Предложить обмен: 2 твои Rare на 1 его Rare
- Система подтверждения обмена
- История обменов
Крафтинг (объединение карточек):
/craft el perro
- 3 Common → 1 Rare (того же слова)
- 3 Rare → 1 Legendary
- Требует "пыль" (dust) - получаешь за дубликаты
Сезонные/тематические карточки:
- Новогодние версии (декабрь)
- Летние версии (июль-август)
- Halloween версии (октябрь)
- Ограниченное время получения
Дополнительные фичи (Phase 2)
7. 📢 Telegram канал (опционально)
Если канал будет создан, можно автоматизировать:
Карточка дня в канале:
- Автопостинг красивого изображения с карточкой в канал каждый день в 9:00
- Использовать
ImageGenerator+Telegram.sendPhoto - Реализация: новый cron task
PostDailyCardTask
Еженедельные итоги:
- Каждое воскресенье пост с статистикой:
- Количество активных пользователей за неделю
- Самые популярные карточки
- Мотивационное сообщение
Технические детали
Структура проекта
Изменения в боте:
mnemo_cards_telegram_bot/
├── lib/
│ ├── backend_client.dart [ОБНОВИТЬ]
│ │ + getUserStats()
│ │ + generateQuiz()
│ │ + submitQuiz()
│ │ + setReminder()
│ │ + getPendingReminders()
│ │ + getPendingAchievements()
│ │ + getCollection() [НОВЫЙ - для коллекционных карточек]
│ │ + getCardVariants() [НОВЫЙ]
│ │ + addToCollection() [НОВЫЙ]
│ │ + getCollectionProgress() [НОВЫЙ]
│ │ + getPendingCardRewards() [НОВЫЙ]
│ │
│ ├── bot_config.dart [БЕЗ ИЗМЕНЕНИЙ]
│ │
│ ├── image_generator.dart [ОБНОВИТЬ]
│ │ + generateCardImage(card, rarity) [НОВЫЙ]
│ │ + _getFrameForRarity() [НОВЫЙ]
│ │ + _addGlowEffect() [НОВЫЙ]
│ │ + _addSparklesEffect() [НОВЫЙ]
│ │
│ ├── quiz_manager.dart [НОВЫЙ]
│ │ - In-memory state для активных квизов
│ │ - Логика генерации inline keyboards
│ │
│ └── models/ [НОВАЯ ПАПКА]
│ ├── card_rarity.dart [НОВЫЙ]
│ ├── card_variant.dart [НОВЫЙ]
│ └── user_collection.dart [НОВЫЙ]
│
└── bin/
└── main.dart [ОБНОВИТЬ]
+ onCommand('daily')
+ onCommand('stats')
+ onCommand('reminders')
+ onCommand('quiz')
+ onCommand('collection') [НОВЫЙ]
+ onCommand('showcase') [НОВЫЙ]
+ onCommand('share_card') [НОВЫЙ]
+ onCallbackQuery (для квизов, напоминаний, коллекции)
Изменения в бэкенде:
mnemo_cards_backend/
├── lib/
│ ├── api/v2/
│ │ └── telegram_bot_api_v2.dart [НОВЫЙ]
│ │ + GET /telegram-bot/users/:id/stats
│ │ + POST /telegram-bot/quiz/generate
│ │ + POST /telegram-bot/quiz/submit
│ │ + POST /telegram-bot/reminders/set
│ │ + GET /telegram-bot/reminders/pending
│ │ + GET /telegram-bot/achievements/pending
│ │ + GET /telegram-bot/collection/:id [НОВЫЙ]
│ │ + POST /telegram-bot/collection/add [НОВЫЙ]
│ │ + GET /telegram-bot/card-variants/:cardId [НОВЫЙ]
│ │ + GET /telegram-bot/collection/:id/progress [НОВЫЙ]
│ │ + POST /telegram-bot/collection/award-rare [НОВЫЙ]
│ │ + POST /telegram-bot/collection/award-legendary [НОВЫЙ]
│ │ + GET /telegram-bot/rewards/pending [НОВЫЙ]
│ │
│ ├── database/tables/
│ │ ├── user_streaks.dart [НОВЫЙ]
│ │ ├── user_reminder_settings.dart [НОВЫЙ]
│ │ ├── user_achievements.dart [НОВЫЙ]
│ │ ├── quiz_results.dart [НОВЫЙ]
│ │ ├── card_variants.dart [НОВЫЙ - коллекционные карточки]
│ │ ├── user_card_collection.dart [НОВЫЙ]
│ │ ├── user_collection_progress.dart [НОВЫЙ]
│ │ └── pending_card_rewards.dart [НОВЫЙ]
│ │
│ ├── collection/ [НОВАЯ ПАПКА]
│ │ ├── collection_manager.dart [НОВЫЙ]
│ │ │ - Добавление карточек в коллекцию
│ │ │ - Проверка unlock conditions
│ │ │ - Награждение карточками
│ │ │ - Обновление прогресса
│ │ │
│ │ ├── rarity_calculator.dart [НОВЫЙ]
│ │ │ - Определение редкости для наград
│ │ │ - Случайный выбор карточек
│ │ │ - Весовые коэффициенты
│ │ │
│ │ └── variant_generator.dart [НОВЫЙ]
│ │ - Генерация вариантов карточек при инициализации
│ │ - Создание Common/Rare/Legendary версий
│ │
│ ├── cron/
│ │ ├── send_reminders.dart [НОВЫЙ]
│ │ ├── check_achievements.dart [НОВЫЙ]
│ │ ├── collection_rewards.dart [НОВЫЙ - награды за коллекцию]
│ │ └── post_daily_card.dart [НОВЫЙ, опционально для канала]
│ │
│ └── statistics/
│ └── streak_calculator.dart [НОВЫЙ]
Миграции базы данных
Новые таблицы PostgreSQL
-- User streaks tracking
CREATE TABLE user_streaks (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
telegram_user_id TEXT UNIQUE,
current_streak INTEGER DEFAULT 0,
longest_streak INTEGER DEFAULT 0,
last_activity_date DATE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_user_streaks_telegram_user_id ON user_streaks(telegram_user_id);
CREATE INDEX idx_user_streaks_last_activity ON user_streaks(last_activity_date);
-- Reminder settings
CREATE TABLE user_reminder_settings (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT UNIQUE,
reminder_time TIME NOT NULL,
timezone TEXT DEFAULT 'UTC',
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_reminder_settings_time ON user_reminder_settings(reminder_time, enabled);
-- Achievements
CREATE TABLE user_achievements (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT NOT NULL,
achievement_type TEXT NOT NULL,
achieved_at TIMESTAMP DEFAULT NOW(),
notified BOOLEAN DEFAULT false
);
CREATE INDEX idx_achievements_notified ON user_achievements(notified);
CREATE INDEX idx_achievements_telegram_user ON user_achievements(telegram_user_id);
-- Quiz results
CREATE TABLE quiz_results (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT NOT NULL,
quiz_id TEXT NOT NULL,
total_questions INTEGER NOT NULL,
correct_answers INTEGER NOT NULL,
completed_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_quiz_results_telegram_user ON quiz_results(telegram_user_id);
-- ==================================================
-- COLLECTIBLE CARDS SYSTEM
-- ==================================================
-- Card variants (all possible collectible versions)
CREATE TABLE card_variants (
id SERIAL PRIMARY KEY,
card_id TEXT NOT NULL, -- ID основной карточки (game_card.id)
rarity TEXT NOT NULL, -- 'common', 'rare', 'legendary'
image_variant TEXT, -- Путь к альтернативному изображению
-- NULL = использовать базовое изображение с рамкой
frame_color TEXT NOT NULL, -- HEX цвет рамки (например: '#808080')
frame_width INTEGER DEFAULT 40, -- Ширина рамки в пикселях
has_glow BOOLEAN DEFAULT false, -- Эффект свечения вокруг рамки
has_sparkles BOOLEAN DEFAULT false, -- Эффект блесток/искр
unlock_condition TEXT, -- Текстовое описание условия получения
description TEXT, -- Описание варианта карточки
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(card_id, rarity),
CHECK (rarity IN ('common', 'rare', 'legendary'))
);
CREATE INDEX idx_variants_card_id ON card_variants(card_id);
CREATE INDEX idx_variants_rarity ON card_variants(rarity);
-- User card collection (что собрал пользователь)
CREATE TABLE user_card_collection (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT NOT NULL,
card_variant_id INTEGER NOT NULL REFERENCES card_variants(id) ON DELETE CASCADE,
obtained_at TIMESTAMP DEFAULT NOW(),
obtained_via TEXT, -- 'daily', 'quiz_perfect', 'streak_7', 'streak_30', 'achievement', etc.
UNIQUE(telegram_user_id, card_variant_id)
);
CREATE INDEX idx_collection_user ON user_card_collection(telegram_user_id);
CREATE INDEX idx_collection_obtained ON user_card_collection(obtained_at);
CREATE INDEX idx_collection_obtained_via ON user_card_collection(obtained_via);
-- User collection progress (кэш для быстрого доступа к статистике)
CREATE TABLE user_collection_progress (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT UNIQUE NOT NULL,
total_unique_words INTEGER DEFAULT 0, -- Количество уникальных слов в коллекции
total_cards INTEGER DEFAULT 0, -- Общее количество карточек (с учетом редкостей)
common_count INTEGER DEFAULT 0,
rare_count INTEGER DEFAULT 0,
legendary_count INTEGER DEFAULT 0,
completion_percentage DECIMAL(5,2) DEFAULT 0.0,
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_collection_progress_user ON user_collection_progress(telegram_user_id);
-- Pending card rewards (очередь наград, которые нужно выдать)
CREATE TABLE pending_card_rewards (
id SERIAL PRIMARY KEY,
telegram_user_id TEXT NOT NULL,
reward_type TEXT NOT NULL, -- 'rare_random', 'legendary_random', 'rare_choice', 'legendary_choice'
quantity INTEGER DEFAULT 1,
reason TEXT, -- 'streak_7', 'streak_30', 'quiz_perfect', etc.
card_choices TEXT[], -- Массив card_id для выбора (если reward_type содержит 'choice')
claimed BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
claimed_at TIMESTAMP
);
CREATE INDEX idx_pending_rewards_user ON pending_card_rewards(telegram_user_id, claimed);
CREATE INDEX idx_pending_rewards_claimed ON pending_card_rewards(claimed);
Аналитика и метрики
После реализации фич, отслеживать:
Вовлеченность:
- DAU (Daily Active Users) через команды
- Частота использования команд
/daily,/quiz,/stats - Retention rate (возвращаются ли пользователи на следующий день)
Эффективность:
- Средняя длина стрика
- Процент пользователей с настроенными напоминаниями
- Процент прохождения квизов (completion rate)
- Средний результат в квизах
Endpoints для админа:
GET /api/v2/admin/telegram-bot/analytics
- Количество активных пользователей бота
- Популярные команды
- Средняя длина стриков
- Retention metrics
Приоритеты реализации
MVP (Iteration 1) - 2-3 недели
- ✅
/daily- Карточка дня (базовая версия без коллекционирования) - ✅
/stats- Базовая статистика - ✅ Backend: Endpoints для карточек и статистики
- ✅ Backend: Таблица user_streaks
Iteration 2 - 1-2 недели
- ✅
/quiz- Мини-квизы - ✅ Backend: Quiz generation и results tracking
Iteration 3 (Коллекционные карточки) - 2-3 недели
-
✅ Система коллекционных карточек:
- Backend: таблицы card_variants, user_card_collection, user_collection_progress
- Backend: endpoints для коллекции
- Генерация вариантов карточек с разными рамками (Common/Rare/Legendary)
-
✅ Команда
/collection- просмотр коллекции -
✅ Команда
/showcase [слово]- детали карточки -
✅ Обновление
/daily- интеграция с коллекцией -
✅ Обновление
/stats- статистика коллекции -
✅ Система награждения карточками за достижения
Iteration 4 - 1-2 недели
- ✅
/reminders- Напоминания - ✅ Cron job для отправки напоминаний
Iteration 5 - 1 неделя
- ✅ Автоматические достижения
- ✅ Cron job для проверки achievements
- ✅ Интеграция достижений с наградами коллекционных карточек
Iteration 6 (Социальные фичи) - 1-2 недели
- ✅
/share_card- поделиться карточкой - ✅
/leaderboard collection- топ коллекционеров (опционально) - ✅ Тематические события для коллекции (опционально)
Optional (если канал появится)
- 📢 Автопостинг в канал
- 📊 Еженедельные итоги в канале
- 🌟 "Карточка недели" в канале
- 🎉 События "Редкие выходные"
Риски и митигация
Технические риски
Проблема: Telegram API rate limits
- Митигация: Использовать батчинг сообщений, queue для напоминаний
Проблема: Сложность state management для квизов
- Митигация: Простой in-memory Map, ограничить время жизни квиза (15 минут)
Проблема: Часовые пояса для напоминаний
- Митигация: Начать с UTC, потом добавить определение timezone через location
Продуктовые риски
Проблема: Низкая активация (пользователи не используют команды)
- Митигация:
- Добавить onboarding после авторизации
- Welcome message с перечислением команд
- Push notification после регистрации
Проблема: Спам напоминаниями
- Митигация:
- Максимум 1 напоминание в день
- Легкое отключение через
/reminders - Автоматическое отключение после 7 дней неактивности
Дизайн сообщений
Единый стиль
Использовать эмодзи для визуальной привлекательности:
- 🎴 Карточки
- 📊 Статистика
- 🔥 Стрики
- 🎯 Квизы
- ⏰ Напоминания
- 🎉 Достижения
- ✅ Успех
- ❌ Ошибка
Тон общения:
- Дружелюбный, мотивирующий
- Короткие сообщения (2-4 строки)
- Призывы к действию (CTA)
Пример onboarding flow
После первой авторизации через /start или /login:
Бот:
Привет! 👋
Я бот Mnemo Cards. Помогу тебе учить языки каждый день!
Что я умею:
🎴 /daily - карточка дня для изучения
🎯 /quiz - быстрый квиз для проверки знаний
📊 /stats - твоя статистика и стрики
⏰ /reminders - настрой напоминания
Начнем с карточки дня? → /daily
Тестирование
Unit тесты
BackendClient.getUserStats()→ проверить парсинг responseBackendClient.generateQuiz()→ проверить структуру квизаQuizManager→ state management для активных квизовStreakCalculator→ логика подсчета стриков
Integration тесты
- End-to-end flow:
/daily→ получить карточку → отправить изображение - End-to-end flow:
/quiz→ ответить на вопросы → получить результат - Cron job:
SendRemindersTask→ отправка напоминаний в нужное время
Manual QA
- Тестирование команд в реальном Telegram
- Проверка inline keyboards
- Проверка таймингов напоминаний
- Проверка корректности стриков при активности в разные дни
Документация
После реализации обновить:
mnemo_cards_telegram_bot/README.md- описание новых командmnemo_cards_backend/README.md- новые API endpoints- Создать
mnemo_cards_telegram_bot/COMMANDS.md- справочник команд для пользователей
Заключение
Предложенные фичи создают полноценную продуктовую экосистему вокруг Telegram бота:
✅ Привычка - ежедневные напоминания и карточка дня
✅ Мотивация - стрики, достижения и коллекционирование
✅ Практика - квизы для закрепления знаний
✅ Прогресс - видимая статистика успехов и коллекции
✅ Удобство - обучение прямо в Telegram без открытия приложения
✅ Геймификация - система коллекционных карточек с редкостью создает долгосрочную цель
✅ Социальный аспект - возможность делиться своими достижениями и редкими карточками
Почему коллекционные карточки важны для retention:
- Долгосрочная мотивация - собрать все Legendary карточки может занять месяцы
- Визуальная награда - красивые изображения с разными рамками создают эмоциональную связь
- Прогресс виден - пользователь всегда видит, сколько ещё осталось собрать
- FOMO эффект - ограниченные/сезонные карточки заставляют возвращаться
- Гордость достижениями - возможность похвастаться редкими карточками
Это создает дополнительную ценность для пользователей и значительно повышает retention, что критично для MVP стадии проекта.
Roadmap Summary
Минимальный MVP (4-5 недель):
- Базовые команды: /daily, /stats, /quiz
- Система стриков
- Простая коллекция (только Common карточки)
Полноценный MVP (8-10 недель):
- Все базовые команды
- Полная система коллекционных карточек (Common/Rare/Legendary)
- Напоминания
- Достижения с наградами в виде карточек
- Команды /collection, /showcase
Phase 2 (12+ недель):
- Социальные фичи (/share_card, /leaderboard)
- Telegram канал с автопостингом
- Тематические события
- Обмен карточками (опционально)
- Крафтинг (опционально)