261 lines
7.9 KiB
Python
261 lines
7.9 KiB
Python
"""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(),
|
||
)
|