reminder-bot/bot/handlers/callbacks.py

261 lines
7.9 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.

"""Handlers for inline button callbacks (done, snooze, pause, delete)."""
from aiogram import Router, F
from aiogram.types import CallbackQuery, Message
from sqlalchemy.ext.asyncio import AsyncSession
from bot.keyboards.reminders import (
ReminderActionCallback,
SnoozeDelayCallback,
ConfirmCallback,
get_snooze_delay_keyboard,
get_confirmation_keyboard,
)
from bot.keyboards.main_menu import get_main_menu_keyboard
from bot.services.reminders_service import RemindersService
from bot.services.time_service import get_time_service
from bot.logging_config import get_logger
logger = get_logger(__name__)
router = Router(name="callbacks")
reminders_service = RemindersService()
time_service = get_time_service()
# ==================== Done Action ====================
@router.callback_query(ReminderActionCallback.filter(F.action == "done"))
async def handle_done(
callback: CallbackQuery,
callback_data: ReminderActionCallback,
session: AsyncSession,
) -> None:
"""
Handle 'Done' button - mark reminder as completed.
Args:
callback: Callback query
callback_data: Parsed callback data
session: Database session
"""
reminder = await reminders_service.mark_as_done(session, callback_data.reminder_id)
if not reminder:
await callback.answer("Напоминание не найдено", show_alert=True)
return
next_run_str = time_service.format_next_run(reminder.next_run_at)
await callback.message.edit_text(
f"✅ Отлично! Отметил как выполненное.\n\n"
f"Следующее напоминание будет {next_run_str}."
)
await callback.answer("Выполнено!")
logger.info(f"Reminder {reminder.id} marked as done by user {callback.from_user.id}")
# ==================== Snooze Action ====================
@router.callback_query(ReminderActionCallback.filter(F.action == "snooze"))
async def handle_snooze_select(
callback: CallbackQuery,
callback_data: ReminderActionCallback,
) -> None:
"""
Handle 'Snooze' button - show delay options.
Args:
callback: Callback query
callback_data: Parsed callback data
"""
await callback.message.edit_text(
"На сколько отложить напоминание?",
reply_markup=get_snooze_delay_keyboard(callback_data.reminder_id),
)
await callback.answer()
@router.callback_query(SnoozeDelayCallback.filter())
async def handle_snooze_delay(
callback: CallbackQuery,
callback_data: SnoozeDelayCallback,
session: AsyncSession,
) -> None:
"""
Handle snooze delay selection.
Args:
callback: Callback query
callback_data: Parsed callback data
session: Database session
"""
reminder = await reminders_service.snooze(
session, callback_data.reminder_id, callback_data.hours
)
if not reminder:
await callback.answer("Напоминание не найдено", show_alert=True)
return
next_run_str = time_service.format_next_run(reminder.next_run_at)
await callback.message.edit_text(
f"⏰ Напоминание отложено.\n\n"
f"Напомню {next_run_str}."
)
await callback.answer("Отложено!")
logger.info(
f"Reminder {reminder.id} snoozed for {callback_data.hours}h "
f"by user {callback.from_user.id}"
)
# ==================== Pause/Resume Actions ====================
@router.callback_query(ReminderActionCallback.filter(F.action == "pause"))
async def handle_pause(
callback: CallbackQuery,
callback_data: ReminderActionCallback,
session: AsyncSession,
) -> None:
"""
Handle 'Pause' button - deactivate reminder.
Args:
callback: Callback query
callback_data: Parsed callback data
session: Database session
"""
reminder = await reminders_service.pause_reminder(session, callback_data.reminder_id)
if not reminder:
await callback.answer("Напоминание не найдено", show_alert=True)
return
await callback.message.edit_text(
"⏸ Напоминание поставлено на паузу.\n\n"
"Можешь возобновить его в любое время через «📋 Мои напоминания»."
)
await callback.answer("Поставлено на паузу")
logger.info(f"Reminder {reminder.id} paused by user {callback.from_user.id}")
@router.callback_query(ReminderActionCallback.filter(F.action == "resume"))
async def handle_resume(
callback: CallbackQuery,
callback_data: ReminderActionCallback,
session: AsyncSession,
) -> None:
"""
Handle 'Resume' button - reactivate reminder.
Args:
callback: Callback query
callback_data: Parsed callback data
session: Database session
"""
reminder = await reminders_service.resume_reminder(session, callback_data.reminder_id)
if not reminder:
await callback.answer("Напоминание не найдено", show_alert=True)
return
next_run_str = time_service.format_next_run(reminder.next_run_at)
await callback.message.edit_text(
f"▶️ Напоминание возобновлено!\n\n"
f"Следующее напоминание будет {next_run_str}."
)
await callback.answer("Возобновлено!")
logger.info(f"Reminder {reminder.id} resumed by user {callback.from_user.id}")
# ==================== Delete Action ====================
@router.callback_query(ReminderActionCallback.filter(F.action == "delete"))
async def handle_delete_confirm(
callback: CallbackQuery,
callback_data: ReminderActionCallback,
) -> None:
"""
Handle 'Delete' button - ask for confirmation.
Args:
callback: Callback query
callback_data: Parsed callback data
"""
await callback.message.edit_text(
"Точно удалить напоминание?",
reply_markup=get_confirmation_keyboard(
entity="delete",
entity_id=callback_data.reminder_id
),
)
await callback.answer()
@router.callback_query(ConfirmCallback.filter(F.entity == "delete"))
async def handle_delete_execute(
callback: CallbackQuery,
callback_data: ConfirmCallback,
session: AsyncSession,
) -> None:
"""
Execute reminder deletion after confirmation.
Args:
callback: Callback query
callback_data: Parsed callback data
session: Database session
"""
if callback_data.action == "no":
await callback.message.edit_text("Удаление отменено.")
await callback.answer()
return
deleted = await reminders_service.delete_reminder_by_id(
session, callback_data.entity_id
)
if not deleted:
await callback.answer("Напоминание не найдено", show_alert=True)
return
await callback.message.edit_text("🗑 Напоминание удалено.")
await callback.answer("Удалено")
logger.info(
f"Reminder {callback_data.entity_id} deleted by user {callback.from_user.id}"
)
# ==================== Settings Placeholder ====================
@router.message(F.text == "⚙️ Настройки")
async def handle_settings(message: Message) -> None:
"""
Handle settings button (placeholder).
Args:
message: Telegram message
"""
await message.answer(
"⚙️ Настройки\n\n"
"Функционал настроек будет добавлен в следующих версиях.\n\n"
"Пока доступны основные функции:\n"
"• Создание напоминаний\n"
"• Просмотр и управление\n"
"• Редактирование параметров",
reply_markup=get_main_menu_keyboard(),
)