This commit is contained in:
2026-02-04 11:28:09 +01:00
5 changed files with 306 additions and 34 deletions
@@ -1,6 +1,6 @@
from abc import ABC, abstractmethod
from enum import Enum
from discord import Message
from discord import Message, Attachment
class IClientMessage(ABC):
@@ -18,56 +18,59 @@ class ClientMessage(IClientMessage):
class IMessageBuilder(ABC):
@abstractmethod
def __init__(self, raw_message: object):
self.raw_message = raw_message
self.message: IClientMessage = None
def create_message(self) -> ClientMessage:
self.set_content() \
.set_author_name() \
.set_image_urls()
return self.message
@abstractmethod
def set_content(self):
def __init__(self):
pass
@abstractmethod
def set_author_name(self):
def set_content(self, value: str):
pass
@abstractmethod
def set_image_urls(self):
def set_author_name(self, value: str):
pass
@abstractmethod
def set_image_urls(self, value: list[str]):
pass
class DiscordMessageBuilder(IMessageBuilder):
def __init__(self, raw_message: Message):
self.raw_message = raw_message
self.message = ClientMessage()
def __init__(self, message: IClientMessage):
self.message = message
def create_message(self) -> ClientMessage:
return super().create_message()
def set_author_name(self) -> 'DiscordMessageBuilder':
self.message.author_name = self.raw_message.author.name
def set_author_name(self, value: str):
self.message.author_name = value
return self
def set_content(self) -> 'DiscordMessageBuilder':
self.message.content = self.raw_message.content
def set_content(self, value: str):
self.message.content = value
return self
def set_image_urls(self) -> 'DiscordMessageBuilder':
self.message.image_urls = [
i.url
for i in self.raw_message.attachments
if i.content_type in ('image/jpeg', 'image/png', 'image/webp', 'image/gif')
]
def set_image_urls(self, value: list[str]):
self.message.image_urls = value
return self
class MessengerTypes(Enum):
DISCORD = DiscordMessageBuilder
class IMessageAdapter(ABC):
@abstractmethod
def create_message(self, message: object) -> IClientMessage:
pass
@staticmethod
def validate_image_urls(urls_list: list[Attachment]) -> list[str]:
supported_image_formats = ('image/jpeg', 'image/png', 'image/webp', 'image/gif')
return [i_attachment.url for i_attachment in urls_list if i_attachment.content_type in supported_image_formats]
class DiscordMessageAdapter(IMessageAdapter):
def create_message(self, message: Message) -> IClientMessage:
client_message = ClientMessage()
message_builder = DiscordMessageBuilder(client_message)
urls_list = self.validate_image_urls(message.attachments)
message_builder.set_content(message.content)\
.set_author_name(message.author.name)\
.set_image_urls(urls_list)
return client_message
if __name__ == "__main__":
+39
View File
@@ -0,0 +1,39 @@
import asyncio
from discord import Message
from reginaldCog.messenger_clients.messenger_client import ClientMessage, DiscordMessageAdapter as MessengerDiscordAdapter
from reginaldCog.llm_clients.llm_client import LMMClientType, MessengerClientMessageAdapter
class MessageService:
def __init__(self, message: Message, llm_client: LMMClientType = LMMClientType.OPENAI):
self.message = message
self.llm_client = llm_client
async def get_llm_response(self) -> str:
# Adapt discord.Message to ClientMessage domain object
client_message: ClientMessage = MessengerDiscordAdapter().create_message(self.message)
# Create prompt and prompt builder for this LLM client
prompt = self.llm_client.value.prompt_class()
prompt_builder = self.llm_client.value.prompt_builder_class(prompt)
# Adapt the messenger client message into LLM message and add it to prompt
llm_message = MessengerClientMessageAdapter(client_message, self.llm_client).to_message()
prompt_builder.add_message(llm_message)
# Call the LLM client; run in executor if method is blocking sync
llm_client_instance = self.llm_client.value()
loop = asyncio.get_running_loop()
# Assuming get_response is blocking - run in executor:
response = await loop.run_in_executor(None, llm_client_instance.get_response, prompt)
# Extract plain text from the response (assuming OpenAIResponseAdapter is present)
from reginaldCog.llm_clients.llm_client import OpenAIResponseAdapter
response_adapter = OpenAIResponseAdapter(response)
message_obj = response_adapter.to_message()
# Concatenate all textual outputs for sending to Discord
texts = [item.get("text", "") for item in message_obj.content.content_items if item.get("type") == "output_text"]
return "\n".join(texts) if texts else "Sorry, no response generated."