diff --git a/nonebot/matcher.py b/nonebot/matcher.py index f9d7f8c5..c00548f5 100644 --- a/nonebot/matcher.py +++ b/nonebot/matcher.py @@ -529,7 +529,7 @@ class Matcher(metaclass=MatcherMeta): :参数: - * ``message: Union[str, Message, MessageSegment]``: 消息内容 + * ``message: Union[str, Message, MessageSegment, MessageTemplate]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ if message is not None: @@ -549,7 +549,7 @@ class Matcher(metaclass=MatcherMeta): :参数: - * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 + * ``prompt: Union[str, Message, MessageSegment, MessageTemplate]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ if prompt is not None: @@ -570,7 +570,7 @@ class Matcher(metaclass=MatcherMeta): :参数: - * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 + * ``prompt: Union[str, Message, MessageSegment, MessageTemplate]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ if prompt is not None: @@ -593,7 +593,7 @@ class Matcher(metaclass=MatcherMeta): :参数: * ``key: str``: 参数名 - * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 + * ``prompt: Union[str, Message, MessageSegment, MessageTemplate]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ matcher = current_matcher.get() @@ -618,7 +618,7 @@ class Matcher(metaclass=MatcherMeta): :参数: * ``id: str``: 消息 id - * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 + * ``prompt: Union[str, Message, MessageSegment, MessageTemplate]``: 消息内容 * ``**kwargs``: 其他传递给 ``bot.send`` 的参数,请参考对应 adapter 的 bot 对象 api """ matcher = current_matcher.get() diff --git a/poetry.lock b/poetry.lock index f59d469b..f91e24f1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -229,7 +229,7 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "2.0.9" +version = "2.0.10" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -344,7 +344,7 @@ python-versions = ">=3.5" [[package]] name = "httpcore" -version = "0.14.3" +version = "0.14.4" description = "A minimal low-level HTTP client." category = "main" optional = true @@ -372,7 +372,7 @@ test = ["Cython (==0.29.22)"] [[package]] name = "httpx" -version = "0.21.1" +version = "0.21.3" description = "The next generation HTTP client." category = "main" optional = true @@ -555,7 +555,7 @@ pytest-asyncio = "^0.16.0" type = "git" url = "https://github.com/nonebot/nonebug.git" reference = "master" -resolved_reference = "e198b56be8f9ccf53c0d6de38e40fb9c0831c890" +resolved_reference = "123916d7281a49e45a1e6b7472a682bec16290ac" [[package]] name = "packaging" @@ -670,7 +670,7 @@ dev = ["black", "coverage", "docformatter", "flake8", "flake8-black", "flake8-bu [[package]] name = "pygments" -version = "2.11.1" +version = "2.11.2" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false @@ -798,7 +798,7 @@ dotenv = ["python-dotenv"] [[package]] name = "requests" -version = "2.27.0" +version = "2.27.1" description = "Python HTTP for Humans." category = "dev" optional = false @@ -1452,8 +1452,8 @@ cffi = [ {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.9.tar.gz", hash = "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"}, - {file = "charset_normalizer-2.0.9-py3-none-any.whl", hash = "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721"}, + {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"}, + {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"}, ] click = [ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, @@ -1611,8 +1611,8 @@ html2text = [ {file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"}, ] httpcore = [ - {file = "httpcore-0.14.3-py3-none-any.whl", hash = "sha256:9a98d2416b78976fc5396ff1f6b26ae9885efbb3105d24eed490f20ab4c95ec1"}, - {file = "httpcore-0.14.3.tar.gz", hash = "sha256:d10162a63265a0228d5807964bd964478cbdb5178f9a2eedfebb2faba27eef5d"}, + {file = "httpcore-0.14.4-py3-none-any.whl", hash = "sha256:9410fe352bea732311f2b2bee0555c8cc5e62b9a73b9d3272fe125a2aa6eb28e"}, + {file = "httpcore-0.14.4.tar.gz", hash = "sha256:d4305811f604d3c2e22869147392f134796976ff946c96a8cfba87f4e0171d83"}, ] httptools = [ {file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"}, @@ -1632,8 +1632,8 @@ httptools = [ {file = "httptools-0.2.0.tar.gz", hash = "sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0"}, ] httpx = [ - {file = "httpx-0.21.1-py3-none-any.whl", hash = "sha256:208e5ef2ad4d105213463cfd541898ed9d11851b346473539a8425e644bb7c66"}, - {file = "httpx-0.21.1.tar.gz", hash = "sha256:02af20df486b78892a614a7ccd4e4e86a5409ec4981ab0e422c579a887acad83"}, + {file = "httpx-0.21.3-py3-none-any.whl", hash = "sha256:df9a0fd43fa79dbab411d83eb1ea6f7a525c96ad92e60c2d7f40388971b25777"}, + {file = "httpx-0.21.3.tar.gz", hash = "sha256:7a3eb67ef0b8abbd6d9402248ef2f84a76080fa1c839f8662e6eb385640e445a"}, ] hypercorn = [ {file = "Hypercorn-0.13.2-py3-none-any.whl", hash = "sha256:ca18f91ab3fa823cbe9e949738f9f2cc07027cd647c80d8f93e4b1a2a175f112"}, @@ -1928,8 +1928,8 @@ pydash = [ {file = "pydash-5.1.0.tar.gz", hash = "sha256:1b2b050ac1bae049cd07f5920b14fabbe52638f485d9ada1eb115a9eebff6835"}, ] pygments = [ - {file = "Pygments-2.11.1-py3-none-any.whl", hash = "sha256:9135c1af61eec0f650cd1ea1ed8ce298e54d56bcd8cc2ef46edd7702c171337c"}, - {file = "Pygments-2.11.1.tar.gz", hash = "sha256:59b895e326f0fb0d733fd28c6839bd18ad0687ba20efc26d4277fd1d30b971f4"}, + {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, + {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, ] pygtrie = [ {file = "pygtrie-2.4.2.tar.gz", hash = "sha256:43205559d28863358dbbf25045029f58e2ab357317a59b11f11ade278ac64692"}, @@ -1998,8 +1998,8 @@ quart = [ {file = "Quart-0.16.2.tar.gz", hash = "sha256:356f4fd795fbf5a7a97bdeb7ca908b5051d0e6e4c0499b2b7c30b743a6938a7e"}, ] requests = [ - {file = "requests-2.27.0-py2.py3-none-any.whl", hash = "sha256:f71a09d7feba4a6b64ffd8e9d9bc60f9bf7d7e19fd0e04362acb1cfc2e3d98df"}, - {file = "requests-2.27.0.tar.gz", hash = "sha256:8e5643905bf20a308e25e4c1dd379117c09000bf8a82ebccc462cfb1b34a16b5"}, + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, ] rfc3986 = [ {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..c70eacf2 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,21 @@ +from pathlib import Path +from typing import TYPE_CHECKING, Set + +import pytest + +if TYPE_CHECKING: + from nonebot.plugin import Plugin + + +@pytest.fixture +def load_plugin(nonebug_init: None) -> Set["Plugin"]: + import nonebot + + return nonebot.load_plugins(str(Path(__file__).parent / "plugins")) + + +@pytest.fixture +def load_example(nonebug_init: None) -> Set["Plugin"]: + import nonebot + + return nonebot.load_plugins(str(Path(__file__).parent / "examples")) diff --git a/tests/examples/weather.py b/tests/examples/weather.py new file mode 100644 index 00000000..c03d70ba --- /dev/null +++ b/tests/examples/weather.py @@ -0,0 +1,29 @@ +from nonebot import on_command +from nonebot.rule import to_me +from nonebot.matcher import Matcher +from nonebot.adapters import Message +from nonebot.params import Arg, CommandArg, ArgPlainText + +weather = on_command("weather", rule=to_me(), aliases={"天气", "天气预报"}, priority=5) + + +@weather.handle() +async def handle_first_receive(matcher: Matcher, args: Message = CommandArg()): + plain_text = args.extract_plain_text() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海 + if plain_text: + matcher.set_arg("city", args) # 如果用户发送了参数则直接赋值 + + +@weather.got("city", prompt="你想查询哪个城市的天气呢?") +async def handle_city(city: Message = Arg(), city_name: str = ArgPlainText("city")): + print(city_name) + if city_name not in ["北京", "上海"]: # 如果参数不符合要求,则提示用户重新输入 + await weather.reject(city.template("你想查询的城市 {city} 暂不支持,请重新输入!")) + + city_weather = await get_weather(city_name) + await weather.finish(city_weather) + + +# 在这里编写获取天气信息的函数 +async def get_weather(city: str) -> str: + return f"{city}的天气是..." diff --git a/tests/adapters/test_template.py b/tests/test_adapters/test_template.py similarity index 100% rename from tests/adapters/test_template.py rename to tests/test_adapters/test_template.py diff --git a/tests/test_examples/test_weather.py b/tests/test_examples/test_weather.py new file mode 100644 index 00000000..08bab064 --- /dev/null +++ b/tests/test_examples/test_weather.py @@ -0,0 +1,64 @@ +import pytest +from nonebug import App + + +@pytest.mark.asyncio +async def test_weather(app: App): + from examples.weather import weather + from utils import make_fake_event, make_fake_message + + # 将此处的 make_fake_message() 替换为你要发送的平台消息 Message 类型 + Message = make_fake_message() + + async with app.test_matcher(weather) as ctx: + bot = ctx.create_bot() + + msg = Message("/天气 上海") + # 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型 + event = make_fake_event(_message=msg, _to_me=True)() + + ctx.receive_event(bot, event) + ctx.should_call_send(event, "上海的天气是...", True) + ctx.should_finished() + + async with app.test_matcher(weather) as ctx: + bot = ctx.create_bot() + + msg = Message("/天气 南京") + # 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型 + event = make_fake_event(_message=msg, _to_me=True)() + + ctx.receive_event(bot, event) + ctx.should_call_send(event, Message("你想查询的城市 南京 暂不支持,请重新输入!"), True) + ctx.should_rejected() + + msg = Message("北京") + event = make_fake_event(_message=msg)() + + ctx.receive_event(bot, event) + ctx.should_call_send(event, "北京的天气是...", True) + ctx.should_finished() + + async with app.test_matcher(weather) as ctx: + bot = ctx.create_bot() + + msg = Message("/天气") + # 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型 + event = make_fake_event(_message=msg, _to_me=True)() + + ctx.receive_event(bot, event) + ctx.should_call_send(event, "你想查询哪个城市的天气呢?", True) + + msg = Message("杭州") + event = make_fake_event(_message=msg)() + + ctx.receive_event(bot, event) + ctx.should_call_send(event, Message("你想查询的城市 杭州 暂不支持,请重新输入!"), True) + ctx.should_rejected() + + msg = Message("北京") + event = make_fake_event(_message=msg)() + + ctx.receive_event(bot, event) + ctx.should_call_send(event, "北京的天气是...", True) + ctx.should_finished() diff --git a/tests/test_init.py b/tests/test_init.py index 84477236..46911755 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -4,8 +4,6 @@ from typing import TYPE_CHECKING, Set import pytest -from utils import load_plugin - if TYPE_CHECKING: from nonebot.plugin import Plugin diff --git a/tests/test_matcher.py b/tests/test_matcher.py index f7647211..abaf1a77 100644 --- a/tests/test_matcher.py +++ b/tests/test_matcher.py @@ -1,7 +1,7 @@ import pytest from nonebug import App -from utils import load_plugin, make_fake_event, make_fake_message +from utils import make_fake_event, make_fake_message @pytest.mark.asyncio diff --git a/tests/test_param.py b/tests/test_param.py index d23f61ff..576d0cbc 100644 --- a/tests/test_param.py +++ b/tests/test_param.py @@ -1,7 +1,7 @@ import pytest from nonebug import App -from utils import load_plugin, make_fake_event, make_fake_message +from utils import make_fake_event, make_fake_message @pytest.mark.asyncio diff --git a/tests/utils.py b/tests/utils.py index a8d0c0ed..09b2a987 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,11 +1,8 @@ -from pathlib import Path -from typing import TYPE_CHECKING, Set, Type, Optional +from typing import TYPE_CHECKING, Type, Optional -import pytest from pydantic import create_model if TYPE_CHECKING: - from nonebot.plugin import Plugin from nonebot.adapters import Event, Message @@ -85,10 +82,3 @@ def make_fake_event( extra = "forbid" return FakeEvent - - -@pytest.fixture -def load_plugin(nonebug_init: None) -> Set["Plugin"]: - import nonebot - - return nonebot.load_plugins(str(Path(__file__).parent / "plugins")) diff --git a/website/docs/tutorial/plugin/example.mdx b/website/docs/tutorial/plugin/example.mdx new file mode 100644 index 00000000..581330ee --- /dev/null +++ b/website/docs/tutorial/plugin/example.mdx @@ -0,0 +1,20 @@ +--- +sidebar_position: 6 +description: 简单插件示例 +--- + +import CodeBlock from "@theme/CodeBlock"; + +# 插件示例 + +## 命令式问答示例 + +import WeatherSource from "!!raw-loader!../../../../tests/examples/weather.py"; + +{WeatherSource} + +### 测试示例 + +import WeatherTest from "!!raw-loader!../../../../tests/test_examples/test_weather.py"; + +{WeatherTest} diff --git a/website/package.json b/website/package.json index 059bee46..5443b9b7 100644 --- a/website/package.json +++ b/website/package.json @@ -30,6 +30,7 @@ "docusaurus-preset-nonepress": "canary", "file-loader": "^6.2.0", "prism-react-renderer": "^1.2.1", + "raw-loader": "^4.0.2", "react": "^17.0.1", "react-color": "^2.19.3", "react-dom": "^17.0.1", diff --git a/yarn.lock b/yarn.lock index a468f344..8ec51665 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6235,6 +6235,14 @@ raw-body@2.4.2: iconv-lite "0.4.24" unpipe "1.0.0" +raw-loader@^4.0.2: + version "4.0.2" + resolved "https://registry.npm.taobao.org/raw-loader/download/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" + integrity sha1-GqxrfRrRUB5m79rBUixz5ZpYTrY= + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + rc@^1.2.8: version "1.2.8" resolved "https://registry.nlark.com/rc/download/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"