nonebot / nonebot Goto Github PK
View Code? Open in Web Editor NEW基于 OneBot 标准的 Python 异步 QQ 机器人框架 / Asynchronous QQ robot framework based on OneBot for Python
Home Page: https://v1.nonebot.dev
License: MIT License
基于 OneBot 标准的 Python 异步 QQ 机器人框架 / Asynchronous QQ robot framework based on OneBot for Python
Home Page: https://v1.nonebot.dev
License: MIT License
由于一套业务逻辑可能是有几个py组成的,都散落在commands下面对于讲究整洁的我来说是个麻烦事,建议commands中支持子目录,这样也好归集同类业务的指令集。
至于指令的full_command是否要包含子目录可以再考虑一下,我也没想太清楚,包含的话使用时有点繁琐,不包含则可能存在同名的问题。
经常出现一种情况是 CoolQ Http API 上报消息成功,但是回复消息失败
目前发现的一定会出现这种情况的情形:代码出了问题产生异常未处理
还有一种不太确定的情况是长时间无人给机器人发消息(额也可能是这期间出现了触发异常的消息?没存日志……)
因为没有保存具体的日志因此暂时没办法贴出问题日志来。。如果需要的话我再写相关代码存吧【另外说一句,希望给一个便捷的文件存储的 Handler 而不是我自己写。。】
在 CoolQ Http API 插件重启即可解决
因此猜测此问题发生的原因:异常导致了 websocket 连接中断
建议的解决方案:全局加上异常处理防止 plugin 导致 websocket 连接断开
看了下建议在load_plugins中增加对子目录的加载#3,所以现目前简单的方法还是在指南中plugins下直接注册命令吗?:sweat_smile:
另外命令名和文件名好像必须一致啊_(:3J∠)_
要理解这段代码,我们要先单独看 6~13 行这个函数。首先,session.get() 函数调... ...
我觉得可以直接把这之后的代码说明改为按句说明,鼠标滚来滚去怪不方便的:joy:
例如自带的 echo 命令输入「/echo/1」,控制台会报错
在文档中的「天气」插件,「/weather/1」会报错,但是「/天气/1」不会
添加计划任务为什么不能发消息到群,我测试计划任务是运行的。
bot = none.get_bot()
机器人对象也获取了。
但是发群消息不行
await bot.send_group_msg(group_id=672076603,message=f'现在{now.hour}点整啦!')
这一句就不执行了
跟着指南走,也就会二级命令的操作:
天气 成都
那么怎么实现像如下的三级命令呢?
天气 成都 后天
会自动回复,在酷Q上的日志也会显示,但是文件夹的日志没有显示处理信息(但显示了开启 HTTP 服务器成功,开始监听 http://0.0.0.0:5700)
CQA-tuling\酷Q Air\app\io.github.richardchien.coolqhttpapi\log
aiocqhttp中看到推荐用ASGI,但none框架下bot对象甚至都不推荐使用?
bot机器人通过pyinstaller 打包,会报WinError 3
请作者帮忙看一下:
Traceback (most recent call last):
File "bot.py", line 6, in
File "site-packages\nonebot\plugin.py", line 72, in load_builtin_plugins
File "site-packages\nonebot\plugin.py", line 48, in load_plugins
FileNotFoundError: [WinError 3] The system cannot find the path specified: 'C:\Users\king\AppData\Local\Temp\4\_MEI23356\nonebot\plugins'
[18796] Failed to execute script bot
split_at_xiaokai_50中控制了群组中必须以@开始的命令机器人才响应,建议放开此控制,改为以装饰器的方式由命令自行声明是否必须@才响应
操作系统:windows
py版本:3.6.6
cqhttpapi版本:4.7.0
none 版本 :0.4.2~0.52(都有)
提示内容:[2018-12-26 19:51:06,002] ASGI Framework Lifespan error, continuing without Lifespan support
引发第三方库:quart,hypercorn
1.根据酷Q的文档,消息中为避免CQ码产生歧义,指定了’[’、’]’、’&’、’,’须进行转义
2.群成员使用群名片而不是昵称来称呼更加和
为减少后续filter和command的修改,转义及群名片最好在cool_http_api.py中直接修改,我已修改实现,因我修改的其他文件包含了非公共的变更,就不推送pull requests给你了,如要实现,可以参考这个代码变更
需求是定义一个插件可以记录所有的消息备查
即任何消息都会触发这个命令、同时不会影响其他命令触发
跟着NoneBot教程走,发现没有<user-id>.json
这个文件啊,所以我新建了一个config目录并在其下新建了QQ号.json
粘贴配置
{
"ws_reverse_api_url": "ws://127.0.0.1:8080/ws/api/",
"ws_reverse_event_url": "ws://127.0.0.1:8080/ws/event/",
"ws_reverse_reconnect_on_code_1000": true,
"use_ws_reverse": true
}
结果无法获取消息:
ujson module not found, using json
msgpack not installed, MsgPackSerializer unavailable
[2018-09-12 23:16:16,995 none] INFO: Succeeded to import "none.plugins.base"
[2018-09-12 23:16:16,995 none] INFO: Running on 127.0.0.1:8080
Running on http://127.0.0.1:8080 (CTRL + C to quit)
在config.cfg中配置对应参数能获取消息,但还是报:
ujson module not found, using json
msgpack not installed, MsgPackSerializer unavailable
虽然能用,强迫症患者还是想问一哈是啥情况?
多线程开启多个Nonebot,现报错如下:
RuntimeError: There is no current event loop in thread 'Thread-1'
上网查了一下,说包括Quart在内的 Coroutine/EventLoop 只存在mian thread中。
请问这种问题如何解决呢?
找到了一个send_private_msg方法,但没找到它的实现,我在on_command调用里引用了一下发现报错了
Task exception was never retrieved future: <Task finished coro=<handle_message() done, defined at C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\message.py:20> exception=ActionFailed() created at C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\__init__.py:39> source_traceback: Object created at (most recent call last): File "C:/E/jupyter_notebook/小工具/pyQQ/test.py", line 11, in <module> none.run() File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\__init__.py", line 104, in run get_bot().run(host=host, port=port, *args, **kwargs) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\__init__.py", line 58, in run *args, **kwargs) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\aiocqhttp\__init__.py", line 195, in run self._server_app.run(host=host, port=port, *args, **kwargs) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\quart\app.py", line 1337, in run run_single(self, config, loop=loop) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\hypercorn\run.py", line 181, in run_single loop.run_forever() File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\base_events.py", line 421, in run_forever self._run_once() File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\base_events.py", line 1423, in _run_once handle._run() File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\events.py", line 145, in _run self._callback(*self._args) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 126, in send return self.gen.send(value) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\__init__.py", line 39, in _ asyncio.ensure_future(handle_message(self, ctx)) Traceback (most recent call last): File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 129, in throw return self.gen.throw(type, value, traceback) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\message.py", line 43, in handle_message handled = await handle_command(bot, ctx) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 129, in throw return self.gen.throw(type, value, traceback) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\command.py", line 465, in handle_command disable_interaction=disable_interaction) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 129, in throw return self.gen.throw(type, value, traceback) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\command.py", line 518, in _real_run_command await asyncio.wait_for(future, timeout) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\tasks.py", line 339, in wait_for return (yield from fut) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 126, in send return self.gen.send(value) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\none\command.py", line 61, in run await self.func(session) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 110, in __next__ return self.gen.send(None) File "C:\E\jupyter_notebook\小工具\pyQQ\plugins\catchSpyder.py", line 140, in join await bot.send_private_msg(user_id=qq, message='哇') File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 110, in __next__ return self.gen.send(None) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\aiocqhttp\api.py", line 170, in call_action action, **params) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\asyncio\coroutines.py", line 110, in __next__ return self.gen.send(None) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\aiocqhttp\api.py", line 140, in call_action return _handle_api_result(await ResultStore.fetch(seq)) File "C:\Users\Sailist\AppData\Local\Programs\Python\Python36\lib\site-packages\aiocqhttp\api.py", line 39, in _handle_api_result raise ActionFailed(retcode=result.get('retcode')) aiocqhttp.exceptions.ActionFailed
用户在进行CommandSession的交互时出现“您有命令正在执行,请稍后再试”,这时用户只能等到timeout,没有任何办法,除非重启整个none应用,如果用户此时可以输入“终止命令”等之类的指令,强行kill掉session,则可以让用户退出本次session后进行其他command操作。
当前,在CommandSession的session处理中,输入的任何文字都会被解析为session中的内容,无法跳出session本身之外进行处理,这个“终止命令”无法被更底层的session调度方监控到并生效,所以应该要有类似操作系统的中断机制,使用“终止命令”之类的保留字来处理这个中断本身。
Task exception was never retrieved
future: <Task finished coro=<ASGIWebsocketConnection.handle_websocket() done, defined at C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\asgi.py:128> exception=AttributeError("'NoneType' object has no attribute 'pop'") created at C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\asgi.py:102>
source_traceback: Object created at (most recent call last):
File "D:\coolq\py\bot.py", line 10, in <module>
none.run()
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\none\__init__.py", line 104, in run
get_bot().run(host=host, port=port, *args, **kwargs)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\none\__init__.py", line 58, in run
*args, **kwargs)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\aiocqhttp\__init__.py", line 224, in run
self._server_app.run(host=host, port=port, *args, **kwargs)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\app.py", line 1359, in run
run_single(self, config, loop=loop)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\hypercorn\asyncio\run.py", line 159, in run_single
loop.run_until_complete(gathered_tasks)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\asyncio\base_events.py", line 571, in run_until_complete
self.run_forever()
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\asyncio\base_events.py", line 539, in run_forever
self._run_once()
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\asyncio\base_events.py", line 1767, in _run_once
handle._run()
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\asyncio\events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\hypercorn\asgi\wsproto.py", line 127, in handle_websocket
await self.handle_asgi_app(event)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\hypercorn\asgi\wsproto.py", line 139, in handle_asgi_app
await asgi_instance(self.asgi_receive, partial(self.asgi_send, event))
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\asgi.py", line 102, in __call__
handler_task = asyncio.ensure_future(self.handle_websocket(websocket, send))
Traceback (most recent call last):
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\asgi.py", line 129, in handle_websocket
response = await self.app.handle_websocket(websocket)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\app.py", line 1589, in handle_websocket
return await self.handle_websocket_exception(error)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\ctx.py", line 133, in __aexit__
await super().__aexit__(exc_type, exc_value, tb)
File "C:\Users\sijj\AppData\Local\Programs\Python\Python37-32\lib\site-packages\quart\ctx.py", line 61, in __aexit__
await _app_ctx_stack.top.pop(exc_value)
AttributeError: 'NoneType' object has no attribute 'pop'
[2018-12-27 11:05:29,570] 127.0.0.1:56030 GET /ws/event/ ws 101 - 48895135
建议Message的append及extend返回值改为Message本身,以便构造Message().append(MessageSegment.at(sender)).append(MessageSegment.text('xxxx')).append(....)之类的连续的操作
怎么调用,调用cqHTTP API时的那个
bot.get_
bot是啥。。。捣腾了几天了,搞不定。。
代码
import nonebot
from nonebot import on_command, CommandSession
@on_command('foo')
async def foo(session: CommandSession):
print('before')
# await session.send(session.state.get('message') or session.current_arg)
msg = session.current_arg
await session.send(msg)
print('end')
if __name__ == '__main__':
nonebot.init()
nonebot.load_builtin_plugins()
nonebot.run(host='127.0.0.1', port=8080)
日志
ujson module not found, using json
msgpack not installed, MsgPackSerializer unavailable
[2019-02-23 05:57:47,362 nonebot] INFO: Succeeded to import "nonebot.plugins.base"
[2019-02-23 05:57:47,362 nonebot] INFO: Running on 127.0.0.1:8080
Running on https://127.0.0.1:8080 (CTRL + C to quit)
[2019-02-23 05:57:47,364] ASGI Framework Lifespan error, continuing without Lifespan support
[2019-02-23 05:57:53,991 nonebot] INFO: Self: 3383679144, Message 175 from 492264408: /foo 123
[2019-02-23 05:57:53,991 nonebot] DEBUG: Parsing command: /foo 123
[2019-02-23 05:57:53,991 nonebot] DEBUG: Matched command start: /
[2019-02-23 05:57:53,992 nonebot] DEBUG: Split command name: ('foo',)
[2019-02-23 05:57:53,992 nonebot] DEBUG: Command ('foo',) found, function: <function foo at 0x7
f0da4074488>
[2019-02-23 05:57:53,993 nonebot] DEBUG: New session of command ('foo',) created
[2019-02-23 05:57:53,993 nonebot] DEBUG: Running command ('foo',)
[2019-02-23 05:57:53,995] 127.0.0.1:40312 POST / 1.1 200 0 7903
before
end
[2019-02-23 05:57:53,996 nonebot] DEBUG: Session of command ('foo',) finished
[2019-02-23 05:57:53,996 nonebot] INFO: Message 175 is handled as a command
是配置问题吗?
我在阅读 message.py 的 handle_message 方法时发现针对 ctx['to_me']
的处理特意写明了仅针对第一个分段,因此造成了群内发消息「XXX@机器人」或者「你在哪呢机器人」这种消息机器人不会做出应答。
这是 bug 还是 feature 呢?如果是 feature 的话又是基于什么考虑呢?
NoneBot 在有限的推广的情况下,被这么多人使用,让我感到很意外。它甚至到现在文档还没有完全写完🙄 。
经过半年多的发展,NoneBot 已经基本可用,虽然还是会有一些小问题,但这不妨碍已经有很多投入使用的应用在使用它。
实际上 NoneBot 还有很多不足,比如:
on_message
装饰器来做到);实际上 NoneBot 的前身,小开机器人,的「过滤器」特性还是比较有用的,可以用来进行消息预处理(比如日志、语音转文本)和拦截(比如屏蔽特定消息类型),但在写 NoneBot 的时候砍掉了 (1.6.0 message_preprocessor
)only_to_me
等 (1.8.2, 1.9.0)PermissionPolicy
)apause
)最近想到 QQ 机器人的开发其实可以从现在流行的语音助手里面寻找灵感,比如对话的回合数、对一些可选参数如何假定、通过辅助的 app 或 web 管理面板来修改配置等。实际上 web 面板这个功能也是可以加入到 NoneBot 的,可以把面板的控制项以可扩展的形式开放 API。
另外,考虑 NoneBot 的定位,我希望它可以被用于任何聊天机器人的场景,无论是闲聊对话、信息查询、推送通知、消息转发、游戏等。
目前命令的参数处理方面的 API 其实也不够好,1.2 版本加入的参数过滤器一定程度上缓解了 args_parser
的复杂和冗余,但总觉得还是不够。
总的来说 NoneBot 还有非常大的提高空间,但由于我今年需要准备考研,因此 NoneBot 会暂停开发将近一年。一年之后,如果时间恰当的话,我打算完全重写这个框架。
如果大家在使用过程中有什么比较好的思路、使用案例,可以在这里讨论,等重写的时候,可以尽可能的考虑更多实际使用需求。
在群中(非私聊)艾特机器人发命令后,在session对话过程中不艾特(注意:没有艾特)机器人发命令相同的语句或者aliases,这个输入不会进入args_parser的处理过程,也不会进入kill的处理过程,直接被none给吞了
如Q号,群名片等。。指南中没有这一块的介绍,求介绍
{
"host": "[::]",
"port": 5700,
"use_http": true,
"ws_host": "[::]",
"ws_port": 6700,
"use_ws": false,
"ws_reverse_url": "",
"ws_reverse_api_url": "",
"ws_reverse_event_url": "",
"ws_reverse_reconnect_interval": 3000,
"ws_reverse_reconnect_on_code_1000": true,
"use_ws_reverse": false,
"post_url": "",
"access_token": "",
"secret": "",
"post_message_format": "string",
"serve_data_files": false,
"update_source": "github",
"update_channel": "stable",
"auto_check_update": false,
"auto_perform_update": false,
"show_log_console": true,
"log_level": "info",
"ws_reverse_api_url": "ws://172.17.0.1:8080/ws/api/",
"ws_reverse_event_url": "ws:/172.17.0.1/:8080/ws/event/",
"ws_reverse_reconnect_on_code_1000": true,
"use_ws_reverse": true
}
import nonebot
if __name__ == '__main__':
nonebot.init()
nonebot.load_builtin_plugins()
nonebot.run(host='172.17.0.1', port=8080)
连不上,酷Q后台一直显示重连,然后发消息给QQ,nonebot这边也没有显示。
是参照教程配置的,使用ws/api和ws/event。
如果一段时间(20-30分钟)不和机器人有任何交互,机器人会停止响应任何指令,包括command和自然语言。但server后台有记录(收到&处理),酷Q日志中有收到消息但无发送消息(向上箭头),怀疑api连接中断?
无论是用hypercorn还是直接python bot.py都有这个问题。
PS酷Q和bot.py在同一ECS上运行。
如果命令格式为
command @某人
使用 session.get('key', prompt='?')
是获取不到参数的
简单来说就是不响应黑名单中用户的任何发言,毕竟现在机器人之间互相聊起来什么的还是挺麻烦的。
但如果挨个命令加忽略机制又很麻烦,如果能在config级别里配置就好了。
现在 PyPI 上的包名叫 none-bot
,实际导入的包名叫 none
,并且 PyPI 上已经存在一个叫 none
的包。打算改名为 nonebot
,统一安装和导入的包名(这个改动可能需要修改现有应用代码),大家觉得有没有什么问题?或者其他建议?
简单研究了一下,好像是因为我设置了这个COMMAND_START.add('')
,导致了QQ群里边@机器人会导致机器人响应两次(一条是@的方式,一条没有@),请问有什么好的解决方法吗?
比如是否自动接收好友申请
,我本是想写在redis里,每次收到请求就on_request
查询一次,但考虑到潜在的如果短时间内频繁收到好友申请就会造成redis频繁读写DDOS,因此如果能读取以后把这个数据存储到机器人当前的运行实例中会好很多。
日志内容:
[2018-12-23 17:13:38,743 none] INFO: Notice: {'group_id': XXXX, 'notice_type': 'group_increase', 'operator_id': 0, 'post_type': 'notice', 'self_id': XXXX, 'sub_type': 'invite', 'time': 1545556418, 'user_id': XXXX}
[2018-12-23 17:13:38,743 none] DEBUG: Emitting event: notice.group_increase.invite
代码:
@on_request('group')
async def group_invite(session: RequestSession):
if session.ctx.get('sub_type') == 'invite':
user_id = session.ctx.get('user_id')
group_id = session.ctx.get('group_id')
if await get_group_accept_value_async():
none.logger.info(f"Received friend invitation of group {group_id} from user {user_id}, approved.")
await session.approve()
else:
none.logger.info(f"Received friend invitation of group {group_id} from user {user_id}, rejected.")
await session.reject()
测试后发现对于人数较多、邀请时提醒“当前群聊人数较多,为减少打扰,对方同意邀请后才会进入群聊”的群可以正常处理请求,但对于测试用小群则上文中函数完全不起作用。
[2018-08-20 23:42:05,238 none] DEBUG: NLP results: [NLPResult(confidence=60.0, cmd_name='tuling', cmd_args={'message': '你是谁'})]
[2018-08-20 23:42:05,238 none] DEBUG: NLP result with highest confidence: NLPResult(confidence=60.0, cmd_name='tuling', cmd_args={'message': '你是谁'})
[2018-08-20 23:42:05,238 none] DEBUG: Running command ('tuling',)
[2018-08-20 23:42:05,244 none] DEBUG: NLP results: [NLPResult(confidence=60.0, cmd_name='tuling', cmd_args={'message': '。。。。'})]
[2018-08-20 23:42:05,244 none] DEBUG: NLP result with highest confidence: NLPResult(confidence=60.0, cmd_name='tuling', cmd_args={'message': '。。。。'})
[2018-08-20 23:42:05,244 none] DEBUG: Running command ('tuling',)
[2018-08-20 23:42:05,627 none] DEBUG: Session of command ('tuling',) finished
[2018-08-20 23:42:05,627 none] INFO: Message 419 is handled as natural language
Task exception was never retrieved
future: <Task finished coro=<handle_message() done, defined at /Users/richard/Projects/none-bot/none/message.py:19> exception=KeyError('/user/1002647525') created at /Users/richard/Projects/none-bot/none/__init__.py:33>
source_traceback: Object created at (most recent call last):
File "/Users/richard/Projects/none-bot/docs/guide/code/awesome-bot-4/bot.py", line 11, in <module>
none.run()
File "/Users/richard/Projects/none-bot/none/__init__.py", line 91, in run
get_bot().run(host=host, port=port, *args, **kwargs)
File "/Users/richard/Projects/none-bot/none/__init__.py", line 51, in run
*args, **kwargs)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/aiocqhttp/__init__.py", line 184, in run
self._server_app.run(host=host, port=port, *args, **kwargs)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/quart/app.py", line 1316, in run
run_single(self, config, loop=loop)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/hypercorn/run.py", line 166, in run_single
loop.run_forever()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 523, in run_forever
self._run_once()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1750, in _run_once
handle._run()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "/Users/richard/Projects/none-bot/none/__init__.py", line 33, in _
asyncio.ensure_future(handle_message(self, ctx))
Traceback (most recent call last):
File "/Users/richard/Projects/none-bot/none/command.py", line 493, in _real_run_command
raise _FinishException(res)
none.command._FinishException: True
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/richard/Projects/none-bot/none/message.py", line 52, in handle_message
handled = await handle_natural_language(bot, ctx)
File "/Users/richard/Projects/none-bot/none/natural_language.py", line 138, in handle_natural_language
check_perm=False)
File "/Users/richard/Projects/none-bot/none/command.py", line 477, in call_command
disable_interaction=disable_interaction)
File "/Users/richard/Projects/none-bot/none/command.py", line 508, in _real_run_command
del _sessions[ctx_id]
KeyError: '/user/1002647525'
[2018-08-20 23:42:05,693 none] DEBUG: Session of command ('tuling',) finished
[2018-08-20 23:42:05,760 none] DEBUG: Session of command ('tuling',) finished
Task exception was never retrieved
future: <Task finished coro=<handle_message() done, defined at /Users/richard/Projects/none-bot/none/message.py:19> exception=KeyError('/user/1002647525') created at /Users/richard/Projects/none-bot/none/__init__.py:33>
source_traceback: Object created at (most recent call last):
File "/Users/richard/Projects/none-bot/docs/guide/code/awesome-bot-4/bot.py", line 11, in <module>
none.run()
File "/Users/richard/Projects/none-bot/none/__init__.py", line 91, in run
get_bot().run(host=host, port=port, *args, **kwargs)
File "/Users/richard/Projects/none-bot/none/__init__.py", line 51, in run
*args, **kwargs)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/aiocqhttp/__init__.py", line 184, in run
self._server_app.run(host=host, port=port, *args, **kwargs)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/quart/app.py", line 1316, in run
run_single(self, config, loop=loop)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/hypercorn/run.py", line 166, in run_single
loop.run_forever()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 523, in run_forever
self._run_once()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1750, in _run_once
handle._run()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "/Users/richard/Projects/none-bot/none/__init__.py", line 33, in _
asyncio.ensure_future(handle_message(self, ctx))
Traceback (most recent call last):
File "/Users/richard/Projects/none-bot/none/command.py", line 493, in _real_run_command
raise _FinishException(res)
none.command._FinishException: True
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/richard/Projects/none-bot/none/message.py", line 52, in handle_message
handled = await handle_natural_language(bot, ctx)
File "/Users/richard/Projects/none-bot/none/natural_language.py", line 138, in handle_natural_language
check_perm=False)
File "/Users/richard/Projects/none-bot/none/command.py", line 477, in call_command
disable_interaction=disable_interaction)
File "/Users/richard/Projects/none-bot/none/command.py", line 508, in _real_run_command
del _sessions[ctx_id]
KeyError: '/user/1002647525'
[2018-08-20 23:42:05,840 none] DEBUG: Session of command ('tuling',) exists
[2018-08-20 23:42:05,840 none] DEBUG: Running command ('tuling',)
[2018-08-20 23:42:05,959 none] DEBUG: Session of command ('tuling',) finished
[2018-08-20 23:42:05,960 none] INFO: Message 416 is handled as natural language
[2018-08-20 23:42:06,338 none] DEBUG: Session of command ('tuling',) finished
Task exception was never retrieved
future: <Task finished coro=<handle_message() done, defined at /Users/richard/Projects/none-bot/none/message.py:19> exception=KeyError('/user/1002647525') created at /Users/richard/Projects/none-bot/none/__init__.py:33>
source_traceback: Object created at (most recent call last):
File "/Users/richard/Projects/none-bot/docs/guide/code/awesome-bot-4/bot.py", line 11, in <module>
none.run()
File "/Users/richard/Projects/none-bot/none/__init__.py", line 91, in run
get_bot().run(host=host, port=port, *args, **kwargs)
File "/Users/richard/Projects/none-bot/none/__init__.py", line 51, in run
*args, **kwargs)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/aiocqhttp/__init__.py", line 184, in run
self._server_app.run(host=host, port=port, *args, **kwargs)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/quart/app.py", line 1316, in run
run_single(self, config, loop=loop)
File "/Users/richard/Projects/none-bot/venv/lib/python3.7/site-packages/hypercorn/run.py", line 166, in run_single
loop.run_forever()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 523, in run_forever
self._run_once()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1750, in _run_once
handle._run()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "/Users/richard/Projects/none-bot/none/__init__.py", line 33, in _
asyncio.ensure_future(handle_message(self, ctx))
Traceback (most recent call last):
File "/Users/richard/Projects/none-bot/none/command.py", line 493, in _real_run_command
raise _FinishException(res)
none.command._FinishException: True
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/richard/Projects/none-bot/none/message.py", line 42, in handle_message
handled = await handle_command(bot, ctx)
File "/Users/richard/Projects/none-bot/none/command.py", line 442, in handle_command
return await _real_run_command(session, ctx_id, check_perm=check_perm)
File "/Users/richard/Projects/none-bot/none/command.py", line 508, in _real_run_command
del _sessions[ctx_id]
KeyError: '/user/1002647525'
CoolQ HTTP中的 set_group_kick之类的api,是需要如何调用呢,或是还未整合进nonebot里面,需要自行解决呢?
看 Http API 是可以实现同步拦截的,不过查了 aiocqhttp 和 none 的文档没找到同步并且拦截消息的办法
目前的思路是,对于加载的每个插件,收集 module 对象的特殊属性 __plugin_name__
和 __plugin_help__
,然后用户可以通过类似于「使用帮助」之类的(同样以插件形式来编写)问话获得使用帮助,例如:
# plugins/weather.py
__plugin_name__ = '天气'
__plugin_help__ = r"""
天气功能使用方法
你可以对我发送「查天气+空格+城市名」来查询当前某城市天气,也可以通过类似于「今天XX市天气怎么样」这样的自然对话来询问我。
""".strip()
# ...
加载了这个命令之后,可以通过下面这样的方式编写使用帮助(目前仅假设,没有实现):
@on_command('help', aliases=['使用帮助', '帮助'])
async def _(sesssion):
plugins = none.get_loaded_plugins()
if session.current_arg_text:
reply = '我现在支持的功能有:\n\n' + '\n'.join(p.name for p in plugins)
else:
plugin = None
for p in plugins:
if p.name == session.current_arg_text:
plugin = p
reply = plugin.help
session.finish(reply)
欢迎讨论~
加上收到事件的日志,优化全局 bot
实例的访问,之后,大概就可以发 0.1.0 了,算是第一个基本可用的版本,文档先不急,等 maruko
写差不多了,再写 None Bot 的文档,同时 aiocqhttp
的接口应该可以稳定,可发布 1.0.0,把文档重新整理一下。
目前CommandSession的args解析通过args_parser进行,所有的参数在一个方法中进行解析和校验,当参数比较多时代码显得非常的臃肿,各种if堆砌,不同参数的解析与校验过于耦合、职责不清,CommandSession的get方法中仅对参数的必录(为空)做了校验及提示,建议在CommandSession的get方法中增加validators参数,validators可为列表类型,支持多个校验器,每个validator校验器参数包含一个内置或自定义的验证方法的入口,及一个返回失败时的消息提示,None本身也可以提供一组缺省的内置校验器,例如数据必录(为空)的校验转为一个校验器,还可以增加数据类型(Number、Date等)的校验器,具体可以参见wtforms的validators.py
调用的方式可以是这样的:
arg1 = session.get('arg1', [(none.validators.required, '要查询的arg1是什么?')] )
arg2 = session.get('arg2',[(none.validators.required, '要查询的arg2是什么?'), (my_validator_func, '你输入了无效的arg2,请重新输入arg2')])
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.