From c1b5a57429083a10b508e13dd21e53da4f4e9c43 Mon Sep 17 00:00:00 2001 From: Dale Null Date: Tue, 3 Feb 2026 10:17:15 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E5=B0=86=20MessageSession=20?= =?UTF-8?q?=E7=9A=84=20platform=5Fid=20=E6=94=B9=E4=B8=BA=20init=3DFalse?= =?UTF-8?q?=EF=BC=8C=E5=AE=9E=E4=BE=8B=E5=8C=96=E6=97=B6=E6=97=A0=E9=9C=80?= =?UTF-8?q?=E4=BC=A0=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: aider (openai/gpt-5.2) --- astrbot/core/platform/message_session.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/astrbot/core/platform/message_session.py b/astrbot/core/platform/message_session.py index 982a844c2e..b282b307ae 100644 --- a/astrbot/core/platform/message_session.py +++ b/astrbot/core/platform/message_session.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field from astrbot.core.platform.message_type import MessageType @@ -13,7 +13,7 @@ class MessageSession: """平台适配器实例的唯一标识符。自 AstrBot v4.0.0 起,该字段实际为 platform_id。""" message_type: MessageType session_id: str - platform_id: str | None = None + platform_id: str = field(init=False) def __str__(self): return f"{self.platform_id}:{self.message_type.value}:{self.session_id}" From d0e2f386f04e73dcfae1f66d8d0de302f5705479 Mon Sep 17 00:00:00 2001 From: Dale Null Date: Tue, 3 Feb 2026 10:40:21 +0800 Subject: [PATCH 2/6] =?UTF-8?q?refactor:=20=E5=B0=86=20isinstance=20?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E6=94=B9=E4=B8=BA=E5=85=83=E7=BB=84=E3=80=81?= =?UTF-8?q?=E5=B0=86=E9=BB=98=E8=AE=A4=E6=A8=A1=E5=9E=8B=E5=80=BC=E8=AE=BE?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E5=AD=97=E7=AC=A6=E4=B8=B2=E3=80=81=E5=B0=86?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=B3=A8=E8=A7=A3=E6=94=B9=E4=B8=BA=20Any=20?= =?UTF-8?q?=E5=B9=B6=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/provider/sources/fishaudio_tts_api_source.py | 2 +- astrbot/core/star/filter/custom_filter.py | 4 ++-- astrbot/core/star/register/star_handler.py | 2 +- astrbot/dashboard/routes/knowledge_base.py | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/astrbot/core/provider/sources/fishaudio_tts_api_source.py b/astrbot/core/provider/sources/fishaudio_tts_api_source.py index e246e00ede..70eabd2894 100644 --- a/astrbot/core/provider/sources/fishaudio_tts_api_source.py +++ b/astrbot/core/provider/sources/fishaudio_tts_api_source.py @@ -63,7 +63,7 @@ def __init__( self.headers = { "Authorization": f"Bearer {self.chosen_api_key}", } - self.set_model(provider_config.get("model", None)) + self.set_model(provider_config.get("model", "")) async def _get_reference_id_by_character(self, character: str) -> str | None: """获取角色的reference_id diff --git a/astrbot/core/star/filter/custom_filter.py b/astrbot/core/star/filter/custom_filter.py index ff2df9bcde..d57b5cac04 100644 --- a/astrbot/core/star/filter/custom_filter.py +++ b/astrbot/core/star/filter/custom_filter.py @@ -37,7 +37,7 @@ def __and__(self, other): class CustomFilterOr(CustomFilter): def __init__(self, filter1: CustomFilter, filter2: CustomFilter): super().__init__() - if not isinstance(filter1, CustomFilter | CustomFilterAnd | CustomFilterOr): + if not isinstance(filter1, (CustomFilter, CustomFilterAnd, CustomFilterOr)): raise ValueError( "CustomFilter lass can only operate with other CustomFilter.", ) @@ -51,7 +51,7 @@ def filter(self, event: AstrMessageEvent, cfg: AstrBotConfig) -> bool: class CustomFilterAnd(CustomFilter): def __init__(self, filter1: CustomFilter, filter2: CustomFilter): super().__init__() - if not isinstance(filter1, CustomFilter | CustomFilterAnd | CustomFilterOr): + if not isinstance(filter1, (CustomFilter, CustomFilterAnd, CustomFilterOr)): raise ValueError( "CustomFilter lass can only operate with other CustomFilter.", ) diff --git a/astrbot/core/star/register/star_handler.py b/astrbot/core/star/register/star_handler.py index 4d9e2bd87f..eefbcedb78 100644 --- a/astrbot/core/star/register/star_handler.py +++ b/astrbot/core/star/register/star_handler.py @@ -150,7 +150,7 @@ def register_custom_filter(custom_type_filter, *args, **kwargs): if args: raise_error = args[0] - if not isinstance(custom_filter, CustomFilterAnd | CustomFilterOr): + if not isinstance(custom_filter, (CustomFilterAnd, CustomFilterOr)): custom_filter = custom_filter(raise_error) def decorator(awaitable): diff --git a/astrbot/dashboard/routes/knowledge_base.py b/astrbot/dashboard/routes/knowledge_base.py index 537a81f0bd..25bc2cf347 100644 --- a/astrbot/dashboard/routes/knowledge_base.py +++ b/astrbot/dashboard/routes/knowledge_base.py @@ -4,6 +4,7 @@ import os import traceback import uuid +from typing import Any import aiofiles from quart import request @@ -75,7 +76,7 @@ def _init_task(self, task_id: str, status: str = "pending") -> None: } def _set_task_result( - self, task_id: str, status: str, result: any = None, error: str | None = None + self, task_id: str, status: str, result: Any = None, error: str | None = None ) -> None: self.upload_tasks[task_id] = { "status": status, From 20c5a8e612d68b9afd03ad420ceaeb9987216a75 Mon Sep 17 00:00:00 2001 From: Dale Null Date: Tue, 3 Feb 2026 13:52:50 +0800 Subject: [PATCH 3/6] =?UTF-8?q?refactor:=20=E4=B8=BA=20=5Fserialize=5Fjob?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=20dict?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/dashboard/routes/cron.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astrbot/dashboard/routes/cron.py b/astrbot/dashboard/routes/cron.py index 6bef938590..8861fc5cca 100644 --- a/astrbot/dashboard/routes/cron.py +++ b/astrbot/dashboard/routes/cron.py @@ -23,7 +23,7 @@ def __init__( ] self.register_routes() - def _serialize_job(self, job): + def _serialize_job(self, job) -> dict: data = job.model_dump() if hasattr(job, "model_dump") else job.__dict__ for k in ["created_at", "updated_at", "last_run_at", "next_run_time"]: if isinstance(data.get(k), datetime): From 65aea8aa9c500e1fe1c660f94af1e684eab437e4 Mon Sep 17 00:00:00 2001 From: Dale Null Date: Thu, 5 Feb 2026 09:09:33 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=E4=BD=BF=E7=94=A8=20cast=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E7=99=BE=E5=BA=A6=20AIP=20=E7=9A=84=20msg=20?= =?UTF-8?q?=E5=B9=B6=E5=AF=B9=20psutil=5Faddr=20=E5=BC=95=E5=85=A5=20type:?= =?UTF-8?q?=20ignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: aider (openai/gpt-5.2) --- .../pipeline/content_safety_check/strategies/baidu_aip.py | 5 ++++- astrbot/dashboard/server.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py b/astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py index bfa82de0e6..dd8ca629e6 100644 --- a/astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py +++ b/astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py @@ -1,5 +1,7 @@ """使用此功能应该先 pip install baidu-aip""" +from typing import Any, cast + from aip import AipContentCensor from . import ContentSafetyStrategy @@ -23,7 +25,8 @@ def check(self, content: str) -> tuple[bool, str]: count = len(res["data"]) parts = [f"百度审核服务发现 {count} 处违规:\n"] for i in res["data"]: - parts.append(f"{i['msg']};\n") + # 百度 AIP 返回结构是动态 dict;类型检查时 i 可能被推断为序列,转成 dict 后用 get 取字段 + parts.append(f"{cast(dict[str, Any], i).get('msg', '')};\n") parts.append("\n判断结果:" + res["conclusion"]) info = "".join(parts) return False, info diff --git a/astrbot/dashboard/server.py b/astrbot/dashboard/server.py index 57b8ad7412..8c38333fe6 100644 --- a/astrbot/dashboard/server.py +++ b/astrbot/dashboard/server.py @@ -9,7 +9,7 @@ from flask.json.provider import DefaultJSONProvider from hypercorn.asyncio import serve from hypercorn.config import Config as HyperConfig -from psutil._common import addr as psutil_addr +from psutil._common import addr as psutil_addr # type: ignore[attr-defined] from quart import Quart, g, jsonify, request from quart.logging import default_handler From db95a96c51f481daa1da29cf76cc28fb71c3fd85 Mon Sep 17 00:00:00 2001 From: Dale Null Date: Thu, 5 Feb 2026 09:17:19 +0800 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=E5=BC=95=E5=85=A5=20=5FAddrWit?= =?UTF-8?q?hPort=20=E5=8D=8F=E8=AE=AE=E5=B9=B6=E6=9B=BF=E6=8D=A2=20conn.la?= =?UTF-8?q?ddr=20=E7=9A=84=20cast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: aider (openai/gpt-5.2) --- astrbot/dashboard/server.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/astrbot/dashboard/server.py b/astrbot/dashboard/server.py index 8c38333fe6..5378f1a856 100644 --- a/astrbot/dashboard/server.py +++ b/astrbot/dashboard/server.py @@ -2,14 +2,13 @@ import logging import os import socket -from typing import cast +from typing import Protocol, cast import jwt import psutil from flask.json.provider import DefaultJSONProvider from hypercorn.asyncio import serve from hypercorn.config import Config as HyperConfig -from psutil._common import addr as psutil_addr # type: ignore[attr-defined] from quart import Quart, g, jsonify, request from quart.logging import default_handler @@ -29,6 +28,11 @@ from .routes.subagent import SubAgentRoute from .routes.t2i import T2iRoute + +class _AddrWithPort(Protocol): + port: int + + APP: Quart @@ -168,7 +172,7 @@ def get_process_using_port(self, port: int) -> str: """获取占用端口的进程详细信息""" try: for conn in psutil.net_connections(kind="inet"): - if cast(psutil_addr, conn.laddr).port == port: + if cast(_AddrWithPort, conn.laddr).port == port: try: process = psutil.Process(conn.pid) # 获取详细信息 From ab37cf5321afda948f99bc248356d07aa8aa7191 Mon Sep 17 00:00:00 2001 From: Dale Null Date: Thu, 5 Feb 2026 09:48:02 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=E5=9C=A8=E6=9E=84=E5=BB=BA=20AstrBo?= =?UTF-8?q?tMessage=20=E6=97=B6=E5=AF=B9=20ctx.channel=20=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E4=B8=BA=20None=20=E8=BF=9B=E8=A1=8C=E5=85=9C?= =?UTF-8?q?=E5=BA=95=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: aider (openai/gpt-5.2) --- .../sources/discord/discord_platform_adapter.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/astrbot/core/platform/sources/discord/discord_platform_adapter.py b/astrbot/core/platform/sources/discord/discord_platform_adapter.py index d81afd1abd..ed9899f6f6 100644 --- a/astrbot/core/platform/sources/discord/discord_platform_adapter.py +++ b/astrbot/core/platform/sources/discord/discord_platform_adapter.py @@ -444,9 +444,20 @@ async def dynamic_callback( logger.warning(f"[Discord] 指令 '{cmd_name}' defer 失败: {e}") # 2. 构建 AstrBotMessage + channel = ctx.channel abm = AstrBotMessage() - abm.type = self._get_message_type(ctx.channel, ctx.guild_id) - abm.group_id = self._get_channel_id(ctx.channel) + if channel is not None: + abm.type = self._get_message_type(channel, ctx.guild_id) + abm.group_id = self._get_channel_id(channel) + else: + # 防守式兜底:channel 取不到时,仍能根据 guild_id/channel_id 推断会话信息 + abm.type = ( + MessageType.GROUP_MESSAGE + if ctx.guild_id is not None + else MessageType.FRIEND_MESSAGE + ) + abm.group_id = str(ctx.channel_id) + abm.message_str = message_str_for_filter abm.sender = MessageMember( user_id=str(ctx.author.id),