Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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