Repository: MountainDash/nonebot-plugin-send-anything-anywhere (language: python)

Issue:
飞书适配器报错
https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere/blob/e6b81f1ee381193f206a72273748ee8f1c4f7b4d/nonebot_plugin_saa/adapters/feishu.py#L71

https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere/blob/e6b81f1ee381193f206a72273748ee8f1c4f7b4d/nonebot_plugin_saa/adapters/feishu.py#L182

![图片](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere/assets/34291620/d5ef51d7-d18a-4fbd-9a9f-25d97a46c7f5)
![图片](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere/assets/34291620/3cbb7354-3e50-423a-ad83-a57806b52c16)

这两处似乎少解析了一层`data`,又或者因为选择的事件是接受消息v2的原因?
![图片](https://github.com/MountainDash/nonebot-plugin-send-anything-anywhere/assets/34291620/aaf819e0-3241-4bee-9130-5c34a732ca2c)




Discussion / hints:
飞书那边的版本更新了吗？
飞书适配器版本和saa这边限制的匹配吗
@MeetWq 看看？
飞书适配器 `v2.3.0` 修改了 api 调用方式 https://github.com/nonebot/adapter-feishu/commit/fe1a6ad7ff504162d985d07693b1e0b9e7db833b
我这边改一下

Fix patch:
diff --git a/nonebot_plugin_saa/adapters/feishu.py b/nonebot_plugin_saa/adapters/feishu.py
index 525bfd4..904d813 100644
--- a/nonebot_plugin_saa/adapters/feishu.py
+++ b/nonebot_plugin_saa/adapters/feishu.py
@@ -4,6 +4,7 @@
 from typing import Any, Dict, Literal, cast
 
 from nonebot.adapters import Event
+from nonebot.drivers import Request
 from nonebot.adapters import Bot as BaseBot
 
 from ..utils import SupportedAdapters
@@ -24,7 +25,6 @@
 )
 
 try:
-    import httpx
     from nonebot.adapters.feishu.message import At
     from nonebot.adapters.feishu import (
         Bot,
@@ -55,10 +55,14 @@ async def _image(i: Image, bot: BaseBot) -> MessageSegment:
 
         image = i.data["image"]
         if isinstance(image, str):
-            async with httpx.AsyncClient() as client:
-                resp = await client.get(image, timeout=10, follow_redirects=True)
-                resp.raise_for_status()
-                image = resp.content
+            resp = await bot.adapter.request(Request("GET", image, timeout=10))
+            if resp.status_code != 200:
+                raise RuntimeError(
+                    f"Failed to download image: {resp.status_code}, url: {image}"
+                )
+            image = resp.content
+            if not isinstance(image, bytes):
+                raise TypeError(f"Unsupported type of file: {type(image)}, need bytes")
         elif isinstance(image, Path):
             image = image.read_bytes()
         elif isinstance(image, BytesIO):
@@ -68,7 +72,7 @@ async def _image(i: Image, bot: BaseBot) -> MessageSegment:
         files = {"image": ("file", image)}
         params = {"method": "POST", "data": data, "files": files}
         result = await bot.call_api("im/v1/images", **params)
-        file_key = result["image_key"]
+        file_key = result["data"]["image_key"]
         return MessageSegment.image(file_key)
 
     @register_feishu(Mention)
@@ -179,7 +183,7 @@ async def send(
             resp = await bot.call_api(
                 f"im/v1/messages/{reply_to_message_id}/reply", **params
             )
-        message_id = resp["message_id"]
+        message_id = resp["data"]["message_id"]
         return FeishuReceipt(bot_id=bot.self_id, message_id=message_id, data=resp)
 
 except ImportError:
diff --git a/poetry.lock b/poetry.lock
index faabbb0..040bf5f 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -824,18 +824,18 @@ nonebot2 = ">=2.0.0,<3.0.0"
 
 [[package]]
 name = "nonebot-adapter-feishu"
-version = "2.3.2"
+version = "2.4.0"
 description = "feishu(larksuite) adapter for nonebot2"
 optional = false
 python-versions = ">=3.8,<4.0"
 files = [
-    {file = "nonebot_adapter_feishu-2.3.2-py3-none-any.whl", hash = "sha256:7f19b9067bb456ee7e815ea8c2e7daf2fb9bd4bffc87921bae1013839285ec5a"},
-    {file = "nonebot_adapter_feishu-2.3.2.tar.gz", hash = "sha256:d963b27f288db1f14c62020023626245ab50c514952d5f3c7693ff2a82fa10d8"},
+    {file = "nonebot_adapter_feishu-2.4.0-py3-none-any.whl", hash = "sha256:b7fdbecbf545231d106299df38617568f8ebf1094f545e4cce22ceaef71af89c"},
+    {file = "nonebot_adapter_feishu-2.4.0.tar.gz", hash = "sha256:ebfdd23257282f5717f6d42df28f4c44a2bb139ea1fefd61d49ea9c0975b0e9b"},
 ]
 
 [package.dependencies]
 cashews = ">=6.0.0,<7.0.0"
-nonebot2 = ">=2.1.0,<3.0.0"
+nonebot2 = ">=2.2.0,<3.0.0"
 pycryptodome = ">=3.18.0,<4.0.0"
 
 [[package]]
@@ -854,18 +854,19 @@ nonebot2 = ">=2.0.0,<3.0.0"
 
 [[package]]
 name = "nonebot-adapter-onebot"
-version = "2.3.1"
+version = "2.4.0"
 description = "OneBot(CQHTTP) adapter for nonebot2"
 optional = false
 python-versions = ">=3.8,<4.0"
 files = [
-    {file = "nonebot_adapter_onebot-2.3.1-py3-none-any.whl", hash = "sha256:c4085f1fc1a62e46c737452b9ce3d6eb374812c78a419bb4fa378f48bd8e4088"},
-    {file = "nonebot_adapter_onebot-2.3.1.tar.gz", hash = "sha256:10cec3aee454700e6d2144748bd898772db7bd95247d51d3ccd3b31919e24689"},
+    {file = "nonebot_adapter_onebot-2.4.0-py3-none-any.whl", hash = "sha256:4a51da1913c8ab6008e8ef8a2877af7acc32eac82d6773ff443f743dda380e14"},
+    {file = "nonebot_adapter_onebot-2.4.0.tar.gz", hash = "sha256:27a29de8137ce60f0ea328c6fac63571ba7efef7619d0cc74c0dff42c3034b12"},
 ]
 
 [package.dependencies]
 msgpack = ">=1.0.3,<2.0.0"
-nonebot2 = ">=2.1.0,<3.0.0"
+nonebot2 = ">=2.2.0,<3.0.0"
+pydantic = ">=1.10.0,<2.5.0 || >2.5.0,<2.5.1 || >2.5.1,<3.0.0"
 typing-extensions = ">=4.0.0,<5.0.0"
 
 [[package]]
@@ -1927,4 +1928,4 @@ multidict = ">=4.0"
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.8"
-content-hash = "90621be3be9b01a72ef0517e4b3597901cd6df54b87de37a1e06a550c5a1dbe0"
+content-hash = "1f7cf88cf5a004bb53331e0c1cf0023db0cd837f3f994edf14474e1cb105ce35"
diff --git a/pyproject.toml b/pyproject.toml
index 98ca12f..5b46311 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -48,7 +48,7 @@ nonebot-adapter-onebot = "^2.2.2"
 nonebot-adapter-qqguild = ">=0.2.1"
 nonebot-adapter-kaiheila = "^0.2.12"
 nonebot-adapter-telegram = ">=0.1.0b16"
-nonebot-adapter-feishu = "^2.1.1"
+nonebot-adapter-feishu = "^2.4.0"
 nonebot-adapter-red = ">=0.4.1"
 nonebot-adapter-dodo = "^0.1.2"
 nonebot-adapter-qq = "^1.3.0"


Test patch:
diff --git a/tests/test_feishu.py b/tests/test_feishu.py
index af15b26..c930104 100644
--- a/tests/test_feishu.py
+++ b/tests/test_feishu.py
@@ -2,9 +2,10 @@
 from pathlib import Path
 from functools import partial
 
-import httpx
+import respx
 import pytest
 from nonebug import App
+from httpx import Response
 from nonebot import get_driver
 from nonebot.adapters.feishu import Bot, Message
 from nonebot.adapters.feishu.models import BotInfo
@@ -116,56 +117,55 @@ async def test_text(app: App, assert_feishu):
     await assert_feishu(app, Text("114514"), MessageSegment.text("114514"))
 
 
+@respx.mock
 async def test_image(app: App, tmp_path: Path):
     from nonebot.adapters.feishu import MessageSegment
 
     from nonebot_plugin_saa import Image, SupportedAdapters
 
+    url = "https://nonebot.dev/logo.png"
+    content = b"\x89PNG\r"
+    image_route = respx.get(url)
+    image_route.mock(return_value=Response(200, content=content))
     async with app.test_api() as ctx:
         adapter = get_driver()._adapters[str(SupportedAdapters.feishu)]
         bot = ctx.create_bot(base=Bot, adapter=adapter, **feishu_kwargs)
 
-        url = "https://nonebot.dev/logo.png"
-        async with httpx.AsyncClient() as client:
-            resp = await client.get(url)
-            resp.raise_for_status()
-            data = resp.content
         ctx.should_call_api(
             "im/v1/images",
             {
                 "method": "POST",
                 "data": {"image_type": "message"},
-                "files": {"image": ("file", data)},
+                "files": {"image": ("file", content)},
             },
-            {"image_key": "114514"},
+            {"code": 0, "msg": "success", "data": {"image_key": "114514"}},
         )
         generated_ms = await Image(url).build(bot)
         assert generated_ms == MessageSegment.image("114514")
 
-        data = b"\x89PNG\r"
         ctx.should_call_api(
             "im/v1/images",
             {
                 "method": "POST",
                 "data": {"image_type": "message"},
-                "files": {"image": ("file", data)},
+                "files": {"image": ("file", content)},
             },
-            {"image_key": "114514"},
+            {"code": 0, "msg": "success", "data": {"image_key": "114514"}},
         )
-        generated_ms = await Image(data).build(bot)
+        generated_ms = await Image(content).build(bot)
         assert generated_ms == MessageSegment.image("114514")
 
         image_path = tmp_path / "test.png"
         with image_path.open("wb") as f:
-            f.write(data)
+            f.write(content)
         ctx.should_call_api(
             "im/v1/images",
             {
                 "method": "POST",
                 "data": {"image_type": "message"},
-                "files": {"image": ("file", data)},
+                "files": {"image": ("file", content)},
             },
-            {"image_key": "114514"},
+            {"code": 0, "msg": "success", "data": {"image_key": "114514"}},
         )
         generated_ms = await Image(image_path).build(bot)
         assert generated_ms == MessageSegment.image("114514")
@@ -175,11 +175,11 @@ async def test_image(app: App, tmp_path: Path):
             {
                 "method": "POST",
                 "data": {"image_type": "message"},
-                "files": {"image": ("file", data)},
+                "files": {"image": ("file", content)},
             },
-            {"image_key": "114514"},
+            {"code": 0, "msg": "success", "data": {"image_key": "114514"}},
         )
-        generated_ms = await Image(BytesIO(data)).build(bot)
+        generated_ms = await Image(BytesIO(content)).build(bot)
         assert generated_ms == MessageSegment.image("114514")
 
 
@@ -234,7 +234,7 @@ async def _(event: MessageEvent):
                     "msg_type": msg_type,
                 },
             },
-            {"message_id": "114514"},
+            {"code": 0, "msg": "success", "data": {"message_id": "114514"}},
         )
 
 
@@ -271,7 +271,7 @@ async def _(event: MessageEvent):
                     "msg_type": msg_type,
                 },
             },
-            {"message_id": "114514"},
+            {"code": 0, "msg": "success", "data": {"message_id": "114514"}},
         )
 
 
@@ -306,7 +306,7 @@ async def _(event: MessageEvent):
                     "msg_type": msg_type,
                 },
             },
-            {"message_id": "114514"},
+            {"code": 0, "msg": "success", "data": {"message_id": "114514"}},
         )
         ctx.should_call_api("im/v1/messages/114514", {"method": "DELETE"}, {})
 
@@ -339,7 +339,7 @@ async def _(event: MessageEvent):
         ctx.should_call_api(
             "im/v1/messages/message_id/reply",
             {"method": "POST", "body": {"content": content, "msg_type": msg_type}},
-            {"message_id": "114514"},
+            {"code": 0, "msg": "success", "data": {"message_id": "114514"}},
         )
         ctx.should_call_api("im/v1/messages/114514", {"method": "DELETE"}, {})
 
@@ -373,7 +373,7 @@ async def test_send_active(app: App):
                     "msg_type": msg_type,
                 },
             },
-            {"message_id": "114514"},
+            {"code": 0, "msg": "success", "data": {"message_id": "114514"}},
         )
         await MessageFactory("114514").send_to(target_private, bot)
 
@@ -389,6 +389,6 @@ async def test_send_active(app: App):
                     "msg_type": msg_type,
                 },
             },
-            {"message_id": "114514"},
+            {"code": 0, "msg": "success", "data": {"message_id": "114514"}},
         )
         await MessageFactory("114514").send_to(target_group, bot)