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/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}" 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), 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/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): 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, diff --git a/astrbot/dashboard/server.py b/astrbot/dashboard/server.py index 57b8ad7412..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 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) # 获取详细信息