From 4021ce84752809f38c864e1b51f368bc4ecb278a Mon Sep 17 00:00:00 2001 From: Chen Jiasheng <2569244273@qq.com> Date: Sat, 12 Jul 2025 21:31:05 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E9=80=82=E9=85=8D=E5=99=A8=20logo=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/platform/platform_metadata.py | 2 + astrbot/core/platform/register.py | 3 ++ astrbot/dashboard/routes/config.py | 51 +++++++++++++++++++++- dashboard/src/views/PlatformPage.vue | 8 ++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/astrbot/core/platform/platform_metadata.py b/astrbot/core/platform/platform_metadata.py index dd0e93fec..8ace67136 100644 --- a/astrbot/core/platform/platform_metadata.py +++ b/astrbot/core/platform/platform_metadata.py @@ -14,3 +14,5 @@ class PlatformMetadata: """平台的默认配置模板""" adapter_display_name: str = None """显示在 WebUI 配置页中的平台名称,如空则是 name""" + logo_path: str = None + """平台适配器的 logo 文件路径(相对于插件目录或绝对路径)""" diff --git a/astrbot/core/platform/register.py b/astrbot/core/platform/register.py index fa65392a8..f385a3f35 100644 --- a/astrbot/core/platform/register.py +++ b/astrbot/core/platform/register.py @@ -13,10 +13,12 @@ def register_platform_adapter( desc: str, default_config_tmpl: dict = None, adapter_display_name: str = None, + logo_path: str = None, ): """用于注册平台适配器的带参装饰器。 default_config_tmpl 指定了平台适配器的默认配置模板。用户填写好后将会作为 platform_config 传入你的 Platform 类的实现类。 + logo_path 指定了平台适配器的 logo 文件路径,可以是相对于插件目录的路径或绝对路径。 """ def decorator(cls): @@ -39,6 +41,7 @@ def decorator(cls): description=desc, default_config_tmpl=default_config_tmpl, adapter_display_name=adapter_display_name, + logo_path=logo_path, ) platform_registry.append(pm) platform_cls_map[adapter_name] = cls diff --git a/astrbot/dashboard/routes/config.py b/astrbot/dashboard/routes/config.py index 1dbe4de4a..1deddce49 100644 --- a/astrbot/dashboard/routes/config.py +++ b/astrbot/dashboard/routes/config.py @@ -5,7 +5,7 @@ from astrbot.core.config.default import CONFIG_METADATA_2, DEFAULT_VALUE_MAP from astrbot.core.config.astrbot_config import AstrBotConfig from astrbot.core.core_lifecycle import AstrBotCoreLifecycle -from astrbot.core.platform.register import platform_registry +from astrbot.core.platform.register import platform_registry, platform_cls_map from astrbot.core.provider.register import provider_registry from astrbot.core.star.star import star_registry from astrbot.core import logger @@ -474,6 +474,52 @@ async def get_llm_tools(self): tools = tool_mgr.get_func_desc_openai_style() return Response().ok(tools).__dict__ + async def _register_platform_logo(self, platform, platform_default_tmpl): + """注册平台logo文件并生成访问令牌""" + if not platform.logo_path: + return + + try: + from astrbot.core import file_token_service + import os + import inspect + + # 获取平台适配器类 + platform_cls = platform_cls_map.get(platform.name) + if not platform_cls: + logger.warning(f"Platform class not found for {platform.name}") + return + + # 获取插件目录路径 + module_file = inspect.getfile(platform_cls) + plugin_dir = os.path.dirname(module_file) + + # 解析logo文件路径 + logo_file_path = ( + platform.logo_path + if os.path.isabs(platform.logo_path) + else os.path.join(plugin_dir, platform.logo_path) + ) + + # 检查文件是否存在并注册令牌 + if os.path.exists(logo_file_path): + logo_token = await file_token_service.register_file( + logo_file_path, timeout=3600 + ) + platform_default_tmpl[platform.name]["logo_token"] = logo_token + logger.debug(f"Logo token registered for platform {platform.name}") + else: + logger.warning( + f"Platform {platform.name} logo file not found: {logo_file_path}" + ) + + except (ImportError, AttributeError) as e: + logger.warning(f"Failed to import required modules for platform {platform.name}: {e}") + except (OSError, IOError) as e: + logger.warning(f"File system error for platform {platform.name} logo: {e}") + except Exception as e: + logger.warning(f"Unexpected error registering logo for platform {platform.name}: {e}") + async def _get_astrbot_config(self): config = self.config @@ -481,9 +527,12 @@ async def _get_astrbot_config(self): platform_default_tmpl = CONFIG_METADATA_2["platform_group"]["metadata"][ "platform" ]["config_template"] + for platform in platform_registry: if platform.default_config_tmpl: platform_default_tmpl[platform.name] = platform.default_config_tmpl + # 处理logo信息 + await self._register_platform_logo(platform, platform_default_tmpl) # 服务提供商的默认配置模板注入 provider_default_tmpl = CONFIG_METADATA_2["provider_group"]["metadata"][ diff --git a/dashboard/src/views/PlatformPage.vue b/dashboard/src/views/PlatformPage.vue index d9f8dfed6..7f44ca3d8 100644 --- a/dashboard/src/views/PlatformPage.vue +++ b/dashboard/src/views/PlatformPage.vue @@ -261,6 +261,14 @@ export default { }, getPlatformIcon(name) { + // 首先检查是否有来自插件的 logo_token + const template = this.metadata['platform_group']?.metadata?.platform?.config_template?.[name]; + if (template && template.logo_token) { + // 通过文件服务访问插件提供的 logo + return `/api/file/${template.logo_token}`; + } + + // 原有的硬编码图标逻辑 if (name === 'aiocqhttp' || name === 'qq_official' || name === 'qq_official_webhook') { return new URL('@/assets/images/platform_logos/qq.png', import.meta.url).href } else if (name === 'wecom') { From 8b7056edb93c15a667e6761e7cb1e44b446f923d Mon Sep 17 00:00:00 2001 From: Chen Jiasheng <2569244273@qq.com> Date: Sun, 13 Jul 2025 10:19:55 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B9=B3=E5=8F=B0logo?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6=E5=B9=B6=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=B9=B6=E8=A1=8C=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/dashboard/routes/config.py | 44 ++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/astrbot/dashboard/routes/config.py b/astrbot/dashboard/routes/config.py index 1deddce49..af19cdde7 100644 --- a/astrbot/dashboard/routes/config.py +++ b/astrbot/dashboard/routes/config.py @@ -1,5 +1,7 @@ import typing import traceback +import os +import inspect from .route import Route, Response, RouteContext from quart import request from astrbot.core.config.default import CONFIG_METADATA_2, DEFAULT_VALUE_MAP @@ -8,7 +10,7 @@ from astrbot.core.platform.register import platform_registry, platform_cls_map from astrbot.core.provider.register import provider_registry from astrbot.core.star.star import star_registry -from astrbot.core import logger +from astrbot.core import logger, file_token_service from astrbot.core.provider import Provider import asyncio @@ -156,6 +158,7 @@ def __init__( super().__init__(context) self.core_lifecycle = core_lifecycle self.config: AstrBotConfig = core_lifecycle.astrbot_config + self._logo_token_cache = {} # 缓存logo token,避免重复注册 self.routes = { "/config/get": ("GET", self.get_configs), "/config/astrbot/update": ("POST", self.post_astrbot_configs), @@ -480,9 +483,18 @@ async def _register_platform_logo(self, platform, platform_default_tmpl): return try: - from astrbot.core import file_token_service - import os - import inspect + # 检查缓存 + cache_key = f"{platform.name}:{platform.logo_path}" + if cache_key in self._logo_token_cache: + cached_token = self._logo_token_cache[cache_key] + # 确保platform_default_tmpl[platform.name]存在且为字典 + if platform.name not in platform_default_tmpl: + platform_default_tmpl[platform.name] = {} + elif not isinstance(platform_default_tmpl[platform.name], dict): + platform_default_tmpl[platform.name] = {} + platform_default_tmpl[platform.name]["logo_token"] = cached_token + logger.debug(f"Using cached logo token for platform {platform.name}") + return # 获取平台适配器类 platform_cls = platform_cls_map.get(platform.name) @@ -506,7 +518,18 @@ async def _register_platform_logo(self, platform, platform_default_tmpl): logo_token = await file_token_service.register_file( logo_file_path, timeout=3600 ) + + # 确保platform_default_tmpl[platform.name]存在且为字典 + if platform.name not in platform_default_tmpl: + platform_default_tmpl[platform.name] = {} + elif not isinstance(platform_default_tmpl[platform.name], dict): + platform_default_tmpl[platform.name] = {} + platform_default_tmpl[platform.name]["logo_token"] = logo_token + + # 缓存token + self._logo_token_cache[cache_key] = logo_token + logger.debug(f"Logo token registered for platform {platform.name}") else: logger.warning( @@ -528,11 +551,20 @@ async def _get_astrbot_config(self): "platform" ]["config_template"] + # 收集需要注册logo的平台 + logo_registration_tasks = [] for platform in platform_registry: if platform.default_config_tmpl: platform_default_tmpl[platform.name] = platform.default_config_tmpl - # 处理logo信息 - await self._register_platform_logo(platform, platform_default_tmpl) + # 收集logo注册任务 + if platform.logo_path: + logo_registration_tasks.append( + self._register_platform_logo(platform, platform_default_tmpl) + ) + + # 并行执行logo注册 + if logo_registration_tasks: + await asyncio.gather(*logo_registration_tasks, return_exceptions=True) # 服务提供商的默认配置模板注入 provider_default_tmpl = CONFIG_METADATA_2["provider_group"]["metadata"][ From f5385a70c530166d5ffc9858cd298abbd4116a80 Mon Sep 17 00:00:00 2001 From: kterna <2569244273@qq.com> Date: Thu, 11 Sep 2025 10:03:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E7=BB=9D=E5=AF=B9=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/platform/platform_metadata.py | 2 +- astrbot/core/platform/register.py | 2 +- astrbot/dashboard/routes/config.py | 6 +----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/astrbot/core/platform/platform_metadata.py b/astrbot/core/platform/platform_metadata.py index 8ace67136..3d3d3566e 100644 --- a/astrbot/core/platform/platform_metadata.py +++ b/astrbot/core/platform/platform_metadata.py @@ -15,4 +15,4 @@ class PlatformMetadata: adapter_display_name: str = None """显示在 WebUI 配置页中的平台名称,如空则是 name""" logo_path: str = None - """平台适配器的 logo 文件路径(相对于插件目录或绝对路径)""" + """平台适配器的 logo 文件路径(相对于插件目录)""" diff --git a/astrbot/core/platform/register.py b/astrbot/core/platform/register.py index f385a3f35..97c33a43e 100644 --- a/astrbot/core/platform/register.py +++ b/astrbot/core/platform/register.py @@ -18,7 +18,7 @@ def register_platform_adapter( """用于注册平台适配器的带参装饰器。 default_config_tmpl 指定了平台适配器的默认配置模板。用户填写好后将会作为 platform_config 传入你的 Platform 类的实现类。 - logo_path 指定了平台适配器的 logo 文件路径,可以是相对于插件目录的路径或绝对路径。 + logo_path 指定了平台适配器的 logo 文件路径,是相对于插件目录的路径。 """ def decorator(cls): diff --git a/astrbot/dashboard/routes/config.py b/astrbot/dashboard/routes/config.py index af19cdde7..4944785a7 100644 --- a/astrbot/dashboard/routes/config.py +++ b/astrbot/dashboard/routes/config.py @@ -507,11 +507,7 @@ async def _register_platform_logo(self, platform, platform_default_tmpl): plugin_dir = os.path.dirname(module_file) # 解析logo文件路径 - logo_file_path = ( - platform.logo_path - if os.path.isabs(platform.logo_path) - else os.path.join(plugin_dir, platform.logo_path) - ) + logo_file_path = os.path.join(plugin_dir, platform.logo_path) # 检查文件是否存在并注册令牌 if os.path.exists(logo_file_path):