mnemo_cards/plans/telegram_bot_product_features.md
Dmitry 8d3d4cd1f7
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Mobile App CI / test (push) Waiting to run
Mobile App CI / build-android (push) Blocked by required conditions
Mobile App CI / build-ios (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Waiting to run
stuff
2025-12-20 02:38:51 +03:00

50 KiB
Raw Permalink Blame History

name overview todos
Telegram Bot Product Features Добавление продуктовых фич в Telegram бот для повышения вовлеченности пользователей и создания привычки ежедневного обучения. Фокус на простых, но эффективных механиках для MVP стадии.
id content status
daily-command Реализовать команду /daily для карточки дня с изображением pending
id content status
stats-command Реализовать команду /stats и backend endpoint для статистики pending
id content status
streaks-tracking Добавить tracking стриков в PostgreSQL (таблица user_streaks) pending
id content status
quiz-command Реализовать мини-квиз /quiz с inline keyboard pending
id content status
reminders-command Реализовать настройку напоминаний /reminders и cron job для отправки pending
id content status
achievements Добавить автоматические поздравления с достижениями pending
id content status
collectible-cards-system Реализовать систему коллекционных карточек с редкостью (Common/Rare/Legendary) pending
id content status
collection-command Реализовать команду /collection для просмотра коллекции pending
id content status
card-variants-generation Добавить генерацию изображений с разными рамками для редкостей pending
id content status
tests Написать unit и integration тесты для новых фич pending

План продуктовых фич для Telegram бота Mnemo Cards

Обзор

Текущий бот выполняет технические функции (бэкап, авторизация, админ-панель) и имеет базовую команду /share. Предлагается добавить продуктовые фичи для вовлечения и контента, которые помогут:

  • Создать привычку ежедневного использования
  • Повысить удержание пользователей
  • Предоставить дополнительную ценность помимо основного приложения
  • Собрать аналитику вовлеченности

Приоритетные фичи (MVP)

1. 🎴 Карточка дня (/daily команда)

Описание: Пользователь получает случайную карточку для изучения

UX Flow:

Пользователь: /daily
Бот: 
  [Красивое изображение карточки]
  
  🇪🇸 el perro
  🇷🇺 собака
  
  💡 Мнемоника: [mnemo text]
  🔊 Транскрипция: [transcription]
  
  Хочешь проверить себя? Нажми /quiz

Реализация:

  • Новая команда в bin/main.dartteledart.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 часа назад
  
  Так держать! Продолжай в том же духе! 💪

Реализация:

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)

Описание: Система коллекционирования карточек с разными уровнями редкости. Одно и то же слово может иметь несколько вариантов карточек с разными изображениями и редкостью.

Концепция редкости

Три уровня редкости:

  1. 🟢 Common (Обычная)

    • Базовое изображение карточки
    • Серая рамка
    • Получение: автоматически при изучении слова или через /daily
  2. 🔵 Rare (Редкая)

    • Улучшенное/детальное изображение
    • Синяя рамка с эффектом свечения
    • Получение: за достижения (стрик 7 дней, квиз 100%, и т.д.)
  3. 🟣 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 версия одной карточки из квиза
  • 📅 Использовал /daily 10 раз → выбери любую 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    [НОВЫЙ]
           - Автоматическое награждение за стрики/достижения
           - Интеграция с системой достижений

Геймификация и мотивация

Прогресс-системы:

  1. Коллекционирование по пакам:

    • "Собери все Common карточки пака 'Животные'" → награда: 1 Rare любой карточки пака
    • "Собери все Rare карточки пака" → награда: 1 Legendary из пака
  2. Коллекционирование по редкости:

    • "Собери 10 Rare карточек" → награда: 1 Legendary на выбор
    • "Собери первую Legendary" → достижение + особая награда
  3. Тематические коллекции:

    • "Собери все карточки с животными" → награда
    • "Собери все карточки с едой" → награда

Лидерборд коллекционеров (опционально):

Команда: /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 недели

  1. /daily - Карточка дня (базовая версия без коллекционирования)
  2. /stats - Базовая статистика
  3. Backend: Endpoints для карточек и статистики
  4. Backend: Таблица user_streaks

Iteration 2 - 1-2 недели

  1. /quiz - Мини-квизы
  2. Backend: Quiz generation и results tracking

Iteration 3 (Коллекционные карточки) - 2-3 недели

  1. Система коллекционных карточек:

    • Backend: таблицы card_variants, user_card_collection, user_collection_progress
    • Backend: endpoints для коллекции
    • Генерация вариантов карточек с разными рамками (Common/Rare/Legendary)
  2. Команда /collection - просмотр коллекции

  3. Команда /showcase [слово] - детали карточки

  4. Обновление /daily - интеграция с коллекцией

  5. Обновление /stats - статистика коллекции

  6. Система награждения карточками за достижения

Iteration 4 - 1-2 недели

  1. /reminders - Напоминания
  2. Cron job для отправки напоминаний

Iteration 5 - 1 неделя

  1. Автоматические достижения
  2. Cron job для проверки achievements
  3. Интеграция достижений с наградами коллекционных карточек

Iteration 6 (Социальные фичи) - 1-2 недели

  1. /share_card - поделиться карточкой
  2. /leaderboard collection - топ коллекционеров (опционально)
  3. Тематические события для коллекции (опционально)

Optional (если канал появится)

  1. 📢 Автопостинг в канал
  2. 📊 Еженедельные итоги в канале
  3. 🌟 "Карточка недели" в канале
  4. 🎉 События "Редкие выходные"

Риски и митигация

Технические риски

Проблема: 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() → проверить парсинг response
  • BackendClient.generateQuiz() → проверить структуру квиза
  • QuizManager → state management для активных квизов
  • StreakCalculator → логика подсчета стриков

Integration тесты

  • End-to-end flow: /daily → получить карточку → отправить изображение
  • End-to-end flow: /quiz → ответить на вопросы → получить результат
  • Cron job: SendRemindersTask → отправка напоминаний в нужное время

Manual QA

  • Тестирование команд в реальном Telegram
  • Проверка inline keyboards
  • Проверка таймингов напоминаний
  • Проверка корректности стриков при активности в разные дни

Документация

После реализации обновить:


Заключение

Предложенные фичи создают полноценную продуктовую экосистему вокруг Telegram бота:

Привычка - ежедневные напоминания и карточка дня

Мотивация - стрики, достижения и коллекционирование

Практика - квизы для закрепления знаний

Прогресс - видимая статистика успехов и коллекции

Удобство - обучение прямо в Telegram без открытия приложения

Геймификация - система коллекционных карточек с редкостью создает долгосрочную цель

Социальный аспект - возможность делиться своими достижениями и редкими карточками

Почему коллекционные карточки важны для retention:

  1. Долгосрочная мотивация - собрать все Legendary карточки может занять месяцы
  2. Визуальная награда - красивые изображения с разными рамками создают эмоциональную связь
  3. Прогресс виден - пользователь всегда видит, сколько ещё осталось собрать
  4. FOMO эффект - ограниченные/сезонные карточки заставляют возвращаться
  5. Гордость достижениями - возможность похвастаться редкими карточками

Это создает дополнительную ценность для пользователей и значительно повышает 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 канал с автопостингом
  • Тематические события
  • Обмен карточками (опционально)
  • Крафтинг (опционально)