Skip to content

Commit 154c7bc

Browse files
committed
fix: Migrate Wecom adapter from Quart to FastAPI
- Replace Quart with FastAPI for webhook handling - Update request and response handling to match FastAPI conventions - Modify signature and message decryption methods - Fix minor configuration parameter references - Improve error handling with FastAPI HTTPException
1 parent cbd6f00 commit 154c7bc

File tree

1 file changed

+23
-22
lines changed

1 file changed

+23
-22
lines changed

kirara_ai/plugins/im_wecom_adapter/adapter.py

+23-22
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
from io import BytesIO
2424

2525
import aiohttp
26+
from fastapi import FastAPI, HTTPException, Request, Response
2627
from pydantic import BaseModel, ConfigDict, Field
27-
from quart import Quart, abort, request
2828
from wechatpy.exceptions import InvalidSignatureException
2929

3030
from kirara_ai.im.adapter import IMAdapter
@@ -123,13 +123,13 @@ class WecomAdapter(IMAdapter):
123123

124124
def __init__(self, config: WecomConfig):
125125
self.config = config
126-
if "host" in config.__pydantic_extra__ and config.__pydantic_extra__["host"] is not None:
127-
self.app = Quart(__name__)
126+
if self.config.host:
127+
self.app = FastAPI()
128128
else:
129129
self.app = self.web_server.app
130130

131131
self.crypto = WeChatCrypto(
132-
config.token, config.encoding_aes_key, config.corp_id or config.agent_id
132+
config.token, config.encoding_aes_key, config.corp_id or config.app_id
133133
)
134134
self.client = WeChatClient(config.corp_id, config.secret)
135135
self.logger = get_logger("Wecom-Adapter")
@@ -149,36 +149,37 @@ def setup_routes(self):
149149
webhook_url = self.config.webhook_url
150150

151151
@self.app.get(webhook_url)
152-
async def handle_check_request():
152+
async def handle_check_request(request: Request):
153153
"""处理 GET 请求"""
154154
if not self.is_running:
155-
return abort(404)
156-
signature = request.args.get("msg_signature", "")
157-
timestamp = request.args.get("timestamp", "")
158-
nonce = request.args.get("nonce", "")
159-
echo_str = request.args.get("echostr", "")
155+
raise HTTPException(status_code=404)
156+
157+
signature = request.query_params.get("msg_signature", "")
158+
timestamp = request.query_params.get("timestamp", "")
159+
nonce = request.query_params.get("nonce", "")
160+
echo_str = request.query_params.get("echostr", "")
160161
try:
161162
echo_str = self.crypto.check_signature(
162163
signature, timestamp, nonce, echo_str
163164
)
164-
return echo_str
165+
return Response(content=echo_str, media_type="text/plain")
165166
except InvalidSignatureException:
166-
return abort(403)
167+
raise HTTPException(status_code=403)
167168

168169
@self.app.post(webhook_url)
169-
async def handle_message():
170+
async def handle_message(request: Request):
170171
"""处理 POST 请求"""
171172
if not self.is_running:
172-
return abort(404)
173-
signature = request.args.get("msg_signature", "")
174-
timestamp = request.args.get("timestamp", "")
175-
nonce = request.args.get("nonce", "")
173+
raise HTTPException(status_code=404)
174+
signature = request.query_params.get("msg_signature", "")
175+
timestamp = request.query_params.get("timestamp", "")
176+
nonce = request.query_params.get("nonce", "")
176177
try:
177178
msg = self.crypto.decrypt_message(
178-
await request.data, signature, timestamp, nonce
179+
await request.body(), signature, timestamp, nonce
179180
)
180181
except (InvalidSignatureException, InvalidCorpIdException):
181-
return abort(403)
182+
raise HTTPException(status_code=403)
182183
msg = parse_message(msg)
183184

184185
# 预处理媒体消息
@@ -192,7 +193,7 @@ async def handle_message():
192193
message = self.convert_to_message(msg, media_path)
193194
# 分发消息
194195
await self.dispatcher.dispatch(self, message)
195-
return "ok"
196+
return Response(content="ok", media_type="text/plain")
196197

197198
def convert_to_message(self, raw_message: Any, media_path: Optional[str] = None) -> IMMessage:
198199
"""将企业微信消息转换为统一消息格式"""
@@ -232,7 +233,7 @@ def convert_to_message(self, raw_message: Any, media_path: Optional[str] = None)
232233
async def _send_text(self, user_id: str, text: str):
233234
"""发送文本消息"""
234235
try:
235-
return self.client.message.send_text(self.config.agent_id, user_id, text)
236+
return self.client.message.send_text(self.config.app_id, user_id, text)
236237
except Exception as e:
237238
self.logger.error(f"Failed to send text message: {e}")
238239

@@ -243,7 +244,7 @@ async def _send_media(self, user_id: str, media_data: str, media_type: str):
243244
media_id = self.client.media.upload(
244245
media_type, media_bytes)["media_id"]
245246
send_method = getattr(self.client.message, f"send_{media_type}")
246-
return send_method(self.config.agent_id, user_id, media_id)
247+
return send_method(self.config.app, user_id, media_id)
247248
except Exception as e:
248249
self.logger.error(f"Failed to send {media_type} message: {e}")
249250

0 commit comments

Comments
 (0)