From da8e988ee99bf833cae152195e44361b00fd56eb Mon Sep 17 00:00:00 2001
From: felinae98 <731499577@qq.com>
Date: Fri, 24 Mar 2023 21:17:52 +0800
Subject: [PATCH] :recycle: use saa
---
nonebot_bison/config_manager.py | 14 +-
nonebot_bison/post/abstract_post.py | 20 +--
nonebot_bison/post/custom_post.py | 46 +++---
nonebot_bison/post/post.py | 23 +--
nonebot_bison/scheduler/scheduler.py | 3 +-
nonebot_bison/send.py | 87 +++--------
nonebot_bison/utils/__init__.py | 8 +-
poetry.lock | 47 ++++--
pyproject.toml | 3 +-
tests/conftest.py | 7 +
tests/test_config_manager_abort.py | 12 +-
tests/test_config_manager_query_del.py | 28 ++--
tests/test_custom_post.py | 23 ++-
tests/test_render.py | 4 +-
tests/test_send.py | 206 ++++++++-----------------
15 files changed, 223 insertions(+), 308 deletions(-)
diff --git a/nonebot_bison/config_manager.py b/nonebot_bison/config_manager.py
index 87ff843..b80aae3 100644
--- a/nonebot_bison/config_manager.py
+++ b/nonebot_bison/config_manager.py
@@ -15,7 +15,12 @@ from nonebot.params import Depends, EventPlainText, EventToMe
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
from nonebot.typing import T_State
-from nonebot_plugin_saa import PlatformTarget, TargetQQGroup, extract_target
+from nonebot_plugin_saa import (
+ MessageFactory,
+ PlatformTarget,
+ TargetQQGroup,
+ extract_target,
+)
from .apis import check_sub_target
from .config import config
@@ -220,7 +225,7 @@ def do_query_sub(query_sub: Type[Matcher]):
query_sub.handle()(ensure_user_info(query_sub))
@query_sub.handle()
- async def _(state: T_State):
+ async def _(bot: Bot, state: T_State):
user_info = state["target_user_info"]
assert isinstance(user_info, PlatformTarget)
sub_list = await config.list_subscribe(user_info)
@@ -242,7 +247,8 @@ def do_query_sub(query_sub: Type[Matcher]):
if platform.enable_tag:
res += " {}".format(", ".join(sub.tags))
res += "\n"
- await query_sub.finish(Message(await parse_text(res)))
+ await MessageFactory(await parse_text(res)).send()
+ await query_sub.finish()
def do_del_sub(del_sub: Type[Matcher]):
@@ -285,7 +291,7 @@ def do_del_sub(del_sub: Type[Matcher]):
res += " {}".format(", ".join(sub.tags))
res += "\n"
res += "请输入要删除的订阅的序号\n输入'取消'中止"
- await bot.send(event=event, message=Message(await parse_text(res)))
+ await MessageFactory(await parse_text(res)).send()
@del_sub.receive()
async def do_del(event: Event, state: T_State):
diff --git a/nonebot_bison/post/abstract_post.py b/nonebot_bison/post/abstract_post.py
index c0902f3..ee055d5 100644
--- a/nonebot_bison/post/abstract_post.py
+++ b/nonebot_bison/post/abstract_post.py
@@ -3,7 +3,7 @@ from dataclasses import dataclass, field
from functools import reduce
from typing import Optional
-from nonebot.adapters.onebot.v11.message import Message, MessageSegment
+from nonebot_plugin_saa import MessageFactory, MessageSegmentFactory
from ..plugin_config import plugin_config
@@ -11,13 +11,13 @@ from ..plugin_config import plugin_config
@dataclass
class BasePost:
@abstractmethod
- async def generate_text_messages(self) -> list[MessageSegment]:
- "Generate Message list from this instance"
+ async def generate_text_messages(self) -> list[MessageSegmentFactory]:
+ "Generate MessageFactory list from this instance"
...
@abstractmethod
- async def generate_pic_messages(self) -> list[MessageSegment]:
- "Generate Message list from this instance with `use_pic`"
+ async def generate_pic_messages(self) -> list[MessageSegmentFactory]:
+ "Generate MessageFactory list from this instance with `use_pic`"
...
@@ -27,7 +27,7 @@ class OptionalMixin:
override_use_pic: Optional[bool] = None
compress: bool = False
- extra_msg: list[Message] = field(default_factory=list)
+ extra_msg: list[MessageFactory] = field(default_factory=list)
def _use_pic(self):
if not self.override_use_pic is None:
@@ -37,17 +37,19 @@ class OptionalMixin:
@dataclass
class AbstractPost(OptionalMixin, BasePost):
- async def generate_messages(self) -> list[Message]:
+ async def generate_messages(self) -> list[MessageFactory]:
if self._use_pic():
msg_segments = await self.generate_pic_messages()
else:
msg_segments = await self.generate_text_messages()
if msg_segments:
if self.compress:
- msgs = [reduce(lambda x, y: x.append(y), msg_segments, Message())]
+ msgs = [
+ reduce(lambda x, y: x.append(y), msg_segments, MessageFactory([]))
+ ]
else:
msgs = list(
- map(lambda msg_segment: Message([msg_segment]), msg_segments)
+ map(lambda msg_segment: MessageFactory([msg_segment]), msg_segments)
)
else:
msgs = []
diff --git a/nonebot_bison/post/custom_post.py b/nonebot_bison/post/custom_post.py
index 3f343be..951a9c8 100644
--- a/nonebot_bison/post/custom_post.py
+++ b/nonebot_bison/post/custom_post.py
@@ -1,10 +1,10 @@
from dataclasses import dataclass, field
-from pathlib import Path
from typing import Optional
-from nonebot.adapters.onebot.v11.message import Message, MessageSegment
+from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot.log import logger
from nonebot.plugin import require
+from nonebot_plugin_saa import Image, MessageFactory, MessageSegmentFactory, Text
from .abstract_post import AbstractPost, BasePost
@@ -12,37 +12,35 @@ from .abstract_post import AbstractPost, BasePost
@dataclass
class _CustomPost(BasePost):
- message_segments: list[MessageSegment] = field(default_factory=list)
+ ms_factories: list[MessageSegmentFactory] = field(default_factory=list)
css_path: Optional[str] = None # 模板文件所用css路径
- async def generate_text_messages(self) -> list[MessageSegment]:
- return self.message_segments
+ async def generate_text_messages(self) -> list[MessageSegmentFactory]:
+ return self.ms_factories
- async def generate_pic_messages(self) -> list[MessageSegment]:
+ async def generate_pic_messages(self) -> list[MessageSegmentFactory]:
require("nonebot_plugin_htmlrender")
from nonebot_plugin_htmlrender import md_to_pic
pic_bytes = await md_to_pic(md=self._generate_md(), css_path=self.css_path)
- return [MessageSegment.image(pic_bytes)]
+ return [Image(pic_bytes)]
def _generate_md(self) -> str:
md = ""
- for message_segment in self.message_segments:
- if message_segment.type == "text":
- md += "{}
".format(message_segment.data.get("text", ""))
- elif message_segment.type == "image":
- # 先尝试获取file的值,没有再尝试获取url的值,都没有则为空
- pic_res = message_segment.data.get("file") or message_segment.data.get(
- "url", ""
- )
- if not pic_res:
- logger.warning("无法获取到图片资源:MessageSegment.image中file/url字段均为空")
- else:
- md += "\n".format(pic_res)
- else:
- logger.warning("custom_post不支持处理类型:{}".format(message_segment.type))
- continue
+ for message_segment in self.ms_factories:
+ match message_segment:
+ case Text(data={"text": text}):
+ md += "{}
".format(text)
+ case Image(data={"image": image}):
+ # use onebot v11 to convert image into url
+ ob11_image = MessageSegment.image(image)
+ md += "\n".format(ob11_image.data["file"])
+ case _:
+ logger.warning(
+ "custom_post不支持处理类型:{}".format(type(message_segment))
+ )
+ continue
return md
@@ -52,14 +50,14 @@ class CustomPost(_CustomPost, AbstractPost):
"""基于 markdown 语法的,自由度较高的推送内容格式
简介:
- 支持处理text/image两种MessageSegment,
+ 支持处理text/image两种MessageSegmentFactory,
通过将text/image转换成对应的markdown语法以生成markdown文本。
理论上text类型中可以直接使用markdown语法,例如`##第一章`。
但会导致不启用`override_use_pic`时, 发送不会被渲染的纯文本消息。
图片渲染最终由htmlrender执行。
注意:
- 每一个MessageSegment元素都会被解释为单独的一行
+ 每一个MessageSegmentFactory元素都会被解释为单独的一行
可选参数:
`override_use_pic`:是否覆盖`bison_use_pic`全局配置
diff --git a/nonebot_bison/post/post.py b/nonebot_bison/post/post.py
index fe0db9a..afec2ce 100644
--- a/nonebot_bison/post/post.py
+++ b/nonebot_bison/post/post.py
@@ -3,8 +3,9 @@ from functools import reduce
from io import BytesIO
from typing import Optional, Union
-from nonebot.adapters.onebot.v11.message import Message, MessageSegment
+import nonebot_plugin_saa as saa
from nonebot.log import logger
+from nonebot_plugin_saa.utils import MessageFactory, MessageSegmentFactory
from PIL import Image
from ..utils import http_client, parse_text
@@ -20,8 +21,8 @@ class _Post(BasePost):
target_name: Optional[str] = None
pics: list[Union[str, bytes]] = field(default_factory=list)
- _message: Optional[list[MessageSegment]] = None
- _pic_message: Optional[list[MessageSegment]] = None
+ _message: Optional[list[MessageSegmentFactory]] = None
+ _pic_message: Optional[list[MessageSegmentFactory]] = None
async def _pic_url_to_image(self, data: Union[str, bytes]) -> Image.Image:
pic_buffer = BytesIO()
@@ -99,11 +100,11 @@ class _Post(BasePost):
self.pics = self.pics[matrix[0] * matrix[1] :]
self.pics.insert(0, target_io.getvalue())
- async def generate_text_messages(self) -> list[MessageSegment]:
+ async def generate_text_messages(self) -> list[MessageSegmentFactory]:
if self._message is None:
await self._pic_merge()
- msg_segments: list[MessageSegment] = []
+ msg_segments: list[MessageSegmentFactory] = []
text = ""
if self.text:
text += "{}".format(
@@ -116,17 +117,17 @@ class _Post(BasePost):
text += " {}".format(self.target_name)
if self.url:
text += " \n详情: {}".format(self.url)
- msg_segments.append(MessageSegment.text(text))
+ msg_segments.append(saa.Text(text))
for pic in self.pics:
- msg_segments.append(MessageSegment.image(pic))
+ msg_segments.append(saa.Image(pic))
self._message = msg_segments
return self._message
- async def generate_pic_messages(self) -> list[MessageSegment]:
+ async def generate_pic_messages(self) -> list[MessageSegmentFactory]:
if self._pic_message is None:
await self._pic_merge()
- msg_segments: list[MessageSegment] = []
+ msg_segments: list[MessageSegmentFactory] = []
text = ""
if self.text:
text += "{}".format(self.text)
@@ -136,9 +137,9 @@ class _Post(BasePost):
text += " {}".format(self.target_name)
msg_segments.append(await parse_text(text))
if not self.target_type == "rss" and self.url:
- msg_segments.append(MessageSegment.text(self.url))
+ msg_segments.append(saa.Text(self.url))
for pic in self.pics:
- msg_segments.append(MessageSegment.image(pic))
+ msg_segments.append(saa.Image(pic))
self._pic_message = msg_segments
return self._pic_message
diff --git a/nonebot_bison/scheduler/scheduler.py b/nonebot_bison/scheduler/scheduler.py
index e55c608..1a7bae4 100644
--- a/nonebot_bison/scheduler/scheduler.py
+++ b/nonebot_bison/scheduler/scheduler.py
@@ -115,8 +115,7 @@ class Scheduler:
else:
await send_msgs(
bot,
- user.user,
- user.user_type,
+ user,
await send_post.generate_messages(),
)
diff --git a/nonebot_bison/send.py b/nonebot_bison/send.py
index 25479dd..14ba366 100644
--- a/nonebot_bison/send.py
+++ b/nonebot_bison/send.py
@@ -1,45 +1,28 @@
import asyncio
-from asyncio.tasks import sleep
from collections import deque
-from typing import Deque, Literal, Union
+from typing import Deque
-from nonebot.adapters.onebot.v11.bot import Bot
+from nonebot.adapters import Bot
from nonebot.adapters.onebot.v11.exception import ActionFailed
-from nonebot.adapters.onebot.v11.message import Message, MessageSegment
from nonebot.log import logger
+from nonebot_plugin_saa import AggregatedMessageFactory, MessageFactory, PlatformTarget
from .plugin_config import plugin_config
from .utils.get_bot import refresh_bots
-QUEUE: Deque[
- tuple[
- Bot,
- int,
- Literal["private", "group", "group-forward"],
- Union[str, Message],
- int,
- ]
-] = deque()
+Sendable = MessageFactory | AggregatedMessageFactory
+
+QUEUE: Deque[tuple[Bot, PlatformTarget, Sendable, int]] = deque()
MESSGE_SEND_INTERVAL = 1.5
-async def _do_send(
- bot: "Bot",
- user: int,
- user_type: Literal["group", "private", "group-forward"],
- msg: Union[str, Message],
-):
+async def _do_send(bot: "Bot", send_target: PlatformTarget, msg: Sendable):
try:
- if user_type == "group":
- await bot.send_group_msg(group_id=user, message=msg)
- elif user_type == "private":
- await bot.send_private_msg(user_id=user, message=msg)
- elif user_type == "group-forward":
- await bot.send_group_forward_msg(group_id=user, messages=msg)
- except ActionFailed:
+ await msg.send_to(send_target, bot)
+ except ActionFailed: # TODO: catch exception of other adapters
await refresh_bots()
- logger.warning(f"send msg failed, refresh bots")
+ logger.warning("send msg failed, refresh bots")
async def do_send_msgs():
@@ -49,18 +32,18 @@ async def do_send_msgs():
# why read from queue then pop item from queue?
# if there is only 1 item in queue, pop it and await send
# the length of queue will be 0.
- # At that time, adding items to queue will trigger a new execution of this func, which is wrong.
+ # At that time, adding items to queue will trigger a new execution of this func, which is not expected.
# So, read from queue first then pop from it
- bot, user, user_type, msg, retry_time = QUEUE[0]
+ bot, send_target, msg_factory, retry_time = QUEUE[0]
try:
- await _do_send(bot, user, user_type, msg)
+ await _do_send(bot, send_target, msg_factory)
except Exception as e:
await asyncio.sleep(MESSGE_SEND_INTERVAL)
QUEUE.popleft()
if retry_time > 0:
- QUEUE.appendleft((bot, user, user_type, msg, retry_time - 1))
+ QUEUE.appendleft((bot, send_target, msg_factory, retry_time - 1))
else:
- msg_str = str(msg)
+ msg_str = str(msg_factory)
if len(msg_str) > 50:
msg_str = msg_str[:50] + "..."
logger.warning(f"send msg err {e} {msg_str}")
@@ -73,47 +56,27 @@ async def do_send_msgs():
return
-async def _send_msgs_dispatch(
- bot: Bot,
- user,
- user_type: Literal["private", "group", "group-forward"],
- msg: Union[str, Message],
-):
+async def _send_msgs_dispatch(bot: Bot, send_target: PlatformTarget, msg: Sendable):
if plugin_config.bison_use_queue:
- QUEUE.append((bot, user, user_type, msg, plugin_config.bison_resend_times))
+ QUEUE.append((bot, send_target, msg, plugin_config.bison_resend_times))
# len(QUEUE) before append was 0
if len(QUEUE) == 1:
asyncio.create_task(do_send_msgs())
else:
- await _do_send(bot, user, user_type, msg)
+ await _do_send(bot, send_target, msg)
-async def send_msgs(
- bot: Bot, user, user_type: Literal["private", "group"], msgs: list[Message]
-):
- if not plugin_config.bison_use_pic_merge or user_type == "private":
+async def send_msgs(bot: Bot, send_target: PlatformTarget, msgs: list[MessageFactory]):
+ if not plugin_config.bison_use_pic_merge:
for msg in msgs:
- await _send_msgs_dispatch(bot, user, user_type, msg)
+ await _send_msgs_dispatch(bot, send_target, msg)
return
msgs = msgs.copy()
if plugin_config.bison_use_pic_merge == 1:
- await _send_msgs_dispatch(bot, user, "group", msgs.pop(0))
+ await _send_msgs_dispatch(bot, send_target, msgs.pop(0))
if msgs:
if len(msgs) == 1: # 只有一条消息序列就不合并转发
- await _send_msgs_dispatch(bot, user, "group", msgs.pop(0))
+ await _send_msgs_dispatch(bot, send_target, msgs.pop(0))
else:
- group_bot_info = await bot.get_group_member_info(
- group_id=user, user_id=int(bot.self_id), no_cache=True
- ) # 调用api获取群内bot的相关参数
- forward_msg = Message(
- [
- MessageSegment.node_custom(
- group_bot_info["user_id"],
- nickname=group_bot_info["card"] or group_bot_info["nickname"],
- content=msg,
- )
- for msg in msgs
- ]
- )
-
- await _send_msgs_dispatch(bot, user, "group-forward", forward_msg)
+ forward_message = AggregatedMessageFactory(list(msgs))
+ await _send_msgs_dispatch(bot, send_target, forward_message)
diff --git a/nonebot_bison/utils/__init__.py b/nonebot_bison/utils/__init__.py
index c3013fd..007b989 100644
--- a/nonebot_bison/utils/__init__.py
+++ b/nonebot_bison/utils/__init__.py
@@ -4,9 +4,9 @@ from typing import Union
import nonebot
from bs4 import BeautifulSoup as bs
-from nonebot.adapters.onebot.v11.message import MessageSegment
from nonebot.log import default_format, logger
from nonebot.plugin import require
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
from ..plugin_config import plugin_config
from .context import ProcessContext
@@ -33,15 +33,15 @@ class Singleton(type):
return cls._instances[cls]
-async def parse_text(text: str) -> MessageSegment:
+async def parse_text(text: str) -> MessageSegmentFactory:
"return raw text if don't use pic, otherwise return rendered opcode"
if plugin_config.bison_use_pic:
require("nonebot_plugin_htmlrender")
from nonebot_plugin_htmlrender import text_to_pic as _text_to_pic
- return MessageSegment.image(await _text_to_pic(text))
+ return Image(await _text_to_pic(text))
else:
- return MessageSegment.text(text)
+ return Text(text)
if not plugin_config.bison_skip_browser_check:
diff --git a/poetry.lock b/poetry.lock
index c820acd..5eb6176 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -276,13 +276,13 @@ beautifulsoup4 = "*"
[[package]]
name = "cashews"
-version = "6.1.0"
+version = "6.2.0"
description = "cache tools with async power"
optional = false
python-versions = ">=3.7"
files = [
- {file = "cashews-6.1.0-py3-none-any.whl", hash = "sha256:bd620e5fdb947949aca0f107f0275a48d46026c747695186d2507f89a48d1af9"},
- {file = "cashews-6.1.0.tar.gz", hash = "sha256:6ef7822500b8bc5ceadeaa284021ec7843d066e2f208612ec28a93064eef7d4a"},
+ {file = "cashews-6.2.0-py3-none-any.whl", hash = "sha256:8a005fdb429efad8a99e2d8c3024a0a59bed35d49fe67da35a2cd9cb1d56cd89"},
+ {file = "cashews-6.2.0.tar.gz", hash = "sha256:c197202336d1bfde732bf43c30c8fd3fdb5836700e8a81bdd25abcc5ea1df9c8"},
]
[package.extras]
@@ -1467,23 +1467,20 @@ typing-extensions = ">=4.0.0"
[[package]]
name = "nonebot-plugin-send-anything-anywhere"
-version = "0.2.4"
+version = "0.2.5"
description = "An adaptor for nonebot2 adaptors"
optional = false
-python-versions = "^3.8"
-files = []
-develop = false
+python-versions = ">=3.8,<4.0"
+files = [
+ {file = "nonebot_plugin_send_anything_anywhere-0.2.5-py3-none-any.whl", hash = "sha256:58db714745f71693292533433e8881b00954e8ee6438ab3cd173048b5c5ce77f"},
+ {file = "nonebot_plugin_send_anything_anywhere-0.2.5.tar.gz", hash = "sha256:2385e95ee22407faf59703074ad95070bedbdcf492c261ed380f26eccd202039"},
+]
[package.dependencies]
-nonebot2 = "^2.0.0rc1"
-pydantic = "^1.10.5"
-strenum = "^0.4.8"
-
-[package.source]
-type = "git"
-url = "https://github.com/felinae98/nonebot-plugin-send-anything-anywhere.git"
-reference = "main"
-resolved_reference = "7f8a57afc72b5b6a7f909935f1a87411bf597173"
+anyio = ">=3.6.2,<4.0.0"
+nonebot2 = ">=2.0.0,<3.0.0"
+pydantic = ">=1.10.5,<2.0.0"
+strenum = ">=0.4.8,<0.5.0"
[[package]]
name = "nonebot2"
@@ -1537,6 +1534,22 @@ url = "https://github.com/nonebot/nonebug.git"
reference = "master"
resolved_reference = "bc82dbe078a1d42c515a3a783269011fb7e7bc9d"
+[[package]]
+name = "nonebug-saa"
+version = "0.1.0"
+description = "A nonebug helper for nonebot-plugin-send-anything-anything"
+optional = false
+python-versions = ">=3.10,<4.0"
+files = [
+ {file = "nonebug_saa-0.1.0-py3-none-any.whl", hash = "sha256:f2e79867f81d53ca08752382e6800ebc8c6242fbee94fa346ef48e887121b9d6"},
+ {file = "nonebug_saa-0.1.0.tar.gz", hash = "sha256:bfe805d3a9d67e9e2585638b0f37185f69934d2bf433276c007850a9cb9ba52c"},
+]
+
+[package.dependencies]
+nonebot-plugin-send-anything-anywhere = ">=0.2.2,<0.3.0"
+nonebug = ">=0.3.1,<0.4.0"
+pytest-mock = ">=3.10.0,<4.0.0"
+
[[package]]
name = "noneprompt"
version = "0.1.9"
@@ -2873,4 +2886,4 @@ yaml = []
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<4.0.0"
-content-hash = "efba4feca911691e91af2b93cb810268f6e35a6e985811587e6b00999c2bd263"
+content-hash = "109ee12685b1c143006df6969f7b1b3b0d3613a8a47fca3a7a8b005b64605902"
diff --git a/pyproject.toml b/pyproject.toml
index 69661f7..5a68388 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -34,7 +34,7 @@ nonebot-adapter-onebot = "^2.0.0-beta.1"
nonebot-plugin-htmlrender = ">=0.2.0"
nonebot-plugin-datastore = "^0.6.2"
nonebot-plugin-apscheduler = "^0.2.0"
-nonebot-plugin-send-anything-anywhere = {git = "https://github.com/felinae98/nonebot-plugin-send-anything-anywhere.git", rev = "main"}
+nonebot-plugin-send-anything-anywhere = "^0.2.5"
[tool.poetry.group.dev.dependencies]
ipdb = "^0.13.4"
@@ -51,6 +51,7 @@ pytest-mock = "^3.10.0"
nonebug = { git = "https://github.com/nonebot/nonebug.git", rev = "master" }
pytest-xdist = { extras = ["psutil"], version = "^3.1.0" }
nb-cli = "^1.0.5"
+nonebug-saa = "^0.1.0"
[tool.poetry.extras]
cli = ["anyio", "click", "typing-extensions"]
diff --git a/tests/conftest.py b/tests/conftest.py
index 4732b48..86dd982 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -3,6 +3,7 @@ from pathlib import Path
import nonebot
import pytest
+from nonebot.adapters.onebot.v11 import Adapter as OnebotV11Adapter
from nonebug import NONEBOT_INIT_KWARGS, App
from pytest_mock.plugin import MockerFixture
from sqlalchemy import delete
@@ -19,6 +20,12 @@ def pytest_configure(config: pytest.Config) -> None:
}
+@pytest.fixture(scope="session", autouse=True)
+def load_adapters(nonebug_init: None):
+ driver = nonebot.get_driver()
+ driver.register_adapter(OnebotV11Adapter)
+
+
@pytest.fixture
async def app(tmp_path: Path, request: pytest.FixtureRequest, mocker: MockerFixture):
sys.path.append(str(Path(__file__).parent.parent / "src" / "plugins"))
diff --git a/tests/test_config_manager_abort.py b/tests/test_config_manager_abort.py
index da56639..683419a 100644
--- a/tests/test_config_manager_abort.py
+++ b/tests/test_config_manager_abort.py
@@ -1,6 +1,7 @@
import pytest
import respx
from httpx import Response
+from nonebot_plugin_saa.nonebug import should_send_saa
from nonebug.app import App
from .platforms.utils import get_json
@@ -279,7 +280,7 @@ async def test_abort_add_on_tag(app: App, init_scheduler):
async def test_abort_del_sub(app: App, init_scheduler):
from nonebot.adapters.onebot.v11.bot import Bot
from nonebot.adapters.onebot.v11.message import Message
- from nonebot_plugin_saa import TargetQQGroup
+ from nonebot_plugin_saa import MessageFactory, TargetQQGroup
from nonebot_bison.config import config
from nonebot_bison.config_manager import del_sub_matcher
@@ -303,12 +304,13 @@ async def test_abort_del_sub(app: App, init_scheduler):
ctx.receive_event(bot, event)
ctx.should_pass_rule()
ctx.should_pass_permission()
- ctx.should_call_send(
- event,
- Message(
+ should_send_saa(
+ ctx,
+ MessageFactory(
"订阅的帐号为:\n1 weibo 明日方舟Arknights 6279793937\n [图文] 明日方舟\n请输入要删除的订阅的序号\n输入'取消'中止"
),
- True,
+ bot,
+ event=event,
)
event_abort = fake_group_message_event(
message=Message("取消"), sender=fake_admin_user
diff --git a/tests/test_config_manager_query_del.py b/tests/test_config_manager_query_del.py
index 9abb696..ba8018a 100644
--- a/tests/test_config_manager_query_del.py
+++ b/tests/test_config_manager_query_del.py
@@ -1,6 +1,7 @@
import pytest
import respx
from httpx import Response
+from nonebot_plugin_saa.nonebug import should_send_saa
from nonebug.app import App
from .platforms.utils import get_json
@@ -9,8 +10,9 @@ from .utils import fake_admin_user, fake_group_message_event
@pytest.mark.asyncio
async def test_query_sub(app: App, init_scheduler):
- from nonebot.adapters.onebot.v11.message import Message
- from nonebot_plugin_saa import TargetQQGroup
+ from nonebot import get_driver
+ from nonebot.adapters.onebot.v11 import Bot, Message
+ from nonebot_plugin_saa import MessageFactory, SupportedAdapters, TargetQQGroup
from nonebot_bison.config import config
from nonebot_bison.config_manager import query_sub_matcher
@@ -26,13 +28,18 @@ async def test_query_sub(app: App, init_scheduler):
["明日方舟"],
)
async with app.test_matcher(query_sub_matcher) as ctx:
- bot = ctx.create_bot()
+ adapter = get_driver()._adapters[str(SupportedAdapters.onebot_v11)]
+ bot = ctx.create_bot(base=Bot, adapter=adapter)
+
event = fake_group_message_event(message=Message("查询订阅"), to_me=True)
ctx.receive_event(bot, event)
ctx.should_pass_rule()
ctx.should_pass_permission()
- ctx.should_call_send(
- event, Message("订阅的帐号为:\nweibo 明日方舟Arknights 6279793937 [图文] 明日方舟\n"), True
+ should_send_saa(
+ ctx,
+ MessageFactory("订阅的帐号为:\nweibo 明日方舟Arknights 6279793937 [图文] 明日方舟\n"),
+ bot,
+ event=event,
)
@@ -40,7 +47,7 @@ async def test_query_sub(app: App, init_scheduler):
async def test_del_sub(app: App, init_scheduler):
from nonebot.adapters.onebot.v11.bot import Bot
from nonebot.adapters.onebot.v11.message import Message
- from nonebot_plugin_saa import TargetQQGroup
+ from nonebot_plugin_saa import MessageFactory, TargetQQGroup
from nonebot_bison.config import config
from nonebot_bison.config_manager import del_sub_matcher
@@ -64,12 +71,13 @@ async def test_del_sub(app: App, init_scheduler):
ctx.receive_event(bot, event)
ctx.should_pass_rule()
ctx.should_pass_permission()
- ctx.should_call_send(
- event,
- Message(
+ should_send_saa(
+ ctx,
+ MessageFactory(
"订阅的帐号为:\n1 weibo 明日方舟Arknights 6279793937\n [图文] 明日方舟\n请输入要删除的订阅的序号\n输入'取消'中止"
),
- True,
+ bot,
+ event=event,
)
event_1_err = fake_group_message_event(
message=Message("2"), sender=fake_admin_user
diff --git a/tests/test_custom_post.py b/tests/test_custom_post.py
index c13b4f7..74390e9 100644
--- a/tests/test_custom_post.py
+++ b/tests/test_custom_post.py
@@ -1,28 +1,23 @@
-import base64
-import hashlib
-import platform
-from io import UnsupportedOperation
from pathlib import Path
import pytest
import respx
from httpx import Response
-from nonebot.adapters.onebot.v11.message import MessageSegment
+from nonebot_plugin_saa import Image, MessageSegmentFactory, Text
from nonebug.app import App
@pytest.fixture
def ms_list():
- msg_segments: list[MessageSegment] = []
- msg_segments.append(MessageSegment.text("【Zc】每早合约日替攻略!"))
+ msg_segments: list[MessageSegmentFactory] = []
+ msg_segments.append(Text("【Zc】每早合约日替攻略!"))
msg_segments.append(
- MessageSegment.image(
- file="http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg",
- cache=0,
+ Image(
+ image="http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg",
)
)
- msg_segments.append(MessageSegment.text("来源: Bilibili直播 魔法Zc目录"))
- msg_segments.append(MessageSegment.text("详情: https://live.bilibili.com/3044248"))
+ msg_segments.append(Text("来源: Bilibili直播 魔法Zc目录"))
+ msg_segments.append(Text("详情: https://live.bilibili.com/3044248"))
return msg_segments
@@ -35,7 +30,7 @@ def expected_md():
def test_gene_md(app: App, expected_md, ms_list):
from nonebot_bison.post.custom_post import CustomPost
- cp = CustomPost(message_segments=ms_list)
+ cp = CustomPost(ms_factories=ms_list)
cp_md = cp._generate_md()
assert cp_md == expected_md
@@ -55,7 +50,7 @@ async def test_gene_pic(app: App, ms_list, expected_md):
pic_router.mock(return_value=Response(200, stream=mock_pic))
- cp = CustomPost(message_segments=ms_list)
+ cp = CustomPost(ms_factories=ms_list)
cp_pic_msg_md: str = cp._generate_md()
assert cp_pic_msg_md == expected_md
diff --git a/tests/test_render.py b/tests/test_render.py
index 004ea9b..91b5e95 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -8,6 +8,8 @@ from nonebug.app import App
@pytest.mark.asyncio
@pytest.mark.render
async def test_render(app: App):
+ from nonebot_plugin_saa import Image
+
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.utils import parse_text
@@ -23,4 +25,4 @@ VuePress 由两部分组成:第一部分是一个极简静态网站生成器
每一个由 VuePress 生成的页面都带有预渲染好的 HTML,也因此具有非常好的加载性能和搜索引擎优化(SEO)。同时,一旦页面被加载,Vue 将接管这些静态内容,并将其转换成一个完整的单页应用(SPA),其他的页面则会只在用户浏览到的时候才按需加载。
"""
)
- assert res.type == "image"
+ assert isinstance(res, Image)
diff --git a/tests/test_send.py b/tests/test_send.py
index c45fb9e..3e9d422 100644
--- a/tests/test_send.py
+++ b/tests/test_send.py
@@ -3,36 +3,34 @@ import typing
import pytest
from flaky import flaky
+from nonebot_plugin_saa.nonebug import should_send_saa
from nonebug import App
from pytest_mock.plugin import MockerFixture
-if typing.TYPE_CHECKING:
- from nonebot.adapters.onebot.v11.message import Message, MessageSegment
-
@pytest.mark.asyncio
async def test_send_no_queue(app: App, mocker: MockerFixture):
from nonebot.adapters.onebot.v11.bot import Bot
- from nonebot.adapters.onebot.v11.message import Message
+ from nonebot_plugin_saa import MessageFactory, TargetQQGroup, TargetQQPrivate
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.send import send_msgs
mocker.patch.object(plugin_config, "bison_use_queue", False)
+
+ group_target = TargetQQGroup(group_id=1233)
+ private_target = TargetQQPrivate(user_id=666)
+
async with app.test_api() as ctx:
bot = ctx.create_bot(base=Bot)
assert isinstance(bot, Bot)
- ctx.should_call_api(
- "send_group_msg", {"group_id": "1233", "message": Message("msg1")}, True
+ should_send_saa(ctx, MessageFactory("msg1"), bot, target=group_target)
+ should_send_saa(ctx, MessageFactory("msg2"), bot, target=group_target)
+ should_send_saa(ctx, MessageFactory("priv"), bot, target=private_target)
+ await send_msgs(
+ bot, group_target, [MessageFactory("msg1"), MessageFactory("msg2")]
)
- ctx.should_call_api(
- "send_group_msg", {"group_id": "1233", "message": Message("msg2")}, True
- )
- ctx.should_call_api(
- "send_private_msg", {"user_id": "666", "message": Message("priv")}, True
- )
- await send_msgs(bot, "1233", "group", [Message("msg1"), Message("msg2")])
- await send_msgs(bot, "666", "private", [Message("priv")])
+ await send_msgs(bot, private_target, [MessageFactory("priv")])
assert ctx.wait_list.empty()
@@ -40,11 +38,10 @@ async def test_send_no_queue(app: App, mocker: MockerFixture):
async def test_send_queue(app: App, mocker: MockerFixture):
import nonebot
from nonebot.adapters.onebot.v11.bot import Bot
- from nonebot.adapters.onebot.v11.message import Message, MessageSegment
+ from nonebot_plugin_saa import MessageFactory, TargetQQGroup
- from nonebot_bison import send
from nonebot_bison.plugin_config import plugin_config
- from nonebot_bison.send import MESSGE_SEND_INTERVAL, do_send_msgs, send_msgs
+ from nonebot_bison.send import MESSGE_SEND_INTERVAL, send_msgs
mocker.patch.object(plugin_config, "bison_use_queue", True)
async with app.test_api() as ctx:
@@ -53,39 +50,28 @@ async def test_send_queue(app: App, mocker: MockerFixture):
bot = nonebot.get_bot()
assert isinstance(bot, Bot)
assert bot == new_bot
- ctx.should_call_api(
- "send_group_msg",
- {"group_id": "1233", "message": [MessageSegment.text("msg")]},
- True,
- )
- ctx.should_call_api(
- "send_group_msg",
- {"group_id": "1233", "message": [MessageSegment.text("msg2")]},
- True,
- )
- await send_msgs(bot, "1233", "group", [Message("msg")])
- await send_msgs(bot, "1233", "group", [Message("msg2")])
+
+ target = TargetQQGroup(group_id=1233)
+ should_send_saa(ctx, MessageFactory("msg"), bot, target=target)
+ should_send_saa(ctx, MessageFactory("msg2"), bot, target=target)
+
+ await send_msgs(bot, target, [MessageFactory("msg")])
+ await send_msgs(bot, target, [MessageFactory("msg2")])
assert not ctx.wait_list.empty()
await asyncio.sleep(2 * MESSGE_SEND_INTERVAL)
assert ctx.wait_list.empty()
-def gen_node(id, name, content: "Message"):
- from nonebot.adapters.onebot.v11.message import MessageSegment
-
- return MessageSegment.node_custom(id, name, content)
-
-
-def _merge_messge(nodes):
- from nonebot.adapters.onebot.v11.message import Message
-
- return Message(nodes)
-
-
@pytest.mark.asyncio
async def test_send_merge_no_queue(app: App):
from nonebot.adapters.onebot.v11.bot import Bot
- from nonebot.adapters.onebot.v11.message import Message, MessageSegment
+ from nonebot_plugin_saa import (
+ AggregatedMessageFactory,
+ Image,
+ MessageFactory,
+ TargetQQGroup,
+ Text,
+ )
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.send import send_msgs
@@ -96,100 +82,46 @@ async def test_send_merge_no_queue(app: App):
async with app.test_api() as ctx:
bot = ctx.create_bot(base=Bot, self_id="8888")
assert isinstance(bot, Bot)
- message = [
- Message(MessageSegment.text("test msg")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
- ]
- ctx.should_call_api(
- "send_group_msg",
- {"group_id": 633, "message": Message(MessageSegment.text("test msg"))},
- None,
- )
- ctx.should_call_api(
- "send_group_msg",
- {"group_id": 633, "message": message[1]},
- None,
- )
- await send_msgs(bot, 633, "group", message)
+ target = TargetQQGroup(group_id=633)
message = [
- Message(MessageSegment.text("test msg")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
+ MessageFactory(Text("test msg")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
]
- ctx.should_call_api(
- "send_group_msg",
- {"group_id": 633, "message": Message(MessageSegment.text("test msg"))},
- None,
- )
- ctx.should_call_api(
- "get_group_member_info",
- {"group_id": 633, "user_id": 8888, "no_cache": True},
- {"user_id": 8888, "card": "admin", "nickname": "adminuser"},
- )
- merged_message = _merge_messge(
- [gen_node(8888, "admin", message[1]), gen_node(8888, "admin", message[2])]
- )
- ctx.should_call_api(
- "send_group_forward_msg",
- {"group_id": 633, "messages": merged_message},
- None,
- )
- await send_msgs(bot, 633, "group", message)
+ should_send_saa(ctx, message[0], bot, target=target)
+ should_send_saa(ctx, message[1], bot, target=target)
+ await send_msgs(bot, target, message)
message = [
- Message(MessageSegment.text("test msg")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
+ MessageFactory(Text("test msg")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
]
- ctx.should_call_api(
- "send_group_msg",
- {"group_id": 633, "message": Message(MessageSegment.text("test msg"))},
- None,
- )
- ctx.should_call_api(
- "get_group_member_info",
- {"group_id": 633, "user_id": 8888, "no_cache": True},
- {"user_id": 8888, "card": None, "nickname": "adminuser"},
- )
- merged_message = _merge_messge(
- [
- gen_node(8888, "adminuser", message[1]),
- gen_node(8888, "adminuser", message[2]),
- gen_node(8888, "adminuser", message[3]),
- ]
- )
- ctx.should_call_api(
- "send_group_forward_msg",
- {"group_id": 633, "messages": merged_message},
- None,
- )
- await send_msgs(bot, 633, "group", message)
+ should_send_saa(ctx, message[0], bot, target=target)
+ should_send_saa(ctx, AggregatedMessageFactory(message[1:]), bot, target=target)
+ # import ipdb; ipdb.set_trace()
+ await send_msgs(bot, target, message)
- # private user should not send in forward
message = [
- Message(MessageSegment.text("test msg")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
+ MessageFactory(Text("test msg")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
]
- ctx.should_call_api(
- "send_private_msg",
- {"user_id": 633, "message": Message(MessageSegment.text("test msg"))},
- None,
- )
- ctx.should_call_api(
- "send_private_msg", {"user_id": 633, "message": message[1]}, None
- )
- ctx.should_call_api(
- "send_private_msg", {"user_id": 633, "message": message[2]}, None
- )
- await send_msgs(bot, 633, "private", message)
+ should_send_saa(ctx, message[0], bot, target=target)
+ should_send_saa(ctx, AggregatedMessageFactory(message[1:]), bot, target=target)
+ await send_msgs(bot, target, message)
async def test_send_merge2_no_queue(app: App):
from nonebot.adapters.onebot.v11.bot import Bot
- from nonebot.adapters.onebot.v11.message import Message, MessageSegment
+ from nonebot_plugin_saa import (
+ AggregatedMessageFactory,
+ Image,
+ MessageFactory,
+ TargetQQGroup,
+ Text,
+ )
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.send import send_msgs
@@ -200,26 +132,12 @@ async def test_send_merge2_no_queue(app: App):
async with app.test_api() as ctx:
bot = ctx.create_bot(base=Bot, self_id="8888")
assert isinstance(bot, Bot)
+ target = TargetQQGroup(group_id=633)
+
message = [
- Message(MessageSegment.text("test msg")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
- Message(MessageSegment.image("https://picsum.photos/200/300")),
+ MessageFactory(Text("test msg")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
+ MessageFactory(Image("https://picsum.photos/200/300")),
]
- ctx.should_call_api(
- "get_group_member_info",
- {"group_id": 633, "user_id": 8888, "no_cache": True},
- {"user_id": 8888, "card": "admin", "nickname": "adminuser"},
- )
- merged_message = _merge_messge(
- [
- gen_node(8888, "admin", message[0]),
- gen_node(8888, "admin", message[1]),
- gen_node(8888, "admin", message[2]),
- ]
- )
- ctx.should_call_api(
- "send_group_forward_msg",
- {"group_id": 633, "messages": merged_message},
- None,
- )
- await send_msgs(bot, 633, "group", message)
+ should_send_saa(ctx, AggregatedMessageFactory(message), bot, target=target)
+ await send_msgs(bot, target, message)