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

# -*- coding: utf-8 -*-
__all__ = ["start_router", "command_start_handler"]
__author__ = "QuacktorAI"
__copyright__ = "Copyright 2024, Forge of Absurd Ducks"
__credits__ = ["QuacktorAI"]

import logging

from aiogram import Router
from aiogram.enums import ParseMode
from aiogram.filters.command import CommandStart
from aiogram.types import Message
from sqlalchemy import select

from quackamollie.core.bot.decorator.permissions import permission_authorized
from quackamollie.core.bot.decorator.acknowledge_with_reactions import acknowledge_with_reactions
from quackamollie.core.bot.menu.settings_menu import get_settings_menu_root
from quackamollie.core.cli.settings import pass_quackamollie_settings, QuackamollieSettings
from quackamollie.core.database.model import User, AppRole, Chat, ChatMember, ChatSetting
from quackamollie.core.enum.chat_type import ChatType
from quackamollie.core.enum.role_type import AppRoleType
from quackamollie.core.enum.user_type import UserType
from quackamollie.core.utils.str_management import sanitize_username

log = logging.getLogger(__name__)

start_router = Router()


[docs] @start_router.message(CommandStart()) @permission_authorized @acknowledge_with_reactions @pass_quackamollie_settings async def command_start_handler(quackamollie_settings: QuackamollieSettings, message: Message): """ Handler for the `/start` 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 """ # Get database session from settings async_session = quackamollie_settings.session # Get user info from message user_id: int = message.from_user.id user_name: str = sanitize_username(message.from_user.full_name) user_role: AppRoleType = AppRoleType.authorized if user_id in quackamollie_settings.admin_ids: user_role = AppRoleType.admin elif user_id in quackamollie_settings.moderator_ids: user_role = AppRoleType.moderator # Get chat info from message chat_id: int = message.chat.id chat_name: str = f"Private chat of {user_name}" if message.chat.title is None else message.chat.title chat_type: ChatType = ChatType[message.chat.type] # Get user object, chat object and chat_member relationship references to know if they already exists or not async with async_session() as session: user_result = await session.execute(select(User.id).where(User.id == user_id).limit(1)) user = user_result.scalars().first() chat_result = await session.execute(select(Chat.id).where(Chat.id == chat_id).limit(1)) chat = chat_result.scalars().first() chat_member_stmt = select(ChatMember.chat_id).where((ChatMember.user_id == user_id) & (ChatMember.chat_id == chat_id)).limit(1) chat_member_result = await session.execute(chat_member_stmt) chat_member = chat_member_result.scalars().first() objects_to_create = [] relationships_to_create = [] # Add user for creation if not found if user is None: log.debug("The user is not found in the database. Creating them...") async with async_session() as session: role_result = await session.execute(select(AppRole.id).where(AppRole.role_type == user_role).limit(1)) role_id = role_result.scalars().one() new_user = User( id=user_id, user_type=UserType.user, app_role_id=role_id, full_name=user_name, username=sanitize_username(message.from_user.username), first_name=sanitize_username(message.from_user.first_name), last_name=sanitize_username(message.from_user.last_name), ) objects_to_create.append(new_user) else: log.debug(f"User '{user_name}' with ID '{user_id}' already exists in the database") # Add chat for creation if not found if chat is None: log.debug("The chat is not found in the database. Creating it...") objects_to_create.append(Chat(id=chat_id, chat_name=chat_name, chat_type=chat_type, settings=ChatSetting())) else: log.debug(f"Chat '{chat_name}' with ID '{chat_id}' already exists in the database") # Add chat_member for creation if not found if chat_member is None: log.debug("The relationship between user and chat is not found in the database. Creating it...") relationships_to_create.append(ChatMember(user_id=user_id, chat_id=chat_id)) else: log.debug(f"Relationship between user '{user_id}' and chat '{chat_id}' already exists in the database") # If the resources to create list is not empty, we create the needed resources if objects_to_create or relationships_to_create: async with async_session() as session: if objects_to_create: async with session.begin(): session.add_all(objects_to_create) if relationships_to_create: async with session.begin(): session.add_all(relationships_to_create) log.debug("Missing resources created with success") start_message = (f"Welcome, <b>{user_name}</b>!\nYou successfully registered in this chat. Now, you may want" f" to edit chat settings to set the LLM model to use in this chat.") else: start_message = f"Welcome, <b>{user_name}</b>!\nYou are already registered in this chat." # Get InlineKeyboardBuilder depending on the current type of chat and user AppRoleType start_builder = get_settings_menu_root(chat_type, user_role) # Reply the constructed answer await message.answer( start_message, parse_mode=ParseMode.HTML, reply_markup=start_builder.as_markup(), disable_web_page_preview=True, )