mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-01 01:10:21 +08:00
* refactor: migrate to fastapi * structure refactor * fix: pyright fix * refactor: improve error handling and public messages in plugin services * feat(api): refactor API client integration and enhance request handling - Updated API client configuration to use a dedicated HTTP client. - Introduced utility functions for generating options, queries, and form data for API requests. - Refactored multiple API methods to utilize the new utility functions for improved consistency and readability. - Renamed types for clarity and updated import statements accordingly. feat(docs): add script to update OpenAPI JSON from YAML spec - Created a Python script to convert OpenAPI YAML specification to JSON format. - The script supports customizable input and output paths. - Ensured the script handles directory creation for output paths and validates the YAML structure. * fix * feat(auth): implement rate limiting for v1 login endpoint and enhance request handling * Refactor dashboard API routers to use legacy_router for backward compatibility - Changed all instances of dashboard_router to legacy_router across multiple API modules including platform, plugins, providers, sessions, skills, stats, subagents, t2i, tools, updates, and asgi_runtime. - Updated route definitions to ensure existing endpoints remain functional under the new router structure. - Introduced support for Quart request context in asgi_runtime to enhance compatibility with existing Quart-based plugins. - Added a test case to validate the functionality of the new Quart request context handling in plugin extensions. * chore: remove cli test * fix: update dashboard tests for fastapi migration * chore: satisfy ruff checks * fix: update openapi api key scopes * fix: sync config scope chip selection * fix: restore quart dependency * docs: clarify quart plugin api compatibility * docs: update openapi scope documentation * fix: use singular skill openapi scope * fix: hide update service exception details * fix: address fastapi review comments * fix: address dashboard review findings * docs: revert unrelated package deployment changes * docs: update agent api generation guidance * feat: add plugin page web api helpers * docs: add plugin page bridge demo * fix: type plugin upload files * fix: stabilize plugin page uploads * fix: type plugin web request proxy * docs: remove plugin page docs example * fix: authenticate plugin page SSE bridge
111 lines
3.5 KiB
Python
111 lines
3.5 KiB
Python
import json
|
|
from pathlib import Path
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import aiohttp
|
|
|
|
from astrbot.api.platform import AstrBotMessage, MessageType
|
|
from astrbot.core.message.components import (
|
|
File,
|
|
Record,
|
|
)
|
|
|
|
CURRENT_DIR = Path(__file__).parent
|
|
TEST_DATA_DIR = CURRENT_DIR / "data"
|
|
|
|
|
|
class KookEventDataPath:
|
|
GROUP_MESSAGE_WITH_MENTION = (
|
|
TEST_DATA_DIR / "kook_ws_event_group_message_with_mention.json"
|
|
)
|
|
GROUP_MESSAGE = TEST_DATA_DIR / "kook_ws_event_group_message.json"
|
|
HELLO = TEST_DATA_DIR / "kook_ws_event_hello.json"
|
|
MESSAGE_WITH_CARD_1 = TEST_DATA_DIR / "kook_ws_event_message_with_card_1.json"
|
|
MESSAGE_WITH_CARD_2 = TEST_DATA_DIR / "kook_ws_event_message_with_card_2.json"
|
|
PING = TEST_DATA_DIR / "kook_ws_event_ping.json"
|
|
PONG = TEST_DATA_DIR / "kook_ws_event_pong.json"
|
|
PRIVATE_MESSAGE = TEST_DATA_DIR / "kook_ws_event_private_message.json"
|
|
PRIVATE_SYSTEM_MESSAGE = TEST_DATA_DIR / "kook_ws_event_private_system_message.json"
|
|
RECONNECT_ERR = TEST_DATA_DIR / "kook_ws_event_reconnect_err.json"
|
|
RESUME_ACK = TEST_DATA_DIR / "kook_ws_event_resume_ack.json"
|
|
RESUME = TEST_DATA_DIR / "kook_ws_event_resume.json"
|
|
GROUP_SYSTEM_MESSAGE_UPDATE_ROLE = (
|
|
TEST_DATA_DIR / "kook_ws_event_group_system_message_update_role.json"
|
|
)
|
|
|
|
|
|
class KookApiDataPath:
|
|
USER_ME = TEST_DATA_DIR / "kook_api_response_user_me.json"
|
|
USER_VIEW = TEST_DATA_DIR / "kook_api_response_user_view.json"
|
|
|
|
|
|
def mock_kook_client(upload_asset_return: str, send_text_return: str):
|
|
client = MagicMock()
|
|
|
|
client.upload_asset = AsyncMock(return_value=upload_asset_return)
|
|
client.send_text = AsyncMock(return_value=send_text_return)
|
|
return client
|
|
|
|
|
|
def mock_http_client(
|
|
http_method: str = "get",
|
|
return_value: str | dict | list | None = None,
|
|
status: int = 200,
|
|
):
|
|
"""Mock aiohttp ClientSession"""
|
|
|
|
if isinstance(return_value, (dict, list)):
|
|
response_text = json.dumps(return_value)
|
|
else:
|
|
response_text = return_value or "{}"
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.status = status
|
|
mock_response.text = AsyncMock(return_value=response_text)
|
|
mock_response.json = AsyncMock(
|
|
return_value=json.loads(response_text) if response_text else {}
|
|
)
|
|
mock_response.read = AsyncMock(return_value=response_text.encode())
|
|
mock_response.__aenter__ = AsyncMock(return_value=mock_response)
|
|
mock_response.__aexit__ = AsyncMock(return_value=None)
|
|
mock_session = MagicMock()
|
|
|
|
async def mock_method(*args, **kwargs):
|
|
return mock_response
|
|
|
|
setattr(mock_session, http_method.lower(), mock_method)
|
|
mock_session.__aenter__ = AsyncMock(return_value=mock_session)
|
|
mock_session.__aexit__ = AsyncMock(return_value=None)
|
|
|
|
mock_session.close = AsyncMock()
|
|
|
|
return mock_session
|
|
|
|
|
|
def mock_file_message(input: str):
|
|
message = MagicMock(spec=File)
|
|
message.get_file = AsyncMock(return_value=input)
|
|
return message
|
|
|
|
|
|
def mock_record_message(input: str):
|
|
message = MagicMock(spec=Record)
|
|
message.text = input
|
|
message.convert_to_file_path = AsyncMock(return_value=input)
|
|
return message
|
|
|
|
|
|
def mock_astrbot_message():
|
|
message = AstrBotMessage()
|
|
message.type = MessageType.OTHER_MESSAGE
|
|
message.group_id = "test"
|
|
message.session_id = "test"
|
|
message.message_id = "test"
|
|
return message
|
|
|
|
|
|
def mock_kook_roles_record(bot_id: str, http_client: aiohttp.ClientSession):
|
|
instance = AsyncMock()
|
|
instance.has_role_in_channel = AsyncMock(return_value=True)
|
|
return instance
|