95 lines
3.7 KiB
Python

from logging import Logger
from typing import Optional
from pyrogram import filters
from pyrogram.filters import Filter
from pyrogram.client import Client
from pyrogram.types import Message
from pyrogram.enums import ChatAction
from src.bot.handlers import AbstractCommandHandler
from src.integrations.gigachat_api_client import GigaChatClient
class AICommandHandler(AbstractCommandHandler):
"""
Command handler for the /ai command in a Pyrogram bot.
This handler processes text input, sends it to the GigaChat AI model,
and returns the generated response.
Attributes:
COMMAND (`str`): The name of the command that this handler handles.
logger (`Logger`): Logger instance for logging events.
gigachat_client (`GigaChatClient`): Client for interacting with the GigaChat API.
"""
def __init__(self, logger: Logger, gigachat_client: GigaChatClient) -> None:
"""
Initializes the AICommandHandler.
Args:
logger (`Logger`): Logger instance for logging events.
gigachat_client (`GigaChatClient`): Client for interacting with the GigaChat API.
"""
self.logger: Logger = logger
self.gigachat_client: GigaChatClient = gigachat_client
@property
def COMMAND(self) -> str:
"""
The name of the command that this handler handles.
Returns:
str: The command name.
"""
return "ai"
def get_filters(self) -> Filter:
"""
Returns the filter for the /ai command.
Returns:
`pyrogram.filters.Filter`: A Pyrogram filter matching the /ai command.
"""
return filters.command(self.COMMAND)
async def handle(self, client: Client, message: Message) -> None:
"""
Handles the /ai command.
Sends the user's input to the GigaChat AI model and returns the generated response.
The command can be used with an inline argument or as a reply to a text message.
Args:
client (`pyrogram.client.Client`): The Pyrogram client instance.
message (`pyrogram.types.Message`): The incoming message object to process.
"""
self.logger.info(f"Received /{self.COMMAND} command from chat_id={message.chat.id}.")
# Extract the command argument or use the replied message's text
command_argument: Optional[str] = " ".join(message.text.split()[1:])
if not command_argument and message.reply_to_message and message.reply_to_message.text:
command_argument = message.reply_to_message.text
if not command_argument:
self.logger.warning(f"No argument provided for /{self.COMMAND} command in chat_id={message.chat.id}.")
await message.reply(f"Please provide a message after /{self.COMMAND} or reply to a message.", quote=True)
return
# Notify the user that the request is being processed
processing_message: Message = await message.reply(
f"{self.gigachat_client.model_name} is processing your request...", quote=True
)
try:
await client.send_chat_action(message.chat.id, ChatAction.TYPING)
response_text: str = self.gigachat_client.get_response(str(message.chat.id), command_argument)
self.logger.debug(f"Generated response for chat_id={message.chat.id}")
await processing_message.edit_text(response_text)
except Exception as error:
self.logger.error(f"Error processing /{self.COMMAND} command for chat_id={message.chat.id}: {error}", exc_info=True)
await processing_message.edit_text("An error occurred while processing your request.")
finally:
await client.send_chat_action(message.chat.id, ChatAction.CANCEL)