Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions astrbot/cli/commands/cmd_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from astrbot.core.utils.auth_password import (
hash_dashboard_password,
hash_legacy_dashboard_password,
hash_md5_dashboard_password,
validate_dashboard_password,
)

Expand Down Expand Up @@ -147,7 +147,7 @@ def _set_dashboard_password(config: dict[str, Any], raw_password: str) -> None:
_set_nested_item(
config,
"dashboard.password",
hash_legacy_dashboard_password(raw_password),
hash_md5_dashboard_password(raw_password),
)
_set_nested_item(config, "dashboard.password_storage_upgraded", True)
_set_nested_item(config, "dashboard.password_change_required", False)
Expand Down
12 changes: 5 additions & 7 deletions astrbot/core/config/astrbot_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from astrbot.core.utils.auth_password import (
generate_dashboard_password,
hash_dashboard_password,
hash_legacy_dashboard_password,
hash_md5_dashboard_password,
validate_dashboard_password,
)

Expand Down Expand Up @@ -64,11 +64,11 @@ def __init__(
conf_str = conf_str[1:]
conf = json.loads(conf_str)
dashboard_conf = conf.get("dashboard")
legacy_dashboard_password_change_required = bool(
stored_dashboard_password_change_required = bool(
isinstance(dashboard_conf, dict)
and dashboard_conf.get("password_change_required", False)
)
if legacy_dashboard_password_change_required:
if stored_dashboard_password_change_required:
object.__setattr__(
self,
"_dashboard_password_change_required_from_config",
Expand All @@ -87,7 +87,7 @@ def __init__(
elif (
"dashboard" in conf
and isinstance(conf["dashboard"], dict)
and legacy_dashboard_password_change_required
and stored_dashboard_password_change_required
and conf["dashboard"].get("pbkdf2_password")
):
self._reset_generated_dashboard_password(conf)
Expand All @@ -103,9 +103,7 @@ def _reset_generated_dashboard_password(self, conf: dict) -> None:
conf["dashboard"]["pbkdf2_password"] = hash_dashboard_password(
generated_password
)
conf["dashboard"]["password"] = hash_legacy_dashboard_password(
generated_password
)
conf["dashboard"]["password"] = hash_md5_dashboard_password(generated_password)
conf["dashboard"]["password_storage_upgraded"] = True
conf["dashboard"]["password_change_required"] = True
object.__setattr__(
Expand Down
2 changes: 1 addition & 1 deletion astrbot/core/platform/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ async def webhook_callback(self, request: Any) -> Any:
当 Dashboard 收到 /api/platform/webhook/{uuid} 请求时,会调用此方法。

Args:
request: Quart 请求对象
request: webhook 请求对象

Returns:
响应内容,格式取决于具体平台的要求
Expand Down
2 changes: 1 addition & 1 deletion astrbot/core/platform/sources/lark/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ async def handle_callback(self, request) -> tuple[dict, int] | dict:
"""处理 webhook 回调,可被统一 webhook 入口复用

Args:
request: Quart 请求对象
request: webhook 请求对象

Returns:
响应数据
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
from binascii import Error as BinasciiError
from typing import cast

import quart
from botpy import BotAPI, BotHttp, BotWebSocket, Client, ConnectionSession, Token
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.asymmetric import ed25519

from astrbot.api import logger
from astrbot.core.platform.webhook_server import FastAPIWebhookServer

# remove logger handler
for handler in logging.root.handlers[:]:
Expand Down Expand Up @@ -90,7 +90,7 @@ def __init__(
self.api: BotAPI = BotAPI(http=self.http)
self.token = Token(self.appid, self.secret)

self.server = quart.Quart(__name__)
self.server = FastAPIWebhookServer("qq-official-webhook")
self.server.add_url_rule(
"/astrbot-qo-webhook/callback",
view_func=self.callback,
Expand Down Expand Up @@ -159,15 +159,15 @@ def pop_extra_data(self, message_id: str) -> dict:
"""Pop and return extra fields cached from the raw webhook payload for a given message ID."""
return self._extra_data_cache.pop(message_id, {})

async def callback(self):
async def callback(self, request):
"""内部服务器的回调入口"""
return await self.handle_callback(quart.request)
return await self.handle_callback(request)

async def handle_callback(self, request) -> dict:
"""处理 webhook 回调,可被统一 webhook 入口复用

Args:
request: Quart 请求对象
request: FastAPI webhook request 对象

Returns:
响应数据
Expand Down
24 changes: 10 additions & 14 deletions astrbot/core/platform/sources/slack/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
import hashlib
import hmac
import json
import logging
from collections.abc import Callable
from typing import cast

from quart import Quart, Response, request
from fastapi.responses import Response
from slack_sdk.socket_mode.aiohttp import SocketModeClient
from slack_sdk.socket_mode.async_client import AsyncBaseSocketModeClient
from slack_sdk.socket_mode.request import SocketModeRequest
from slack_sdk.socket_mode.response import SocketModeResponse
from slack_sdk.web.async_client import AsyncWebClient

from astrbot.api import logger
from astrbot.core.platform.webhook_server import FastAPIWebhookServer


class SlackWebhookClient:
"""Slack Webhook 模式客户端,使用 Quart 作为 Web 服务器"""
"""Slack Webhook 模式客户端,使用 FastAPI 作为 Web 服务器"""

def __init__(
self,
Expand All @@ -35,20 +35,16 @@ def __init__(
self.path = path
self.event_handler = event_handler

self.app = Quart(__name__)
self.app = FastAPIWebhookServer("slack-webhook")
self._setup_routes()

# 禁用 Quart 的默认日志输出
logging.getLogger("quart.app").setLevel(logging.WARNING)
logging.getLogger("quart.serving").setLevel(logging.WARNING)

self.shutdown_event = asyncio.Event()

def _setup_routes(self) -> None:
"""设置路由"""

@self.app.route(self.path, methods=["POST"])
async def slack_events():
async def slack_events(request):
"""内部服务器的 POST 回调入口"""
return await self.handle_callback(request)

Expand All @@ -61,7 +57,7 @@ async def handle_callback(self, req):
"""处理 Slack 回调请求,可被统一 webhook 入口复用

Args:
req: Quart 请求对象
req: webhook 请求对象

Returns:
Response 对象或字典
Expand All @@ -75,7 +71,7 @@ async def handle_callback(self, req):
timestamp = req.headers.get("X-Slack-Request-Timestamp")
signature = req.headers.get("X-Slack-Signature")
if not timestamp or not signature:
return Response("Missing headers", status=400)
return Response("Missing headers", status_code=400)
# Calculate the HMAC signature
sig_basestring = f"v0:{timestamp}:{body.decode('utf-8')}"
my_signature = (
Expand All @@ -89,7 +85,7 @@ async def handle_callback(self, req):
# Verify the signature
if not hmac.compare_digest(my_signature, signature):
logger.warning("Slack request signature verification failed")
return Response("Invalid signature", status=400)
return Response("Invalid signature", status_code=400)
logger.info(f"Received Slack event: {event_data}")

# 处理 URL 验证事件
Expand All @@ -99,11 +95,11 @@ async def handle_callback(self, req):
if self.event_handler and event_data.get("type") == "event_callback":
await self.event_handler(event_data)

return Response("", status=200)
return Response("", status_code=200)

except Exception as e:
logger.error(f"处理 Slack 事件时出错: {e}")
return Response("Internal Server Error", status=500)
return Response("Internal Server Error", status_code=500)

async def start(self) -> None:
"""启动 Webhook 服务器"""
Expand Down
16 changes: 8 additions & 8 deletions astrbot/core/platform/sources/wecom/wecom_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from typing import Any, cast
from urllib.parse import unquote

import quart
from requests import Response
from wechatpy.enterprise import WeChatClient, parse_message
from wechatpy.enterprise.crypto import WeChatCrypto
Expand All @@ -28,6 +27,7 @@
)
from astrbot.core import logger
from astrbot.core.platform.astr_message_event import MessageSesion
from astrbot.core.platform.webhook_server import FastAPIWebhookServer
from astrbot.core.utils.astrbot_path import get_astrbot_temp_path
from astrbot.core.utils.media_utils import convert_audio_to_wav
from astrbot.core.utils.webhook_utils import log_webhook_info
Expand Down Expand Up @@ -65,7 +65,7 @@ def _extract_wecom_media_filename(disposition: str | None) -> str | None:

class WecomServer:
def __init__(self, event_queue: asyncio.Queue, config: dict) -> None:
self.server = quart.Quart(__name__)
self.server = FastAPIWebhookServer("wecom-webhook")
self.port = int(cast(str, config.get("port")))
self.callback_server_host = config.get("callback_server_host", "0.0.0.0")
self.server.add_url_rule(
Expand All @@ -89,15 +89,15 @@ def __init__(self, event_queue: asyncio.Queue, config: dict) -> None:
self.callback: Callable[[BaseMessage], Awaitable[None]] | None = None
self.shutdown_event = asyncio.Event()

async def verify(self):
async def verify(self, request):
"""内部服务器的 GET 验证入口"""
return await self.handle_verify(quart.request)
return await self.handle_verify(request)

async def handle_verify(self, request) -> str:
"""处理验证请求,可被统一 webhook 入口复用

Args:
request: Quart 请求对象
request: FastAPI webhook request 对象

Returns:
验证响应
Expand All @@ -117,15 +117,15 @@ async def handle_verify(self, request) -> str:
logger.error("验证请求有效性失败,签名异常,请检查配置。")
raise

async def callback_command(self):
async def callback_command(self, request):
"""内部服务器的 POST 回调入口"""
return await self.handle_callback(quart.request)
return await self.handle_callback(request)

async def handle_callback(self, request) -> str:
"""处理回调请求,可被统一 webhook 入口复用

Args:
request: Quart 请求对象
request: FastAPI webhook request 对象

Returns:
响应内容
Expand Down
24 changes: 11 additions & 13 deletions astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
from collections.abc import Callable
from typing import Any

import quart

from astrbot.api import logger
from astrbot.core.platform.webhook_server import FastAPIWebhookServer

from .wecomai_api import WecomAIBotAPIClient
from .wecomai_utils import WecomAIBotConstants
Expand Down Expand Up @@ -38,14 +37,13 @@ def __init__(
self.api_client = api_client
self.message_handler = message_handler

self.app = quart.Quart(__name__)
self.app = FastAPIWebhookServer("wecom-ai-bot-webhook")
self._setup_routes()

self.shutdown_event = asyncio.Event()

def _setup_routes(self) -> None:
"""设置 Quart 路由"""
# 使用 Quart 的 add_url_rule 方法添加路由
"""设置 FastAPI 路由"""
self.app.add_url_rule(
"/webhook/wecom-ai-bot",
view_func=self.verify_url,
Expand All @@ -58,15 +56,15 @@ def _setup_routes(self) -> None:
methods=["POST"],
)

async def verify_url(self):
async def verify_url(self, request):
"""内部服务器的 GET 验证入口"""
return await self.handle_verify(quart.request)
return await self.handle_verify(request)

async def handle_verify(self, request):
"""处理 URL 验证请求,可被统一 webhook 入口复用

Args:
request: Quart 请求对象
request: FastAPI webhook request 对象

Returns:
验证响应元组 (content, status_code, headers)
Expand All @@ -91,15 +89,15 @@ async def handle_verify(self, request):
result = self.api_client.verify_url(msg_signature, timestamp, nonce, echostr)
return result, 200, {"Content-Type": "text/plain"}

async def handle_message(self):
async def handle_message(self, request):
"""内部服务器的 POST 消息回调入口"""
return await self.handle_callback(quart.request)
return await self.handle_callback(request)

async def handle_callback(self, request):
"""处理消息回调,可被统一 webhook 入口复用

Args:
request: Quart 请求对象
request: FastAPI webhook request 对象

Returns:
响应元组 (content, status_code, headers)
Expand Down Expand Up @@ -186,5 +184,5 @@ async def shutdown(self) -> None:
self.shutdown_event.set()

def get_app(self):
"""获取 Quart 应用实例"""
return self.app
"""获取 FastAPI 应用实例"""
return self.app.app
Loading
Loading