Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于 NoneBot 未来发展的思考 #53

Open
stdrc opened this issue Feb 20, 2019 · 20 comments
Open

关于 NoneBot 未来发展的思考 #53

stdrc opened this issue Feb 20, 2019 · 20 comments
Labels
discussion Open discussions on topics related to this project

Comments

@stdrc
Copy link
Member

stdrc commented Feb 20, 2019

NoneBot 在有限的推广的情况下,被这么多人使用,让我感到很意外。它甚至到现在文档还没有完全写完🙄 。

经过半年多的发展,NoneBot 已经基本可用,虽然还是会有一些小问题,但这不妨碍已经有很多投入使用的应用在使用它。

实际上 NoneBot 还有很多不足,比如:

  • 基于 python-aiocqhttp(跟 酷Q 强耦合),无法支持其它机器人平台
  • 过于以「命令」为核心,而忽略了大量其它类型的消息处理需求(虽然可以通过 python-aiocqhttp 的 on_message 装饰器来做到);实际上 NoneBot 的前身,小开机器人,的「过滤器」特性还是比较有用的,可以用来进行消息预处理(比如日志、语音转文本)和拦截(比如屏蔽特定消息类型),但在写 NoneBot 的时候砍掉了 (1.6.0 message_preprocessor)
  • 没有全局黑名单机制,无法简单地屏蔽其它 bot 的消息(实际上这个功能只要有「过滤器」功能就可以轻松实现)
  • 注册命令的选项不够灵活,比如不能对不同命令设置不同的过期时间、超时时间,没有全局权限、全局 only_to_me(1.8.2, 1.9.0)
  • 权限控制功能不够强大,无法进行单用户和群组粒度的控制 (1.8.0, 1.9.0 PermissionPolicy)
  • 命令会话机制针对单个用户做区分,无法简单地实现群组内多人游戏等需求
  • 没有持久化命令会话 (1.8.0 apause)
  • 没有维护用户、群组、系统全局的整体状态,只有命令层面的状态
  • ……

最近想到 QQ 机器人的开发其实可以从现在流行的语音助手里面寻找灵感,比如对话的回合数、对一些可选参数如何假定、通过辅助的 app 或 web 管理面板来修改配置等。实际上 web 面板这个功能也是可以加入到 NoneBot 的,可以把面板的控制项以可扩展的形式开放 API。

另外,考虑 NoneBot 的定位,我希望它可以被用于任何聊天机器人的场景,无论是闲聊对话、信息查询、推送通知、消息转发、游戏等。

目前命令的参数处理方面的 API 其实也不够好,1.2 版本加入的参数过滤器一定程度上缓解了 args_parser 的复杂和冗余,但总觉得还是不够。

总的来说 NoneBot 还有非常大的提高空间,但由于我今年需要准备考研,因此 NoneBot 会暂停开发将近一年。一年之后,如果时间恰当的话,我打算完全重写这个框架。

如果大家在使用过程中有什么比较好的思路、使用案例,可以在这里讨论,等重写的时候,可以尽可能的考虑更多实际使用需求。

@miranquil
Copy link
Contributor

emm……一年后我的机器人看来也要完全重写了?(噗

@needhourger
Copy link

needhourger commented Feb 24, 2019

目前给我的感觉nonebot相较于其他的sdk过于繁琐。文档中对于程序的目录格式要求,以及命令处理的支持
(个人感觉,可能纯粹是因为我太菜)
相较于nonebot很多强大的功能,我似乎更希望nonebot仅仅作为一个基础框架,把用户发来的消息直接转交给我自己的插件程序来处理。

@stdrc
Copy link
Member Author

stdrc commented Feb 24, 2019

相较于nonebot很多强大的功能,我似乎更希望nonebot仅仅作为一个基础框架,把用户发来的消息直接转交给我自己的插件程序来处理。

@needhourger 其实如果真的是这个需求的话,可以使用 python-aiocqhttp,这个 SDK 的定位就是仅仅提供一个最基础的 CQHTTP 插件的 Python binding

@miranquil
Copy link
Contributor

相较于nonebot很多强大的功能,我似乎更希望nonebot仅仅作为一个基础框架,把用户发来的消息直接转交给我自己的插件程序来处理。

@needhourger 其实如果真的是这个需求的话,可以使用 python-aiocqhttp,这个 SDK 的定位就是仅仅提供一个最基础的 CQHTTP 插件的 Python binding

啊,这倒提醒我了。之前是为了图方便和先熟悉一下用的none,现在可以用底层SDK自给自足咯。

@ryan4yin
Copy link

ryan4yin commented Mar 1, 2019

这样的话,我觉得你想做的是把 nonebot 写成一个通用的机器人框架了,不如干脆提供统一的 websocket api,用 aiocqhttp 桥接 nonebot 和 酷Q,tg 也可以直接通过 websocket api 接入同一个 nonebot.

@ryan4yin
Copy link

ryan4yin commented Mar 1, 2019

或者说把 酷Q 独有的一些东西,写成一个 nonebot 插件,独立提供。
tg 也是,写成一个插件。甚至可以提供 tg 账号绑定 QQ 账号的功能,两头不误hhh

群/用户级别的权限,或者一些比较通用的命令,也可以通过 Web 页面来设置、组合。

@satouriko
Copy link

命令会话机制针对单个用户做区分,无法简单地实现群组内多人游戏等需求

顶一下这个,感觉这里面涉及到共享 session 所有权以及所有权转移控制问题。

@satouriko
Copy link

基于 python-aiocqhttp(跟 酷Q 强耦合),无法支持其它机器人平台

这个问题其实主要涉及到 at 和图片的处理,尤其是 at,不同平台真的差距非常大,支持起来负担很大 /流泪

——一个踩过一年坑的人建议还是把精力放在有灵魂的功能上,不要做这么繁琐又没有意义的事情(嘤嘤嘤

@satouriko
Copy link

个人感觉现在
闲聊对话 ✔️
信息查询 ✔️
推送通知 ✔️
消息转发 ✔️
游戏 ❌

@stdrc
Copy link
Member Author

stdrc commented Apr 22, 2019

一个踩过一年坑的人建议还是把精力放在有灵魂的功能上,不要做这么繁琐又没有意义的事情(嘤嘤嘤

23333,适配确实是过于繁琐了,反正先讨论着,到时候再决定怎么写

游戏 ❌

感觉游戏算是个蛮实际的需求,不过我有点不太清楚现在那些游戏都是什么个逻辑,自己没写过

@koke2c95
Copy link

koke2c95 commented May 9, 2019

比如 用户 说了一句
然后说 同一个用户复读,请
才会复读

这样的情况现能实现吗?

RT:使用命令函数触发获取以往消息怎么写

如果写DB,或者全局变量,仅仅是为了这一个功能那实在太亏了

如果不行

是不支持持久化命令会话的原因吗?

@stdrc
Copy link
Member Author

stdrc commented May 10, 2019

@huaji0353 你这个功能必然是要保存每个潜在用户的最近几条消息的

@stdrc stdrc pinned this issue Jan 18, 2020
@nnnewb
Copy link

nnnewb commented Jan 19, 2020

正在用nonebot(个人娱乐用途),很感谢大佬的付出。

使用中遇到了一些细节,刷github的时候看到了这条issue,来抱怨一下 (^_^),想到哪里说到哪里,见谅。

  1. nl_processors 很多的话会影响效率,换成ac自动机可以快一点,现成的库pyahocorasick。这个倒不是很重要。

https://github.com/richardchien/nonebot/blob/7d96bacbb9b979f3e7ae4a33d371863df5933d86/nonebot/natural_language.py#L131-L136

  1. log 不方便配置,使用coloredlogs.installlogging.basicConfigdictConfig都不能影响到这个logger。

image

  1. 要求一个config模块不是很合理,这个主要是考虑不能简单地用json.dumps(config)pickle保存配置/加载配置,平白多了很多代码要写。

  2. 关于部署的问题,主要是发图、收图方面,我预期是可以分别部署酷Q和nonebot到两台机器上的,但发图要求把图片放在酷Q的data/image里,导致不能分开部署。这个能由cqhttp提供支持吗?调用方式类似于这样:

msg=Message()
msg.append(MessageSegment.image(url)) # url 可以是本地文件路径、网址

如果部署在不同机器上的话,传入本地文件路径时,把图片上传到cqhttp,cqhttp保存到酷q的data/image下,再发送整条消息。传网址时同理,cqhttp先把图片下载到酷Q的data/image下。

这个应该算是cqhttp的问题,这里姑且一提。

关于nonebot未来的发展

我希望它可以被用于任何聊天机器人的场景,无论是闲聊对话、信息查询、推送通知、消息转发、游戏等。

目前我自己使用体验上来看,确实是【命令】重于【对话】,这方面的改进恕我暂时只想到封装一个on_message,和on_commandon_natural_language平级的玩意儿。

最近想到 QQ 机器人的开发其实可以从现在流行的语音助手里面寻找灵感,比如对话的回合数、对一些可选参数如何假定、通过辅助的 app 或 web 管理面板来修改配置等。实际上 web 面板这个功能也是可以加入到 NoneBot 的,可以把面板的控制项以可扩展的形式开放 API。

web面板我简单做过一个,实际用了几天,发现不是很好用,特别是用手机的时候突然想改点什么的时候,切到浏览器打开网页挺麻烦的。前端还得适配移动端,写起来也麻烦。

比较自然的想法是直接发送一条消息给机器人查询、修改配置项:!config get superusers!config add superusers xxxxxxx

不清楚您对web面板是怎么考虑、需求场景是什么样的,所以我还是保留意见。不过提供一些实用的内置命令也许不错=w=。

目前只想到这些,刚发现忘记给star了,补上(^_^)

@stdrc stdrc unpinned this issue Mar 1, 2020
@yp05327
Copy link

yp05327 commented Mar 21, 2020

aiocqhttp是可以自己修改成支持别的机器人平台的 自己改一改就好了

@zzbslayer
Copy link

zzbslayer commented May 7, 2020

“没有全局黑名单机制”,“没有维护用户、群组、系统全局的整体状态“ 这两个个 feature 我是在 https://github.com/Ice-Cirno/HoshinoBot 这个基于 nonebot 的项目中有看到。
这个项目基于 nonebot 封装了一层 service 层,在 service 层实现了全局黑名单机制。群组状态在某些 service 的实现中使用 sqlite 存储。

个人感觉前一个 feature 可以考虑加入 nonebot 框架中。但是状态管理可能还是交给应用层自行管理比较好。

@stdrc stdrc added the discussion Open discussions on topics related to this project label Aug 1, 2020
@cleoold
Copy link
Member

cleoold commented Aug 1, 2020

据我的观察权限控制仅仅靠那几个 int 遠遠不夠,而且這些常量現在的實現只能取聯合不能取交集,導致更鷄肋。我建議弄成類似策略模式:

my_perm_setting = Permission(
    lambda perm, event: (perm.ISSUPERUSER or perm.ISGROUP_MEMBER) and event.sender_id != 123456789
)

@on_command("weather", permission=my_perm_setting)
async def _(session): ...

或者裝飾器。把 lambda 在收到消息的時候跑一下來篩選權限。

@stdrc
Copy link
Member Author

stdrc commented Aug 3, 2020

据我的观察权限控制仅仅靠那几个 int 遠遠不夠,而且這些常量現在的實現只能取聯合不能取交集,導致更鷄肋。我建議弄成類似策略模式:

my_perm_setting = Permission(
    lambda perm, event: (perm.ISSUPERUSER or perm.ISGROUP_MEMBER) and event.sender_id != 123456789
)

@on_command("weather", permission=my_perm_setting)
async def _(session): ...

或者裝飾器。把 lambda 在收到消息的時候跑一下來篩選權限。

有趣,看起来在 nb2 的思路里面这个可以很方便地实现,cc @yanyongyu

@cleoold
Copy link
Member

cleoold commented Aug 5, 2020

据我的观察权限控制仅仅靠那几个 int 遠遠不夠,而且這些常量現在的實現只能取聯合不能取交集,導致更鷄肋。我建議弄成類似策略模式:

my_perm_setting = Permission(
    lambda perm, event: (perm.ISSUPERUSER or perm.ISGROUP_MEMBER) and event.sender_id != 123456789
)

@on_command("weather", permission=my_perm_setting)
async def _(session): ...

或者裝飾器。把 lambda 在收到消息的時候跑一下來篩選權限。

有趣,看起来在 nb2 的思路里面这个可以很方便地实现,cc @yanyongyu

之前在 QQ 群裏看到過兩三次問道如何給命令加冷卻時間,覺得這個功能差不多也可以整到這裏面。我自己就搞過,很容易。只是不瞭解多綫程裏有沒有問題。link

@Shedarshian
Copy link

您好,无意间逛到这个issue,我是个业余爱好者,用nonebot做个人用的qq机器人也已经很久了,非常感谢各位开发者能让我们这么方便的做qqbot。想从一个业余代码的角度聊聊这段时间用nonebot的感受。

看到这里聊到用nonebot做游戏,我从一开始用的时候到现在,在我的qq机器人上做过好几个小游戏,还写过一个比较简单的多人对战游戏的API。我的qq机器人是指令型的而不是对话型的,很大程度上是因为nonebot本身就是指令型的。nonebot的session确实无法直接用来做多人游戏,所以我一开始写游戏API的时候逻辑是完全和session这个逻辑无关的,就是在插件里自己维护一些Game对象,用户对话时操作Game对象,独立完成判断。用这个API我写过几个多人的或是单人的小游戏,用指令进入/退出游戏,游戏过程中通过on_natural_language装饰的函数处理游戏操作。
6V({BUANV1$BW%`A0JRO~(1

一段时间前,我看到nonebot 1.8.0更新了CommandSession.aget函数,我惊呼这就是我很久之前就想过但是自己又无法实现的功能,在目前session绑定到用户的情况下,有这个异步暂停的功能可以实现很多复杂的想法。我最近在维护的一个多人游戏就很大程度上受益于这个函数。这个游戏是一个有复杂结算机制的卡牌游戏,诸如摸牌弃牌使用手牌等等都可能会有嵌套结算。使用手牌时可能需要选定对象,或是手牌超出上限需要弃牌这些都是需要借助aget异步暂停才得以实现的。虽然在整个游戏的层面上仍然是类似于之前的逻辑,Game对象本身存在插件中,但是我也对用户交互这里做了一些自己的封装(虽然这一部分是参考了一些我学软件工程的同学的意见)。我先是对session做了一个简单的包装,使它携带一个缓冲区,在需要的时候再进行flush,这是因为游戏结算可能会在同一次用户交互时显示很多次结算信息,这些信息需要打包到一条消息里进行发送。在用户数据这一块,由于这个游戏不是回合制的,不同用户的交互之间会有穿插,而攻击之类的操作也可能会涉及到其他用户,我使用了一个UserData类存数据,对每一个用户绑定同一个UserData,然后User类保有一个UserData对象和一个带缓冲区的session,在每次交互时创建交互结束时删除,这样与同一个用户相关的所有操作结果会输出到同一个缓冲区然后flush。
(当然这是比较specific的idea,更general一点的可能还是session支持多人这个比较现实吧......)

关于其他部分我也有一些个人的想法。虽然比较不好意思,我在使用的时候是对nonebot本身的源码做了一些修改的。我在使用时发现了几个瓶颈。第一个问题是指令的帮助,我将指令帮助文本放在了函数的__doc__里,依靠反射获取帮助文本,那么查找帮助文本的时候就需要从nonebot的Command里去寻找,这本身比较简单。但是我遇到的问题是,假设我有一个指令play.game1,一个指令play.game2,我想在调用指令play时自动发送play的帮助文档。在nonebot 1.8.0以前的时候指令是树状存储的,无法同时创建指令playplay.game1,我也只能对nonebot的源码做少量的修改来达到这一要求。当然在我现在使用的版本1.8.2里命令的储存方式修改了,这也不再是问题了,但是我仍然需要修改on_command函数来达到自动创建play指令(以及一些更复杂的逻辑,比如某些调试用指令需要hide,某些特殊指令不完全依照前缀分类而是应当显示在别的母指令下)的目的。

另一个修改是权限方面的问题。上面也讨论过了,权限控制确实是一个非常复杂的内容,我遇到过有的群的建议是在每天的某些时间开放某些指令,这些也只能用lambda来表示了。目前我自己简单地写了一个类,在我修改后的on_command里传进去,包含“在某些群里可以使用”、“某些群的管理员可用”、额外的lambda限制、是否私聊可用,以及一些储存在文件中的可变项表示“游戏维护中”等。以及还有一点比较重要的是,在某些不可用的情况发送一条消息。比如说在开放时段之外的时间试图调用时会发送提示消息“这个游戏在每天xx点至xx点开放”,甚至更复杂的是这条消息本身也可能包含可变信息需要用lambda来表示等等我觉得都是有可能有需求的。

还有另外一些虽然自己做起来很简单但是也是不可或缺的内容,比如对于复杂游戏可能需要自己维护一个log文件,对于容易抛出error又需要调试的地方需要wrap一下以消息的形式发送error message等等。

再次感谢各位开发者的努力付出。

@cleoold
Copy link
Member

cleoold commented Oct 14, 2021

另一个修改是权限方面的问题。上面也讨论过了,权限控制确实是一个非常复杂的内容,我遇到过有的群的建议是在每天的某些时间开放某些指令,这些也只能用lambda来表示了。目前我自己简单地写了一个类,在我修改后的on_command里传进去,包含“在某些群里可以使用”、“某些群的管理员可用”、额外的lambda限制、是否私聊可用,以及一些储存在文件中的可变项表示“游戏维护中”等。以及还有一点比较重要的是,在某些不可用的情况发送一条消息。比如说在开放时段之外的时间试图调用时会发送提示消息“这个游戏在每天xx点至xx点开放”,甚至更复杂的是这条消息本身也可能包含可变信息需要用lambda来表示等等我觉得都是有可能有需求的。

还有另外一些虽然自己做起来很简单但是也是不可或缺的内容,比如对于复杂游戏可能需要自己维护一个log文件,对于容易抛出error又需要调试的地方需要wrap一下以消息的形式发送error message等等。

再次感谢各位开发者的努力付出。

實際上用 lambda 表示權限在 1.8.0 就引入了,你可以看下文檔 https://docs.nonebot.dev/advanced/legacy_features.html#%E6%9D%83%E9%99%90%E5%A3%B0%E6%98%8E%E5%B8%B8%E9%87%8Fhttps://docs.nonebot.dev/advanced/permission.html

(and,現在最新版本是 1.9.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Open discussions on topics related to this project
Projects
None yet
Development

No branches or pull requests