Source code for quackamollie.core.bot.command.settings_bot_command

# -*- coding: utf-8 -*-
""" Module to access the `/settings` menu from the Telegram bot"""
__all__ = ["settings_router", "command_settings_handler", "root_settings_callback_handler", "answer_root_settings"]
__author__ = "QuacktorAI"
__copyright__ = "Copyright 2024, Forge of Absurd Ducks"
__credits__ = ["QuacktorAI"]

import logging

from aiogram import F, Router
from aiogram.enums import ParseMode
from aiogram.filters.command import Command
from aiogram.types import Message, CallbackQuery
from sqlalchemy import select
from typing import Optional, Union

from quackamollie.core.bot.decorator.acknowledge_with_reactions import acknowledge_with_reactions
from quackamollie.core.bot.decorator.permissions import permission_authorized
from quackamollie.core.bot.decorator.user_chat_registered import ensure_user_chat_registered
from quackamollie.core.bot.menu.settings_menu import (SettingsCallbackData, get_settings_menu_root,
                                                      get_settings_menu_root_description)
from quackamollie.core.cli.settings import pass_quackamollie_settings, QuackamollieSettings
from quackamollie.core.database.model import ChatSetting
from quackamollie.core.enum.chat_type import ChatType
from quackamollie.core.enum.role_type import AppRoleType

log = logging.getLogger(__name__)

settings_router = Router()


[docs] @settings_router.message(Command("settings")) @permission_authorized @ensure_user_chat_registered @acknowledge_with_reactions @pass_quackamollie_settings async def command_settings_handler(quackamollie_settings: QuackamollieSettings, message: Message): """ Handler for the `/settings` command in Telegram chat. :param quackamollie_settings: The application settings initialized from click context :type quackamollie_settings: QuackamollieSettings :param message: The message as given by aiogram router :type message: Message """ await answer_root_settings(quackamollie_settings, message)
[docs] @settings_router.callback_query(SettingsCallbackData.filter(F.name == "settings_root")) @permission_authorized @ensure_user_chat_registered @pass_quackamollie_settings async def root_settings_callback_handler(quackamollie_settings: QuackamollieSettings, query: CallbackQuery): """ Callback query handler for when hitting a `go back` button redirecting to te settings root :param quackamollie_settings: The application settings initialized from click context :type quackamollie_settings: QuackamollieSettings :param query: A callback query given by aiogram :type query: CallbackQuery """ await answer_root_settings(quackamollie_settings, query)
[docs] async def answer_root_settings(quackamollie_settings: QuackamollieSettings, query_msg: Union[Message, CallbackQuery]): """ Handler when asked to display the `/settings` command in Telegram chat or when hitting a `go back` button redirecting to te settings root :param quackamollie_settings: The application settings initialized from click context :type quackamollie_settings: QuackamollieSettings :param query_msg: Undifferentiated Message or CallbackQuery as given by aiogram router :type query_msg: Union[Message, CallbackQuery] """ message: Message = query_msg.message if isinstance(query_msg, CallbackQuery) else query_msg # Get database session from settings async_session = quackamollie_settings.session # Get user AppRoleType from the message and quackamollie_settings user_role: AppRoleType = AppRoleType.authorized if query_msg.from_user.id in quackamollie_settings.admin_ids: user_role = AppRoleType.admin elif query_msg.from_user.id in quackamollie_settings.moderator_ids: user_role = AppRoleType.moderator # Get chat info from message chat_id: int = message.chat.id chat_type: ChatType = ChatType[message.chat.type] # Get possible chat type override from database, if not already in a private chat if chat_type != ChatType.private: async with async_session() as session: # Get chat settings for the current chat chat_setting_result = await session.execute(select(ChatSetting).where( ChatSetting.chat_id == chat_id ).limit(1)) chat_setting: Optional[ChatSetting] = chat_setting_result.scalars().first() # Get possible chat type override chat_type_override: Optional[ChatType] = chat_setting.chat_type_override if chat_type_override is not None: chat_type = chat_type_override # Get InlineKeyboardBuilder depending on the current type of chat and user AppRoleType settings_builder = get_settings_menu_root(chat_type, user_role) # Get menu descriptions depending on the current type of chat and user AppRoleType settings_message = get_settings_menu_root_description(chat_type, user_role) # Reply the constructed answer depending on the type of the given `query_msg` if isinstance(query_msg, CallbackQuery): # If this answer results from a CallbackQuery, we edit the current message await message.edit_text( settings_message, parse_mode=ParseMode.HTML, reply_markup=settings_builder.as_markup(), disable_web_page_preview=True, ) else: # If this answer results from a Message (i.e. from the /settings command), we answer a new message await message.answer( settings_message, parse_mode=ParseMode.HTML, reply_markup=settings_builder.as_markup(), disable_web_page_preview=True, )