星际旅行
编写一个星际旅行插件,从简单到复杂
基本使用¶
打开和关闭应用
动作 | 效果 |
---|---|
星际旅行、travel | 打开星际旅行应用 |
退出、exit | 关闭星际旅行应用 |
# ---------- 1 ----------
from ayaka import AyakaBox
from nonebot import on_command
box = AyakaBox("星际旅行-nb")
box.help = "xing ji lv xing"
# 启动应用
m1 = on_command("星际旅行-nb", aliases={"travel-nb"}, rule=box.rule())
@m1.handle()
async def start():
await box.start()
# 关闭应用
m2 = on_command("退出", aliases={"exit"}, rule=box.rule(states="*"))
@m2.handle()
async def close():
await box.close()
# ---------- 1 ----------
from ayaka import AyakaBox
box = AyakaBox("星际旅行")
box.help = "xing ji lv xing"
# 启动应用
box.set_start_cmds(cmds=["星际旅行", "travel"])
# 关闭应用
box.set_close_cmds(cmds=["退出", "exit"])
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:退出
"Bot" 说:已关闭应用 [星际旅行]
旅行¶
地点 | 动作 | 效果 |
---|---|---|
任意地点 | move <地名> | 去指定地点 |
# ---------- 2 ----------
m3 = on_command("move", rule=box.rule(states="*"))
@m3.handle()
async def move():
'''移动'''
arg = str(box.arg)
await box.set_state(arg)
await m3.send(f"前往 {arg}")
# ---------- 2 ----------
@box.on_cmd(cmds="move", states="*")
async def move():
'''移动'''
arg = str(box.arg)
await box.set_state(arg)
await box.send(f"前往 {arg}")
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 地球
"Bot" 说:前往 地球
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
hello!¶
实现打招呼的功能
地点 | 动作 | 效果 |
---|---|---|
地球, 月球, 太阳 | hi | 你好,<地名> ! |
# ---------- 3 ----------
m4 = on_command("hi", rule=box.rule(states=["地球", "月球", "太阳"]))
@m4.handle()
async def say_hi():
'''打招呼'''
await m4.send(f"你好,{box.state}!")
# ---------- 3 ----------
@box.on_cmd(cmds="hi", states=["地球", "月球", "太阳"])
async def say_hi():
'''打招呼'''
await box.send(f"你好,{box.state}!")
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 地球
"Bot" 说:前往 地球
"user" 说:hi
"Bot" 说:你好,地球
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
不同地方不同效果¶
地点 | 动作 | 效果 |
---|---|---|
地球,月球 | drink | 喝水 |
太阳 | drink | 喝太阳风 |
# ---------- 4 ----------
# 相同命令,不同行为
m5 = on_command("drink", rule=box.rule(states=["地球", "月球"]))
@m5.handle()
async def drink():
'''喝水'''
await m5.send("喝水")
m6 = on_command("drink", rule=box.rule(states="太阳"))
@m6.handle()
async def drink():
'''喝太阳风'''
await m6.send("喝太阳风")
# ---------- 4 ----------
# 相同命令,不同行为
@box.on_cmd(cmds="drink", states=["地球", "月球"])
async def drink():
'''喝水'''
await box.send("喝水")
@box.on_cmd(cmds="drink", states="太阳")
async def drink():
'''喝太阳风'''
await box.send("喝太阳风")
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 月球
"Bot" 说:前往 月球
"user" 说:drink
"Bot" 说:喝水
"user" 说:move 太阳
"Bot" 说:前往 太阳
"user" 说:drink
"Bot" 说:喝太阳风
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
缓存¶
宇宙旅游公司又开设了一个新项目:耀斑表演
我们需要先去售票处买耀斑表演的门票,然后才能看表演,一张票不能用多次
地点 | 动作 | 效果 |
---|---|---|
售票处 | buy | 耀斑表演门票+1 |
任意地点 | watch | 看表演 |
# ---------- 5 ----------
from ayaka import BaseModel
class Cache(BaseModel):
ticket:int = 0
m7 = on_command("buy", aliases={"买票"}, rule=box.rule(states="售票处"))
@m7.handle()
async def buy_ticket():
'''买门票'''
cache = box.get_data(Cache)
cache.ticket += 1
await m7.send("耀斑表演门票+1")
m8 = on_command("watch", aliases={"看表演"}, rule=box.rule(states="*"))
@m8.handle()
async def watch():
'''看表演'''
cache = box.get_data(Cache)
if cache.ticket <= 0:
await m8.send("先去售票处买票!")
else:
cache.ticket -= 1
await m8.send("门票-1")
await m8.send("10分甚至9分的好看")
# ---------- 5 ----------
from ayaka import BaseModel
class Cache(BaseModel):
ticket:int = 0
@box.on_cmd(cmds=["buy", "买票"], states="售票处")
async def buy_ticket():
'''买门票'''
cache = box.get_data(Cache)
cache.ticket += 1
await box.send("耀斑表演门票+1")
@box.on_cmd(cmds=["watch", "看表演"], states="*")
async def watch():
'''看表演'''
cache = box.get_data(Cache)
if cache.ticket <= 0:
await box.send("先去售票处买票!")
else:
cache.ticket -= 1
await box.send("门票-1")
await box.send("10分甚至9分的好看")
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:watch
"Bot" 说:先去售票处买票!
"user" 说:move 售票处
"Bot" 说:前往 售票处
"user" 说:buy
"Bot" 说:耀斑表演门票+1
"user" 说:watch
"Bot" 说:10分甚至9分的好看
"user" 说:watch
"Bot" 说:先去售票处买票!
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
命令触发 vs 消息触发¶
刚才的所有回调都是由具体的、指定的命令来触发运行的
然而,你也可以使用消息触发
比如,你随便说了一句话,就能触发该回调运行
# ---------- 6 ----------
from nonebot import on_message
m9 = on_message(rule=box.rule(states="火星"))
@m9.handle()
async def handle():
'''令人震惊的事实'''
await m9.send("你火星了")
# ---------- 6 ----------
@box.on_text(states="火星")
async def handle():
'''令人震惊的事实'''
await box.send("你火星了")
消息触发的优先级低于命令触发
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 火星
"Bot" 说:前往 火星
"user" 说:嗯?
"Bot" 说:你火星了
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
配置项¶
你在沙城里捡到了?块金子,你想设置你到底能捡到几个
# ---------- 7 ----------
from ayaka import AyakaConfig, slow_load_config
class Cache2(BaseModel):
gold:int = 0
@slow_load_config
class Config(AyakaConfig):
__config_name__ = box.name
gold_each_time: int = 1
m10 = on_command("pick", rule=box.rule(states="沙城"))
@m10.handle()
async def get_gold():
'''捡金子'''
config = Config()
cache = box.get_data(Cache2)
cache.gold += config.gold_each_time
await m10.send(f"+{config.gold_each_time} / {cache.gold}")
# ---------- 7 ----------
from ayaka import AyakaConfig, slow_load_config
class Cache2(BaseModel):
gold:int = 0
@slow_load_config
class Config(AyakaConfig):
__config_name__ = box.name
gold_each_time: int = 1
@box.on_cmd(cmds="pick", states="沙城")
async def get_gold():
'''捡金子'''
config = Config()
cache = box.get_data(Cache2)
cache.gold += config.gold_each_time
await box.send(f"+{config.gold_each_time} / {cache.gold}")
查看data/ayaka/星际旅行.json
{
"gold_number": 1
}
修改配置后需要重启bot才生效
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 沙城
"Bot" 说:前往 沙城
"user" 说:pick
"Bot" 说:+1 / 1
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
"sys" 说:修改配置为10并重启bot后
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 沙城
"Bot" 说:前往 沙城
"user" 说:pick
"Bot" 说:+10 / 10
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
动态修改配置项¶
跑到后台修改配置再重启bot实在太麻烦了,你想通过命令修改配置
# ---------- 8 ----------
from ayaka import Numbers
m11 = on_command("change", rule=box.rule(states="沙城"))
@m11.handle()
async def change_gold_number(nums=Numbers("请输入一个数字")):
'''修改捡金子配置'''
config = Config()
config.gold_each_time = int(nums[0])
await m11.send(f"修改每次拾取数量为{config.gold_each_time}")
# ---------- 8 ----------
from ayaka import Numbers
@box.on_cmd(cmds="change", states="沙城")
async def change_gold_number(nums=Numbers("请输入一个数字")):
'''修改捡金子配置'''
config = Config()
config.gold_each_time = int(nums[0])
await box.send(f"修改每次拾取数量为{config.gold_each_time}")
实现效果
"user" 说:travel
"Bot" 说:已打开应用 [星际旅行]
"user" 说:move 沙城
"Bot" 说:前往 沙城
"user" 说:change 100
"Bot" 说:修改每次拾取数量为100
"user" 说:pick
"Bot" 说:+100 / 100
"user" 说:exit
"Bot" 说:已关闭应用 [星际旅行]
插件帮助¶
现在,我们写完了一个小插件了,那么该为它编写帮助了
不幸的是,如果你使用的是AYAKA风格编写代码,那么你已经在上述代码中完成了它
通过分析注册回调的注释(func.__doc__
),ayaka
会自动生成对应的帮助
现在,你只需发送命令盒子帮助
实现效果
"user" 说:盒子帮助
"Bot" 说:[盒子管理器]
- 盒子帮助 展示盒子帮助
- 盒子状态 展示盒子状态
"Bot" 说:[星际旅行]
xing ji lv xing
- 星际旅行/travel 启动应用
[*]
- 退出/exit 关闭应用
- move 移动
- watch/看表演 看表演
[地球]
- hi 打招呼
- drink 喝水
[月球]
- hi 打招呼
- drink 喝水
[太阳]
- hi 打招呼
- drink 喝太阳风
[售票处]
- buy/买票 买门票
[火星]
- <任意文字> 令人震惊的事实
[沙城]
- pick 捡金子
- change 修改捡金子配置
- real_pick 捡金子
全部代码¶
下一步¶
在这里~ ↘