Hi,聆听·彼岸



听说,你是我最遥不可及的梦。
What should I do?
What should I do?
I think I'm going to fall in love with myself.

装饰器与插件

发表于 2022-11-17| 分类于 笔记 | | 评论数

装饰器

什么是装饰器?

装饰器指的定义一个函数,该函数是用来为其他函数添加额外的功能

@decorator
def func():
pass
# 等于
func = decorator(func)

实例

在不修改func源代码的前提下,计算并输出运行func用的时间

import time
def f(fun):
def inner():
start = time.time()
fun()
end = time.time()
print(f"{end-start}s")
return inner
@f
def func():
time.sleep(5)

func()

补充:装饰器有括号时,被装饰函数被传给inner,无括号时传给f

插件

我为什么要学装饰器呢?因为插件示例出现了我看不懂的@
但现在能看懂了,开写。
先看看官方示例

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 # 导入获取参数的方法,分别是,获取某次 got 接收的参数,获取命令型消息命令后跟随的参数,获取某次 got 接收的参数的纯文本部分。


weather = on_command("weather", rule=to_me(), aliases={"天气", "天气预报"}, priority=5) #定义消息事件响应器。

# 解说参数
'''
cmd: 指定命令内容
rule: 事件响应规则
aliases: 命令别名
permission: 事件响应权限
handlers: 事件处理函数列表
temp: 是否为临时事件响应器(仅执行一次)
expire_time: 事件响应器最终有效时间点,过时即被删除
priority: 事件响应器优先级
block: 是否阻止事件向更低优先传递
state: 默认 state

注:to_me规则匹配与机器人有关的事件。

'''


@weather.handle() #用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) # 如果用户发送了参数则直接赋值

'''
其中Message是一个类,或者说消息序列,大概长这样
message = Message([
MessageSegment(type='text', data={'text':'hello'}),
MessageSegment(type='image', data={'url':'http://example.com/image.png'}),
MessageSegment(type='text', data={'text':'world'}),
])
,而message.extract_plain_text()可以获得该消息序列的纯文本信息

再看Matcher类,前面说过这是个事件响应器。
其中有如下方法
send
finish
pause
reject
reject_arg
reject_receive
skip
get_receive
set_receive
get_last_receive
get_arg
set_arg
stop_propagation

其中set_arg
设置/覆盖一个 got 接收的参数。
上面的意思是给city参数或者说关键字赋值上海

'''


@weather.got("city", prompt="你想查询哪个城市的天气呢?") #用got函数装饰,got会获取city的值,如果不存在则会发送prompt再获取
async def handle_city(city: Message = Arg(), city_name: str = ArgPlainText("city")): # 如果/天气 上海,则city_name="上海"
if city_name not in ["北京", "上海"]: # 如果参数不符合要求,则提示用户重新输入
# 可以使用平台的 Message 类直接构造模板消息
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}的天气是..."

大概分析得差不多了

下面自己写一个,网上找的机器人聊天api

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
import requests as r
from urllib.parse import urlencode

ai = on_command("陪我聊天",rule = to_me(), aliases={"聊天", "聊会儿"}, priority=5)

@ai.handle()
async def handle_first_receive(matcher: Matcher, args: Message = CommandArg()):
plain_text = args.extract_plain_text()
if plain_text:
matcher.set_arg("city", args)

@ai.got("city", prompt="好啊!聊什么?")
async def handle_city(city: Message = Arg(), city_name: str = ArgPlainText("city")):
if city_name=="不聊了":
await ai.finish("好吧!下次再聊!拜拜咯!")
res = r.get("https://api.qingyunke.com/api.php?key=free&appid=0&"+urlencode({"msg":f"{city_name}"})).json()
await ai.reject(res["content"])

Nice!大功告成!


满分是10分的话,这篇文章你给几分,您的支持将鼓励我继续创作!