Files
tg_bot_language/services/reminder_service.py
mamonov.ep 72a63eeda5 Добавлены основные функции MVP: тематические подборки, импорт слов, диалоговая практика, напоминания и тест уровня
Новые команды:
- /words [тема] - AI-генерация тематических подборок слов (10 слов по теме с учётом уровня)
- /import - извлечение до 15 ключевых слов из текста (книги, статьи, песни)
- /practice - диалоговая практика с AI в 6 сценариях (ресторан, магазин, путешествие, работа, врач, общение)
- /reminder - настройка ежедневных напоминаний по расписанию
- /level_test - тест из 7 вопросов для определения уровня английского (A1-C2)

Основные изменения:
- AI сервис: добавлены методы generate_thematic_words, extract_words_from_text, start_conversation, continue_conversation, generate_level_test
- Диалоговая практика: исправление ошибок в реальном времени, подсказки, перевод реплик
- Напоминания: APScheduler для ежедневной отправки напоминаний в выбранное время
- Тест уровня: автоматическое определение уровня при регистрации, можно пропустить
- База данных: добавлены поля reminders_enabled, last_reminder_sent
- Vocabulary service: метод get_word_by_original для проверки дубликатов
- Зависимости: apscheduler==3.10.4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:46:02 +03:00

142 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import logging
from datetime import datetime, timedelta
from typing import List
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database.models import User
from database.db import async_session_maker
logger = logging.getLogger(__name__)
class ReminderService:
"""Сервис для управления напоминаниями"""
def __init__(self, bot):
self.bot = bot
self.scheduler = AsyncIOScheduler()
def start(self):
"""Запустить планировщик"""
# Проверяем напоминания каждые 5 минут
self.scheduler.add_job(
self.check_and_send_reminders,
trigger='interval',
minutes=5,
id='check_reminders',
replace_existing=True
)
self.scheduler.start()
logger.info("Планировщик напоминаний запущен")
def shutdown(self):
"""Остановить планировщик"""
self.scheduler.shutdown()
logger.info("Планировщик напоминаний остановлен")
async def check_and_send_reminders(self):
"""Проверить и отправить напоминания пользователям"""
try:
async with async_session_maker() as session:
# Получаем всех пользователей с включенными напоминаниями
result = await session.execute(
select(User).where(
User.reminders_enabled == True,
User.daily_task_time.isnot(None)
)
)
users = list(result.scalars().all())
current_time = datetime.utcnow()
for user in users:
if await self._should_send_reminder(user, current_time):
await self._send_reminder(user, session)
except Exception as e:
logger.error(f"Ошибка при проверке напоминаний: {e}")
async def _should_send_reminder(self, user: User, current_time: datetime) -> bool:
"""
Проверить, нужно ли отправлять напоминание пользователю
Args:
user: Пользователь
current_time: Текущее время (UTC)
Returns:
True если нужно отправить
"""
if not user.daily_task_time:
return False
# Парсим время напоминания (формат HH:MM)
try:
hour, minute = map(int, user.daily_task_time.split(':'))
except:
return False
# Создаем datetime для времени напоминания сегодня (UTC)
reminder_time = current_time.replace(hour=hour, minute=minute, second=0, microsecond=0)
# Проверяем, не отправляли ли мы уже напоминание сегодня
if user.last_reminder_sent:
last_sent_date = user.last_reminder_sent.date()
current_date = current_time.date()
# Если уже отправляли сегодня, не отправляем снова
if last_sent_date == current_date:
return False
# Проверяем, наступило ли время напоминания (с погрешностью 5 минут)
time_diff = abs((current_time - reminder_time).total_seconds())
return time_diff < 300 # 5 минут в секундах
async def _send_reminder(self, user: User, session: AsyncSession):
"""
Отправить напоминание пользователю
Args:
user: Пользователь
session: Сессия базы данных
"""
try:
message_text = (
"⏰ <b>Время для практики!</b>\n\n"
"Не забудь потренироваться сегодня:\n"
"• /task - выполни задания\n"
"• /practice - попрактикуй диалог\n"
"• /words - добавь новые слова\n\n"
"💪 Регулярная практика - ключ к успеху!"
)
await self.bot.send_message(
chat_id=user.telegram_id,
text=message_text
)
# Обновляем время последнего напоминания
user.last_reminder_sent = datetime.utcnow()
await session.commit()
logger.info(f"Напоминание отправлено пользователю {user.telegram_id}")
except Exception as e:
logger.error(f"Ошибка при отправке напоминания пользователю {user.telegram_id}: {e}")
# Глобальный экземпляр сервиса (будет инициализирован в main.py)
reminder_service: ReminderService = None
def init_reminder_service(bot):
"""Инициализировать сервис напоминаний"""
global reminder_service
reminder_service = ReminderService(bot)
return reminder_service