Skip to content
本页大纲

Saya Util

Utilities for Graia Framework Community.
来点好用的缩写吧~

仓库地址:GitHub
许可证:MIT
文档版本:v0.2.1
最新版本:PyPI
作者:BlueGlassBlock、RF-Tar-Railt

TIP

你可能已经在本章之外的地方见过相关内容了, 但这一章其实仍然属于《东西要分类好》的进阶, 你最好先那一章看完了再回头看这个。

按多数人的口味,类似 channel.use(...) 的写法其实并不方便,甚至看起来会很丑(死亡缩进kana)。

别担心,这里有更好的写法!

警告

Saya Util 目前仅适用于替代 graia.saya.builtin.broadcast.ListenerSchemagraia.schedule.saya.SchedulerSchema

如果你需要使用其他例如 ConsoleSchema 等元信息模板(Schema,在此处提及过), 那么你目前仍需要以 @channel.use(...) 的方法使用。

以下面的代码为例:

python
...
from graia.ariadne.message.parser.base import DetectPrefix
from graia.ariadne.util.cooldown import CoolDown


@channel.use( 
    ListenerSchema( 
        listening_events=[GroupMessage], 
        inline_dispatchers=[CoolDown(0.1)], 
        decorators=[DetectPrefix("你好")], 
    ) 
) 
async def setu(app: Ariadne, group: Group, message: MessageChain):
    await app.send_message(
        group,
        MessageChain(f"不要说{message.display},来点涩图"),
    )

是不是看着比较头疼?不如试试下面的写法!

python
...
from graia.ariadne.message.parser.base import DetectPrefix
from graia.ariadne.util.cooldown import CoolDown
from graiax.shortcut.saya import listen, dispatch, decorate 


@listen(GroupMessage) 
@dispatch(CoolDown(0.1)) 
@decorate(DetectPrefix("你好")) 
async def setu(app: Ariadne, group: Group, message: MessageChain):
    await app.send_message(
        group,
        MessageChain(f"不要说{message.display},来点涩图"),
    )

是不是感觉焕然一新?

安装

TIP

graia.ariadne.util.saya 也写有类似的 Saya Util 组件, 但前者已停止更新,请尽量从 graiax.shortcut.saya 导入 Saya Util

sh
pdm add graiax-shortcut
sh
poetry add graiax-shortcut
sh
pip install graiax-shortcut

使用方法

Saya Utilchannel.use 一样,需要以装饰器的方式附加在事件处理器(就是你的函数啦~)上。 但是其相对 ListenerSchemaSchedulerSchema 会更加简洁,增加了代码可读性。

注意事项

Saya Util 本质上是对当前的 Channel 的重复使用。 因此,在同一函数/方法上多次使用相同类型的 Saya Util 组件实际上是在为同一个 ListenerSchema 进行追加。

listen

listen 组件负责指定监听的事件,对应于 ListenerSchemalistening_events

即:

python
@listen(GroupMessage, FriendMessage)
async def xxx(): ...

# 等价于
@channel.use(
    ListenerSchema(
        listening_events=[GroupMessage, FriendMessage],
    )
)
async def xxx(): ...

当同时监听多个事件时,也可以把不同的事件使用两个 listen 分开写,如:

python
@listen(GroupMessage)
@listen(FriendMessage)
async def xxx(): ...

WARNING

listen 组件存在时必须将其置于顶层(即位于其他类型修饰器的上面),否则会产生预期外行为:

python
@listen(GroupMessage)  # 顶层
@dispatch(...)
async def xxx(): ...

dispatch

dispatch 组件负责指定处理器上的调度器,对应 ListenerSchemainline_dispatchersSchedulerSchemadispatchers

python
@dispatch(Twilight.from_command(...), AlconnaDispatcher(...))
async def xxx(): ...

# 等价于
@channel.use(
    ListenerSchema(
        ...,
        inline_dispatchers=[Twilight.from_command(...), AlconnaDispatcher(...)],
    )
)
async def xxx(): ...

当同时使用多个调度器时,也可以把不同的调度器使用两个 dispatch 分开写,如:

python
@dispatch(Twilight.from_command(...))
@dispatch(AlconnaDispatcher(...))
async def xxx(): ...

decorate

decorate 组件负责指定处理器上的装饰器,对应 ListenerSchemaSchedulerSchemadecorators

python
@decorate(Depend(...), MentionMe())
async def xxx(): ...

# 等价于
@channel.use(
    ListenerSchema(
        ...,
        decorators=[Depend(...), MentionMe()],
    )
)
async def xxx(): ...

除了无头装饰器以外, decorate 亦支持对已有参数附加装饰器,你可以以此安全地通过类型检查。

  • 仅针对单个参数添加装饰器时:

    python
    @decorate("name", DetectSuffix(...))
  • 需要对多个参数添加装饰器时:

    python
    @decorate({"foo": Depend(...), "bar": MatchTemplate(...)})

priority

priority 组件负责指定优先级,对应 ListenerSchemapriority

python
@priority(8)
async def xxx(): ...
# 等价于
@channel.use(
    ListenerSchema(
        ...,
        priority=8,
    )
)
async def xxx(): ...

除了传入 int 作为该监听器的优先级外,priority 还支持传入一系列事件类型,以代表当前优先级仅对指定的事件类型有效,其余事件按默认优先级(16)处理,例如:

python
@priority(8, GroupMessage, FriendMessage)

提醒

设置指定事件的优先级这个特性需要 Graia Broadcast0.18.0 及以上版本的支持。

关于事件监听器的优先级概念,请参考官方文档

schedule

schedule 组件负责增加一个调度任务,对应于 SchedulerSchematimercancelable

即:

python
@schedule(every_minute())
async def xxx(): ...

# 等价于
@channel.use(
    SchedulerSchema(
        timer=every_minute()
    )
)
async def xxx(): ...

WARNING

schedule 组件存在时其必须置于顶层,否则会产生预期外行为:

python
@schedule(every_minute())  # 顶层
@dispatch(...)
async def xxx(): ...

every

every 是便捷使用 SchedulerSchema 的组件,作为 every_custom_xxxSchedulerSchema 的一同使用。

即:

python
@every(30, "second")
async def xxx(): ...

# 等价于
@channel.use(
    SchedulerSchema(
        timer=every_custom_seconds(30)
    )
)
async def xxx(): ...

value 参数表示时间长度,mode 参数表示定时模式,其只能为 "second", "minute", "hour" 三种,默认为 second

python
@every(30)  # 每 30 秒,等价于 @every(30, "second")
@every(30, "minute")  # 每 30 分钟
@every(30, "hour")  # 每 30 小时

WARNING

every 组件存在时其必须置于顶层,否则会产生预期外行为:

python
@every(30)  # 顶层
@dispatch(...)
async def xxx(): ...

crontab

crontab 是便捷使用 SchedulerSchema 的组件,作为 crontabifySchedulerSchema 的一同使用。

即:

python
@crontab("* * * * 1")
async def xxx(): ...

# 等价于
@channel.use(
    SchedulerSchema(
        timer=crontabify("* * * * 1")
    )
)
async def xxx(): ...

WARNING

crontab 组件存在时其必须置于顶层,否则会产生预期外行为:

python
@crontab("* * * * 1")  # 顶层
@dispatch(...)
async def xxx(): ...

Tip:

本文档使用 CC BY-NC-SA 4.0 协议进行共享,详情见 README

MIT License