mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-01-19 01:18:19 +08:00
📝 Docs: 更新最佳实践部分的 Alconna 章节 (#2303)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
41498bdf21
commit
dc4ac6d8d7
@ -64,6 +64,15 @@ alc = Alconna(".rd{roll:int}")
|
||||
assert alc.parse(".rd123").header["roll"] == 123
|
||||
```
|
||||
|
||||
Bracket Header 类似 python 里的 f-string 写法,通过 "{}" 声明匹配类型
|
||||
|
||||
"{}" 中的内容为 "name:type or pat":
|
||||
|
||||
- "{}", "{:}": 占位符,等价于 "(.+)"
|
||||
- "{foo}": 等价于 "(?P<foo>.+)"
|
||||
- "{:\d+}": 等价于 "(\d+)"
|
||||
- "{foo:int}": 等价于 "(?P<foo>\d+)",其中 "int" 部分若能转为 `BasePattern` 则读取里面的表达式
|
||||
|
||||
### 组件
|
||||
|
||||
我们可以看到主要的两大组件:`Option` 与 `Subcommand`。
|
||||
@ -74,6 +83,27 @@ assert alc.parse(".rd123").header["roll"] == 123
|
||||
|
||||
`Subcommand` 则可以传入自己的 **Option** 与 **Subcommand**。
|
||||
|
||||
```python
|
||||
from arclet.alconna import Alconna, Option, Subcommand
|
||||
|
||||
alc = Alconna(
|
||||
"command_name",
|
||||
Option("opt1"),
|
||||
Option("--opt2"),
|
||||
Subcommand(
|
||||
"sub1",
|
||||
Option("sub1_opt1"),
|
||||
Option("-SO2"),
|
||||
Subcommand(
|
||||
"sub1_sub1"
|
||||
)
|
||||
),
|
||||
Subcommand(
|
||||
"sub2"
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
他们拥有如下共同参数:
|
||||
|
||||
- `help_text`: 传入该组件的帮助信息
|
||||
@ -237,8 +267,8 @@ assert alc.parse("test123 BARabc").matched
|
||||
|
||||
```python
|
||||
>>> from arclet.alconna import Alconna, Option, Args, append
|
||||
>>> alc = Alconna("gcc", Option("--flag|-F", Args["content", str], action=append))
|
||||
>>> alc.parse("gcc -Fabc -Fdef -Fxyz").query("flag.content")
|
||||
>>> alc = Alconna("gcc", Option("--flag|-F", Args["content", str], action=append, compact=True))
|
||||
>>> alc.parse("gcc -Fabc -Fdef -Fxyz").query[list[str]]("flag.content")
|
||||
['abc', 'def', 'xyz']
|
||||
```
|
||||
|
||||
@ -247,7 +277,7 @@ assert alc.parse("test123 BARabc").matched
|
||||
```python
|
||||
>>> from arclet.alconna import Alconna, Option, Args, count
|
||||
>>> alc = Alconna("pp", Option("--verbose|-v", action=count, default=0))
|
||||
>>> alc.parse("pp -vvv").query("verbose.value")
|
||||
>>> alc.parse("pp -vvv").query[int]("verbose.value")
|
||||
3
|
||||
```
|
||||
|
||||
@ -291,13 +321,13 @@ with namespace(config.default_namespace.name) as np:
|
||||
|
||||
半自动补全为用户提供了推荐后续输入的功能。
|
||||
|
||||
补全默认通过 `--comp` 或 `-cp` 触发:(命名空间配置可修改名称)
|
||||
补全默认通过 `--comp` 或 `-cp` 或 `?` 触发:(命名空间配置可修改名称)
|
||||
|
||||
```python
|
||||
from arclet.alconna import Alconna, Args, Option
|
||||
|
||||
alc = Alconna("test", Args["abc", int]) + Option("foo") + Option("bar")
|
||||
alc.parse("test --comp")
|
||||
alc.parse("test ?")
|
||||
|
||||
'''
|
||||
output
|
||||
@ -323,7 +353,7 @@ output
|
||||
>>> from arclet.alconna import Alconna, Args
|
||||
>>> alc = Alconna("setu", Args["count", int])
|
||||
>>> alc.shortcut("涩图(\d+)张", {"args": ["{0}"]})
|
||||
'Alconna::setu 的快截指令: "涩图(\\d+)张" 添加成功'
|
||||
'Alconna::setu 的快捷指令: "涩图(\\d+)张" 添加成功'
|
||||
>>> alc.parse("涩图3张").query("count")
|
||||
3
|
||||
```
|
||||
@ -331,32 +361,40 @@ output
|
||||
`shortcut` 的第一个参数为快捷指令名称,第二个参数为 `ShortcutArgs`,作为快捷指令的配置
|
||||
|
||||
```python
|
||||
class ShortcutArgs(TypedDict, Generic[TDC]):
|
||||
class ShortcutArgs(TypedDict):
|
||||
"""快捷指令参数"""
|
||||
|
||||
command: NotRequired[TDC]
|
||||
command: NotRequired[DataCollection[Any]]
|
||||
"""快捷指令的命令"""
|
||||
args: NotRequired[list[Any]]
|
||||
"""快捷指令的附带参数"""
|
||||
fuzzy: NotRequired[bool]
|
||||
"""是否允许命令后随参数"""
|
||||
prefix: NotRequired[bool]
|
||||
"""是否调用时保留指令前缀"""
|
||||
```
|
||||
|
||||
当 `fuzzy` 为 False 时,传入 `"涩图1张 abc"` 之类的快捷指令将视为解析失败
|
||||
|
||||
快捷指令允许三类特殊的 placeholder:
|
||||
|
||||
- `{%X}`: 只用于 `command`, 如 `setu {%0}`,表示此处填入快截指令后随的第 X 个参数。
|
||||
- `{%X}`: 如 `setu {%0}`,表示此处填入快捷指令后随的第 X 个参数。
|
||||
|
||||
例如,若快捷指令为 `涩图`, 配置为 `{"command": "setu {%0}"}`, 则指令 `涩图 1` 相当于 `setu 1`
|
||||
|
||||
- `{*}`: 只用于 `command`, 表示此处填入所有后随参数,并且可以通过 `{*X}` 的方式指定组合参数之间的分隔符。
|
||||
- `{X}`: 用于 `command` 与 `args`, 表示此处填入可能的正则匹配的组:
|
||||
- `{*}`: 表示此处填入所有后随参数,并且可以通过 `{*X}` 的方式指定组合参数之间的分隔符。
|
||||
- `{X}`: 表示此处填入可能的正则匹配的组:
|
||||
- 若 `command` 中存在匹配组 `(xxx)`,则 `{X}` 表示第 X 个匹配组的内容
|
||||
- 若 `command` 中存储匹配组 `(?P<xxx>...)`, 则 `{X}` 表示名字为 X 的匹配结果
|
||||
|
||||
除此之外, 通过内置选项 `--shortcut` 可以动态操作快捷指令。
|
||||
|
||||
例如:
|
||||
|
||||
- `cmd --shortcut <key> <cmd>` 来增加一个快捷指令
|
||||
- `cmd --shortcut list` 来列出当前指令的所有快捷指令
|
||||
- `cmd --shortcut delete key` 来删除一个快捷指令
|
||||
|
||||
### 使用模糊匹配
|
||||
|
||||
模糊匹配通过在 Alconna 中设置其 CommandMeta 开启。
|
||||
@ -370,3 +408,77 @@ alc = Alconna("test_fuzzy", meta=CommandMeta(fuzzy_match=True))
|
||||
alc.parse("test_fuzy")
|
||||
# output: test_fuzy is not matched. Do you mean "test_fuzzy"?
|
||||
```
|
||||
|
||||
## 解析结果
|
||||
|
||||
`Alconna.parse` 会返回由 **Arparma** 承载的解析结果。
|
||||
|
||||
`Arpamar` 会有如下参数:
|
||||
|
||||
- 调试类
|
||||
|
||||
- matched: 是否匹配成功
|
||||
- error_data: 解析失败时剩余的数据
|
||||
- error_info: 解析失败时的异常内容
|
||||
- origin: 原始命令,可以类型标注
|
||||
|
||||
- 分析类
|
||||
- header_match: 命令头部的解析结果,包括原始头部、解析后头部、解析结果与可能的正则匹配组
|
||||
- main_args: 命令的主参数的解析结果
|
||||
- options: 命令所有选项的解析结果
|
||||
- subcommands: 命令所有子命令的解析结果
|
||||
- other_args: 除主参数外的其他解析结果
|
||||
- all_matched_args: 所有 Args 的解析结果
|
||||
|
||||
`Arparma` 同时提供了便捷的查询方法 `query[type]()`,会根据传入的 `path` 查找参数并返回
|
||||
|
||||
`path` 支持如下:
|
||||
|
||||
- `main_args`, `options`, ...: 返回对应的属性
|
||||
- `args`: 返回 all_matched_args
|
||||
- `main_args.xxx`, `options.xxx`, ...: 返回字典中 `xxx`键对应的值
|
||||
- `args.xxx`: 返回 all_matched_args 中 `xxx`键对应的值
|
||||
- `options.foo`, `foo`: 返回选项 `foo` 的解析结果 (OptionResult)
|
||||
- `options.foo.value`, `foo.value`: 返回选项 `foo` 的解析值
|
||||
- `options.foo.args`, `foo.args`: 返回选项 `foo` 的解析参数字典
|
||||
- `options.foo.args.bar`, `foo.bar`: 返回选项 `foo` 的参数字典中 `bar` 键对应的值
|
||||
...
|
||||
|
||||
同样, `Arparma["foo.bar"]` 的表现与 `query()` 一致
|
||||
|
||||
## Duplication
|
||||
|
||||
**Duplication** 用来提供更好的自动补全,类似于 **ArgParse** 的 **Namespace**,经测试表现良好(好耶)。
|
||||
|
||||
普通情况下使用,需要利用到 **ArgsStub**、**OptionStub** 和 **SubcommandStub** 三个部分,
|
||||
|
||||
以pip为例,其对应的 Duplication 应如下构造:
|
||||
|
||||
```python
|
||||
from arclet.alconna import OptionResult, Duplication, SubcommandStub
|
||||
|
||||
class MyDup(Duplication):
|
||||
verbose: OptionResult
|
||||
install: SubcommandStub # 选项与子命令对应的stub的变量名必须与其名字相同
|
||||
```
|
||||
|
||||
并在解析时传入 Duplication:
|
||||
|
||||
```python
|
||||
result = alc.parse("pip -v install ...", duplication=MyDup)
|
||||
>>> type(result)
|
||||
<class MyDup>
|
||||
```
|
||||
|
||||
**Duplication** 也可以如 **Namespace** 一样直接标明参数名称和类型:
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
from arclet.alconna import Duplication
|
||||
|
||||
|
||||
class MyDup(Duplication):
|
||||
package: str
|
||||
file: Optional[str] = None
|
||||
url: Optional[str] = None
|
||||
```
|
||||
|
@ -32,3 +32,10 @@ description: 配置项
|
||||
- **默认值**: `False`
|
||||
|
||||
是否全局使用原始消息 (即未经过 to_me 等处理的), 该选项会影响到 Alconna 的匹配行为。
|
||||
|
||||
## alconna_use_param
|
||||
|
||||
- **类型**: `bool`
|
||||
- **默认值**: `True`
|
||||
|
||||
是否使用特制的 Param 提供更好的依赖注入,该选项不会对使用依赖注入函数形式造成影响
|
||||
|
@ -8,7 +8,7 @@ description: 响应规则的使用
|
||||
以下为一个简单的使用示例:
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna.adapters import At
|
||||
from nonebot_plugin_alconna import At
|
||||
from nonebot.adapters.onebot.v12 import Message
|
||||
from nonebot_plugin_alconna.adapters.onebot12 import Image
|
||||
from nonebot_plugin_alconna import AlconnaMatches, on_alconna
|
||||
@ -36,8 +36,8 @@ async def _(result: Arparma = AlconnaMatches()):
|
||||
if result.find("add"):
|
||||
group = await create_role_group(result["add.name"])
|
||||
if result.find("add.member"):
|
||||
ats: tuple[Ob12MS, ...] = result["add.member.target"]
|
||||
group.extend(member.data["user_id"] for member in ats)
|
||||
ats: tuple[At, ...] = result["add.member.target"]
|
||||
group.extend(member.target for member in ats)
|
||||
await rg.finish("添加成功")
|
||||
```
|
||||
|
||||
@ -52,12 +52,14 @@ async def _(result: Arparma = AlconnaMatches()):
|
||||
- `aliases: set[str | tuple[str, ...]] | None = None`: 命令别名, 作用类似于 `on_command` 中的 aliases
|
||||
- `comp_config: CompConfig | None = None`: 补全会话配置, 不传入则不启用补全会话
|
||||
- `use_origin: bool = False`: 是否使用未经 to_me 等处理过的消息
|
||||
- `use_cmd_start`: 是否使用 COMMAND_START 作为命令前缀
|
||||
|
||||
`on_alconna` 返回的是 `Matcher` 的子类 `AlconnaMatcher`,其拓展了四类方法:
|
||||
`on_alconna` 返回的是 `Matcher` 的子类 `AlconnaMatcher`,其拓展了五类方法:
|
||||
|
||||
- `.assign(path, value, or_not)`: 用于对包含多个选项/子命令的命令的分派处理
|
||||
- `.got_path(path, prompt)`: 在 `got` 方法的基础上,会以 path 对应的参数为准,读取传入 message 的最后一个消息段并验证转换
|
||||
- `.got_path(path, prompt, middleware)`: 在 `got` 方法的基础上,会以 path 对应的参数为准,读取传入 message 的最后一个消息段并验证转换
|
||||
- `.set_path_arg(key, value)`, `.get_path_arg(key)`: 类似 `set_arg` 和 `got_arg`,为 `got_path` 的特化版本
|
||||
- `.reject_path(path[, prompt])`: 类似于 `reject_arg`,对应 `got_path`
|
||||
|
||||
用例:
|
||||
|
||||
@ -90,8 +92,8 @@ async def login_got(password: str = AlconnaArg("password")):
|
||||
- `AlconnaResult`: `CommandResult` 类型的依赖注入函数
|
||||
- `AlconnaMatches`: `Arparma` 类型的依赖注入函数
|
||||
- `AlconnaDuplication`: `Duplication` 类型的依赖注入函数
|
||||
- `AlconnaMatch`: `Match` 类型的依赖注入函数
|
||||
- `AlconnaQuery`: `Query` 类型的依赖注入函数
|
||||
- `AlconnaMatch`: `Match` 类型的依赖注入函数,其能够额外传入一个 middleware 函数来处理得到的参数
|
||||
- `AlconnaQuery`: `Query` 类型的依赖注入函数,其能够额外传入一个 middleware 函数来处理得到的参数
|
||||
- `AlconnaExecResult`: 提供挂载在命令上的 callback 的返回结果 (`Dict[str, Any]`) 的依赖注入函数
|
||||
|
||||
可以看到,本插件提供了几类额外的模型:
|
||||
@ -100,12 +102,29 @@ async def login_got(password: str = AlconnaArg("password")):
|
||||
- `Match`: 匹配项,表示参数是否存在于 `all_matched_args` 内,可用 `Match.available` 判断是否匹配,`Match.result` 获取匹配的值
|
||||
- `Query`: 查询项,表示参数是否可由 `Arparma.query` 查询并获得结果,可用 `Query.available` 判断是否查询成功,`Query.result` 获取查询结果
|
||||
|
||||
同时,基于 [`Annotated` 支持](https://github.com/nonebot/nonebot2/pull/1832), 添加了两类注解:
|
||||
同时,基于 [`Annotated` 支持](https://github.com/nonebot/nonebot2/pull/1832), 添加了三类注解:
|
||||
|
||||
- `AlcMatches`:同 `AlconnaMatches`
|
||||
- `AlcResult`:同 `AlconnaResult`
|
||||
- `AlcExecResult`: 同 `AlconnaExecResult`
|
||||
|
||||
而若设置配置项 **ALCONNA_USE_PARAM** (默认为 True) 为 True,则上述依赖注入的目标参数皆不需要使用依赖注入函数:
|
||||
|
||||
```python
|
||||
async def handle(
|
||||
result: CommandResult,
|
||||
arp: Arparma,
|
||||
dup: Duplication,
|
||||
source: Alconna,
|
||||
abc: str, # 类似 Match, 但是若匹配结果不存在对应字段则跳过该 handler
|
||||
foo: Match[str],
|
||||
bar: Query[int] = Query("ttt.bar", 0) # Query 仍然需要一个默认值来传递 path 参数
|
||||
):
|
||||
...
|
||||
```
|
||||
|
||||
该效果对于 `got_path` 下的 Arg 同样有效
|
||||
|
||||
实例:
|
||||
|
||||
```python
|
||||
@ -118,9 +137,7 @@ from nonebot_plugin_alconna import (
|
||||
on_alconna,
|
||||
Match,
|
||||
Query,
|
||||
AlconnaMatch,
|
||||
AlconnaQuery,
|
||||
AlconnaMatches,
|
||||
AlcResult
|
||||
)
|
||||
from arclet.alconna import Alconna, Args, Option, Arparma
|
||||
@ -141,12 +158,12 @@ async def handle_test1(result: AlcResult):
|
||||
await test.send(f"maybe output: {result.output}")
|
||||
|
||||
@test.handle()
|
||||
async def handle_test2(result: Arparma = AlconnaMatches()):
|
||||
async def handle_test2(result: Arparma):
|
||||
await test.send(f"head result: {result.header_result}")
|
||||
await test.send(f"args: {result.all_matched_args}")
|
||||
|
||||
@test.handle()
|
||||
async def handle_test3(bar: Match[int] = AlconnaMatch("bar")):
|
||||
async def handle_test3(bar: Match[int]):
|
||||
if bar.available:
|
||||
await test.send(f"foo={bar.result}")
|
||||
|
||||
@ -160,18 +177,10 @@ async def handle_test4(qux: Query[bool] = AlconnaQuery("baz.qux", False)):
|
||||
|
||||
示例中使用了消息段标注,其中 `At` 属于通用标注,而 `Image` 属于 `onebot12` 适配器下的标注。
|
||||
|
||||
消息段标注会匹配特定的 `MessageSegment`:
|
||||
适配器下的消息段标注会匹配特定的 `MessageSegment`:
|
||||
|
||||
```python
|
||||
...
|
||||
ats: tuple[Ob12MS, ...] = result["add.member.target"]
|
||||
group.extend(member.data["user_id"] for member in ats)
|
||||
```
|
||||
|
||||
:::tip
|
||||
通用标注与适配器标注的区别在于,通用标注会匹配多个适配器中相似类型的消息段。
|
||||
|
||||
通用标注返回的是 `nonebot_plugin_alconna.adapters` 中定义的 `Segment` 模型:
|
||||
而通用标注与适配器标注的区别在于,通用标注会匹配多个适配器中相似类型的消息段,并返回
|
||||
`nonebot_plugin_alconna.adapters` 中定义的 `Segment` 模型:
|
||||
|
||||
```python
|
||||
class Segment:
|
||||
@ -180,8 +189,12 @@ class Segment:
|
||||
|
||||
class At(Segment):
|
||||
"""At对象, 表示一类提醒某用户的元素"""
|
||||
type: Literal["user", "role", "channel"]
|
||||
target: str
|
||||
|
||||
class AtAll(Segment):
|
||||
"""AtAll对象, 表示一类提醒所有人的元素"""
|
||||
|
||||
class Emoji(Segment):
|
||||
"""Emoji对象, 表示一类表情元素"""
|
||||
id: str
|
||||
@ -206,33 +219,85 @@ class Video(Media):
|
||||
class File(Segment):
|
||||
"""File对象, 表示一类文件元素"""
|
||||
id: str
|
||||
name: Optional[str] = field(default=None)
|
||||
name: Optional[str]
|
||||
|
||||
class Reply(Segment):
|
||||
"""Reply对象,表示一类回复消息"""
|
||||
origin: Any
|
||||
id: str
|
||||
msg: Optional[Union[Message, str]]
|
||||
|
||||
class Other(Segment):
|
||||
"""其他 Segment"""
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 特殊装饰器
|
||||
|
||||
`nonebot_plugin_alconna` 提供 了一个 `funcommand` 装饰器, 其用于将一个接受任意参数,
|
||||
返回 `str` 或 `Message` 或 `MessageSegment` 的函数转换为命令响应器。
|
||||
例如:
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna import funcommand
|
||||
|
||||
@funcommand()
|
||||
async def echo(msg: str):
|
||||
return msg
|
||||
...
|
||||
ats: tuple[At, ...] = result["add.member.target"]
|
||||
group.extend(member.target for member in ats)
|
||||
```
|
||||
|
||||
其等同于
|
||||
这样插件使用者就不用考虑平台之间字段的差异
|
||||
|
||||
## 条件控制
|
||||
|
||||
本插件可以通过 `handle(parameterless)` 来控制一个具体的响应函数是否在不满足条件时跳过响应。
|
||||
|
||||
```python
|
||||
from arclet.alconna import Alconna, Args
|
||||
from nonebot_plugin_alconna import on_alconna, AlconnaMatch, Match
|
||||
...
|
||||
from nonebot import require
|
||||
require("nonebot_plugin_alconna")
|
||||
...
|
||||
|
||||
echo = on_alconna(Alconna("echo", Args["msg", str]))
|
||||
from arclet.alconna import Alconna, Subcommand, Option, Args
|
||||
from nonebot_plugin_alconna import assign, on_alconna, CommandResult, Check
|
||||
|
||||
@echo.handle()
|
||||
async def echo_exit(msg: Match[str] = AlconnaMatch("msg")):
|
||||
await echo.finish(msg.result)
|
||||
pip = Alconna(
|
||||
"pip",
|
||||
Subcommand(
|
||||
"install", Args["pak", str],
|
||||
Option("--upgrade"),
|
||||
Option("--force-reinstall")
|
||||
),
|
||||
Subcommand("list", Option("--out-dated"))
|
||||
)
|
||||
|
||||
pip_cmd = on_alconna(pip)
|
||||
|
||||
# 仅在命令为 `pip install` 并且 pak 为 `pip` 时响应
|
||||
@pip_cmd.handle([Check(assign("install.pak", "pip"))])
|
||||
async def update(arp: CommandResult):
|
||||
...
|
||||
|
||||
# 仅在命令为 `pip list` 时响应
|
||||
@pip_cmd.handle([Check(assign("list"))])
|
||||
async def list_(arp: CommandResult):
|
||||
...
|
||||
|
||||
# 仅在命令为 `pip install` 时响应
|
||||
@pip_cmd.handle([Check(assign("install"))])
|
||||
async def install(arp: CommandResult):
|
||||
...
|
||||
```
|
||||
|
||||
或者使用 `AlconnaMatcher.assign`:
|
||||
|
||||
```python
|
||||
@pip_cmd.assign("install.pak", "pip")
|
||||
async def update(arp: CommandResult):
|
||||
...
|
||||
|
||||
# 仅在命令为 `pip list` 时响应
|
||||
@pip_cmd.assign("list")
|
||||
async def list_(arp: CommandResult):
|
||||
...
|
||||
|
||||
# 仅在命令为 `pip install` 时响应
|
||||
@pip_cmd.assign("install")
|
||||
async def install(arp: CommandResult):
|
||||
...
|
||||
```
|
||||
|
180
website/docs/best-practice/alconna/utils.md
Normal file
180
website/docs/best-practice/alconna/utils.md
Normal file
@ -0,0 +1,180 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
description: 杂项
|
||||
---
|
||||
|
||||
# 杂项
|
||||
|
||||
## 通用消息序列
|
||||
|
||||
除了之前提到的通用标注外,`nonebot_plugin_alconna` 还提供了一个类似于 `Message` 的 `UniMessage` 类型,其元素为经过通用标注转换后的 `Segment`。
|
||||
|
||||
你可以通过提供的 `UniversalMessage` 或 `UniMsg` 依赖注入器来获取 `UniMessage`。
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna import UniMsg, At, Reply
|
||||
|
||||
matcher = on_xxx(...)
|
||||
|
||||
@matcher.handle()
|
||||
async def _(msg: UniMsg):
|
||||
reply = msg[Reply, 0]
|
||||
print(reply.origin)
|
||||
if msg.has(At):
|
||||
ats = msg.get(At)
|
||||
print(ats)
|
||||
...
|
||||
```
|
||||
|
||||
### 获取消息纯文本
|
||||
|
||||
类似于 `Message.extract_plain_text()`,用于获取通用消息的纯文本。
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna import UniMessage, At
|
||||
# 提取消息纯文本字符串
|
||||
assert UniMessage(
|
||||
[At("user", "1234"), "text"]
|
||||
).extract_plain_text() == "text"
|
||||
```
|
||||
|
||||
### 遍历
|
||||
|
||||
通用消息序列继承自 `List[Union[str, Segment]]` ,因此可以使用 `for` 循环遍历消息段。
|
||||
|
||||
```python
|
||||
for segment in message: # type: Union[str, Segment]
|
||||
...
|
||||
```
|
||||
|
||||
### 检查消息段
|
||||
|
||||
我们可以通过 `in` 运算符或消息序列的 `has` 方法来:
|
||||
|
||||
```python
|
||||
# 是否存在消息段
|
||||
At("user", "1234") in message
|
||||
# 是否存在指定类型的消息段
|
||||
At in message
|
||||
```
|
||||
|
||||
我们还可以使用 `only` 方法来检查消息中是否仅包含指定的消息段。
|
||||
|
||||
```python
|
||||
# 是否都为 "test"
|
||||
message.only("test")
|
||||
# 是否仅包含指定类型的消息段
|
||||
message.only(str)
|
||||
```
|
||||
|
||||
### 过滤、索引与切片
|
||||
|
||||
消息序列对列表的索引与切片进行了增强,在原有列表 `int` 索引与 `slice` 切片的基础上,支持 `type` 过滤索引与切片。
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna import UniMessage, At, Reply
|
||||
|
||||
message = UniMessage(
|
||||
[
|
||||
Reply(...),
|
||||
"text1",
|
||||
At("user", "1234"),
|
||||
"text2"
|
||||
]
|
||||
)
|
||||
# 索引
|
||||
message[0] == Reply(...)
|
||||
# 切片
|
||||
message[0:2] == UniMessage([Reply(...), "text1"])
|
||||
# 类型过滤
|
||||
message[At] == Message([At("user", "1234")])
|
||||
# 类型索引
|
||||
message[At, 0] == At("user", "1234")
|
||||
# 类型切片
|
||||
message[str, 0:2] == UniMessage(["text1", "text2"])
|
||||
```
|
||||
|
||||
我们也可以通过消息序列的 `include`、`exclude` 方法进行类型过滤。
|
||||
|
||||
```python
|
||||
message.include(str, At)
|
||||
message.exclude(Reply)
|
||||
```
|
||||
|
||||
同样的,消息序列对列表的 `index`、`count` 方法也进行了增强,可以用于索引指定类型的消息段。
|
||||
|
||||
```python
|
||||
# 指定类型首个消息段索引
|
||||
message.index(str) == 1
|
||||
# 指定类型消息段数量
|
||||
message.count(str) == 2
|
||||
```
|
||||
|
||||
此外,消息序列添加了一个 `get` 方法,可以用于获取指定类型指定个数的消息段。
|
||||
|
||||
```python
|
||||
# 获取指定类型指定个数的消息段
|
||||
message.get(str, 1) == UniMessage(["test1"])
|
||||
```
|
||||
|
||||
## 特殊装饰器
|
||||
|
||||
`nonebot_plugin_alconna` 提供 了一个 `funcommand` 装饰器, 其用于将一个接受任意参数,
|
||||
返回 `str` 或 `Message` 或 `MessageSegment` 的函数转换为命令响应器。
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna import funcommand
|
||||
|
||||
@funcommand()
|
||||
async def echo(msg: str):
|
||||
return msg
|
||||
```
|
||||
|
||||
其等同于
|
||||
|
||||
```python
|
||||
from arclet.alconna import Alconna, Args
|
||||
from nonebot_plugin_alconna import on_alconna, AlconnaMatch, Match
|
||||
|
||||
echo = on_alconna(Alconna("echo", Args["msg", str]))
|
||||
|
||||
@echo.handle()
|
||||
async def echo_exit(msg: Match[str] = AlconnaMatch("msg")):
|
||||
await echo.finish(msg.result)
|
||||
```
|
||||
|
||||
## 特殊构造器
|
||||
|
||||
`nonebot_plugin_alconna` 提供了一个 `Command` 构造器,其基于 `arclet.alconna.tools` 中的 `AlconnaString`,
|
||||
以类似 `Koishi` 中注册命令的方式来构建一个 AlconnaMatcher:
|
||||
|
||||
```python
|
||||
from nonebot_plugin_alconna import Command, Arparma
|
||||
|
||||
book = (
|
||||
Command("book", "测试")
|
||||
.option("writer", "-w <id:int>")
|
||||
.option("writer", "--anonymous", {"id": 0})
|
||||
.usage("book [-w <id:int> | --anonymous]")
|
||||
.shortcut("测试", {"args": ["--anonymous"]})
|
||||
.build()
|
||||
)
|
||||
|
||||
@book.handle()
|
||||
async def _(arp: Arparma):
|
||||
await book.send(str(arp.options))
|
||||
```
|
||||
|
||||
甚至,你可以设置 `action` 来设定响应行为:
|
||||
|
||||
```python
|
||||
book = (
|
||||
Command("book", "测试")
|
||||
.option("writer", "-w <id:int>")
|
||||
.option("writer", "--anonymous", {"id": 0})
|
||||
.usage("book [-w <id:int> | --anonymous]")
|
||||
.shortcut("测试", {"args": ["--anonymous"]})
|
||||
.action(lambda options: str(options)) # 会自动通过 bot.send 发送
|
||||
.build()
|
||||
)
|
||||
```
|
@ -303,6 +303,31 @@
|
||||
"type": null,
|
||||
"supported_adapters": null
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_alconna",
|
||||
"project_link": "nonebot-plugin-alconna",
|
||||
"name": "Alconna 命令工具",
|
||||
"desc": "提供一系列工具以在 nonebot 下使用 Alconna 拓展命令解析",
|
||||
"author": "RF-Tar-Railt",
|
||||
"homepage": "https://github.com/nonebot/plugin-alconna",
|
||||
"tags": [
|
||||
{
|
||||
"label": "matcher",
|
||||
"color": "#5280ea"
|
||||
},
|
||||
{
|
||||
"label": "command",
|
||||
"color": "#ea6f52"
|
||||
},
|
||||
{
|
||||
"label": "alconna",
|
||||
"color": "#5452ea"
|
||||
}
|
||||
],
|
||||
"is_official": true,
|
||||
"type": null,
|
||||
"supported_adapters": null
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_mcstatus",
|
||||
"project_link": "nonebot-plugin-mcstatus",
|
||||
@ -3990,31 +4015,6 @@
|
||||
"type": null,
|
||||
"supported_adapters": null
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot_plugin_alconna",
|
||||
"project_link": "nonebot-plugin-alconna",
|
||||
"name": "Alconna 命令工具",
|
||||
"desc": "提供一系列工具以在 nonebot 下使用 Alconna 拓展命令解析",
|
||||
"author": "RF-Tar-Railt",
|
||||
"homepage": "https://github.com/nonebot/plugin-alconna",
|
||||
"tags": [
|
||||
{
|
||||
"label": "matcher",
|
||||
"color": "#5280ea"
|
||||
},
|
||||
{
|
||||
"label": "command",
|
||||
"color": "#ea6f52"
|
||||
},
|
||||
{
|
||||
"label": "alconna",
|
||||
"color": "#5452ea"
|
||||
}
|
||||
],
|
||||
"is_official": true,
|
||||
"type": null,
|
||||
"supported_adapters": null
|
||||
},
|
||||
{
|
||||
"module_name": "nonebot-plugin-mcport",
|
||||
"project_link": "nonebot-plugin-mcport",
|
||||
|
Loading…
Reference in New Issue
Block a user