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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
![Python Version](https://img.shields.io/badge/python-3.7+-blue.svg)
![OneBot Version](https://img.shields.io/badge/OneBot-v10,v11-black.svg)

**aiocqhttp** 是 [OneBot](https://github.com/howmanybots/onebot) (原 [酷Q](https://cqp.cc) 的 [CQHTTP 插件](https://cqhttp.cc)) 的 Python SDK,采用异步 I/O,封装了 web 服务器相关的代码,支持 OneBot 的 HTTP 和反向 WebSocket 两种通信方式,让使用 Python 的开发者能方便地开发插件。
**aiocqhttp** 是 [OneBot](https://github.com/howmanybots/onebot) (原 [酷Q](https://cqp.cc) 的 [CQHTTP 插件](https://cqhttp.cc)) 的 Python SDK,采用异步 I/O,封装了 web 服务器相关的代码,支持 OneBot 的 HTTP、正向 WebSocket 和反向 WebSocket 三种通信方式,让使用 Python 的开发者能方便地开发插件。

本 SDK 要求使用 Python 3.7 或更高版本,以及建议搭配支持 OneBot v11 的 OneBot 实现。

Expand Down
41 changes: 33 additions & 8 deletions aiocqhttp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
from quart import Quart, request, abort, jsonify, websocket, Response

from .api import AsyncApi, SyncApi
from .api_impl import (SyncWrapperApi, HttpApi, WebSocketReverseApi,
UnifiedApi, ResultStore)
from .api_impl import (SyncWrapperApi, HttpApi, WebSocketReverseApi, UnifiedApi,
ResultStore, WebSocketForwardApi, _is_websocket_url)
from .bus import EventBus
from .exceptions import Error, TimingError
from .event import Event
Expand Down Expand Up @@ -105,8 +105,10 @@ def __init__(self,
``import_name`` 参数为当前模块(使用 `CQHttp` 的模块)的导入名,通常传入
``__name__`` 或不传入。

``api_root`` 参数为 OneBot API 的 URL,``access_token`` 和
``secret`` 参数为 OneBot 配置中填写的对应项。
``api_root`` 参数为 OneBot API 的地址,支持 HTTP URL(如
``http://127.0.0.1:5700``)或正向 WebSocket URL(如
``ws://127.0.0.1:6700/``)。``access_token`` 和 ``secret`` 参数为 OneBot
配置中填写的对应项。

``message_class`` 参数为要用来对 `Event.message` 进行转换的消息类,可使用
`Message`,例如:
Expand Down Expand Up @@ -155,12 +157,35 @@ def _configure(self,
api_timeout_sec = api_timeout_sec or 60 # wait for 60 secs by default
self._access_token = access_token
self._secret = secret
self._api._http_api = HttpApi(api_root, access_token, api_timeout_sec)

# Configure API implementations based on api_root type
http_api = None
wsf_api = None

if _is_websocket_url(api_root):
# Forward WebSocket mode
try:
wsf_api = WebSocketForwardApi(ws_url=api_root,
access_token=access_token,
timeout_sec=api_timeout_sec,
event_handler=self._handle_event)
except ImportError as e:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里建议 catch 所有 Exception 然后日志里会显示具体原因

self.logger.error(f"Failed to create WebSocketForwardApi: {e}")
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the ImportError is raised and re-raised here, the WebSocketForwardApi initialization fails but leaves the bot in an inconsistent state. The _api instance already exists but won't have a properly configured _wsf_api. Consider whether the error should be caught and the bot should fall back to HTTP mode instead, or document that forward WebSocket is a hard requirement when a ws:// URL is provided.

Suggested change
self.logger.error(f"Failed to create WebSocketForwardApi: {e}")
self.logger.error(f"Failed to create WebSocketForwardApi: {e}")
# Avoid leaving the unified API in a potentially inconsistent state
# if forward WebSocket support cannot be initialized.
self._api = None

Copilot uses AI. Check for mistakes.
raise
else:
# HTTP mode
http_api = HttpApi(api_root, access_token, api_timeout_sec)

# Always configure reverse WebSocket (independent)
self._wsr_api_clients = {} # connected wsr api clients
self._wsr_event_clients = set()
self._api._wsr_api = WebSocketReverseApi(self._wsr_api_clients,
self._wsr_event_clients,
api_timeout_sec)
wsr_api = WebSocketReverseApi(self._wsr_api_clients,
self._wsr_event_clients, api_timeout_sec)

# Update the existing UnifiedApi instance instead of creating a new one
self._api._http_api = http_api
self._api._wsr_api = wsr_api
self._api._wsf_api = wsf_api

async def _before_serving(self):
self._loop = asyncio.get_running_loop()
Expand Down
Loading