diff --git a/astrbot/core/platform/sources/webchat/webchat_adapter.py b/astrbot/core/platform/sources/webchat/webchat_adapter.py index d78bfeadf..87e9d5f7b 100644 --- a/astrbot/core/platform/sources/webchat/webchat_adapter.py +++ b/astrbot/core/platform/sources/webchat/webchat_adapter.py @@ -1,10 +1,11 @@ import time import asyncio import uuid +import os from typing import Awaitable, Any from astrbot.api.platform import Platform, AstrBotMessage, MessageMember, MessageType, PlatformMetadata from astrbot.api.event import MessageChain -from astrbot.api.message_components import * # noqa: F403 +from astrbot.api.message_components import Plain, Image # noqa: F403 from astrbot.api import logger from astrbot.core import web_chat_queue, web_chat_back_queue from .webchat_event import WebChatMessageEvent @@ -29,6 +30,7 @@ class WebChatAdapter(Platform): self.config = platform_config self.settings = platform_settings self.unique_session = platform_settings['unique_session'] + self.imgs_dir = "data/webchat/imgs" self.metadata = PlatformMetadata( "webchat", @@ -45,7 +47,7 @@ class WebChatAdapter(Platform): await super().send_by_session(session, message_chain) async def convert_message(self, data: tuple) -> AstrBotMessage: - username, cid, message = data + username, cid, payload = data abm = AstrBotMessage() @@ -58,8 +60,20 @@ class WebChatAdapter(Platform): abm.session_id = f"webchat!{username}!{cid}" abm.message_id = str(uuid.uuid4()) - abm.message = [Plain(message)] - message_str = message + abm.message = [] + + if payload['message']: + abm.message.append(Plain(payload['message'])) + if payload['image_url']: + if isinstance(payload['image_url'], list): + for img in payload['image_url']: + abm.message.append(Image.fromFileSystem(os.path.join(self.imgs_dir, img))) + else: + abm.message.append(Image.fromFileSystem(os.path.join(self.imgs_dir, payload['image_url']))) + + logger.debug(f"WebChatAdapter: {abm.message}") + + message_str = payload['message'] abm.timestamp = int(time.time()) abm.message_str = message_str abm.raw_message = data diff --git a/astrbot/core/provider/sources/openai_source.py b/astrbot/core/provider/sources/openai_source.py index b0c9f0a58..7e601e958 100644 --- a/astrbot/core/provider/sources/openai_source.py +++ b/astrbot/core/provider/sources/openai_source.py @@ -209,6 +209,8 @@ class ProviderOpenAIOfficial(Provider): image_path = await download_image_by_url(image_url) image_data = await self.encode_image_bs64(image_path) else: + if image_url.startswith("file:///"): + image_url = image_url.replace("file:///", "") image_data = await self.encode_image_bs64(image_url) user_content["content"].append({"type": "image_url", "image_url": {"url": image_data}}) return user_content diff --git a/astrbot/dashboard/routes/chat.py b/astrbot/dashboard/routes/chat.py index 735673976..cef7e563f 100644 --- a/astrbot/dashboard/routes/chat.py +++ b/astrbot/dashboard/routes/chat.py @@ -16,7 +16,8 @@ class ChatRoute(Route): '/chat/conversations': ('GET', self.get_conversations), '/chat/get_conversation': ('GET', self.get_conversation), '/chat/delete_conversation': ('GET', self.delete_conversation), - '/chat/get_file': ('GET', self.get_file) + '/chat/get_file': ('GET', self.get_file), + '/chat/post_image': ('POST', self.post_image) } self.db = db self.register_routes() @@ -32,25 +33,43 @@ class ChatRoute(Route): return QuartResponse(f.read(), mimetype="image/jpeg") except FileNotFoundError: return Response().error("File not found").__dict__ + + async def post_image(self): + post_data = await request.files + if 'file' not in post_data: + return Response().error("Missing key: file").__dict__ + + file = post_data['file'] + filename = str(uuid.uuid4()) + ".jpg" + path = os.path.join(self.imgs_dir, filename) + await file.save(path) + + return Response().ok(data={ + 'filename': filename + }).__dict__ async def chat(self): username = g.get('username', 'guest') post_data = await request.json - if 'message' not in post_data: - return Response().error("Missing key: message").__dict__ + if 'message' not in post_data and 'image_url' not in post_data: + return Response().error("Missing key: message or image_url").__dict__ if 'conversation_id' not in post_data: return Response().error("Missing key: conversation_id").__dict__ message = post_data['message'] conversation_id = post_data['conversation_id'] - if not message: - return Response().error("Message is empty").__dict__ + image_url = post_data.get('image_url') + if not message and not image_url: + return Response().error("Message and image_url are empty").__dict__ if not conversation_id: return Response().error("conversation_id is empty").__dict__ - await web_chat_queue.put((username, conversation_id, message)) + await web_chat_queue.put((username, conversation_id, { + 'message': message, + 'image_url': image_url # list + })) async def stream(): ret = [] @@ -72,14 +91,14 @@ class ChatRoute(Route): except BaseException as e: print(e) history = [] - history.append({ + + new_his = { 'type': 'user', 'message': message - }) - # history.append({ - # 'type': 'bot', - # 'message': ret - # }) + } + if image_url: + new_his['image_url'] = image_url + history.append(new_his) for r in ret: history.append({ 'type': 'bot', diff --git a/dashboard/src/views/ChatPage.vue b/dashboard/src/views/ChatPage.vue index 8362d15f4..f4cb9b0e5 100644 --- a/dashboard/src/views/ChatPage.vue +++ b/dashboard/src/views/ChatPage.vue @@ -16,32 +16,27 @@ marked.setOptions({