来自 2024 年的回旋镖:
- 下个版本将支持禁用原生别名的功能(你甚至可以把所有名字全删了)
- 关于上面提到的无法触发的问题,会采用「原名可以被插件调用但不能被用户触发」的处理思路
来自 2024 年的回旋镖:
快把香槟全部开了!
对了,如果原名可以被插件调用的话,那要怎么解决冲突的问题呢
原名不能冲突,别名也不能冲突。
原名无法修改,因此两个插件的指令如果原名相同,那么就只能启用一个。
别名可以禁用或者修改,因此两个插件的指令如果别名相同(但是原名不同),你可以先启用一个插件,然后把冲突的别名禁用掉,再启用另一个插件。
原名不能冲突只是为了session.execute吗,还是有其他更深层的原因
无论是原名不能冲突还是别名不能冲突,都是因为如果两个插件别名冲突那么同时安装行为会不确定。
Koishi 希望相同的配置文件产生相同的行为。
在此之上,原名不能冲突有着更多意义:
原名是指令的唯一标识符,如果冲突了一切基于此的设置都做不了。
明白了,谢谢海胆
明白了,谢谢海胆
明白了,谢谢海胆
已更新:
我宁愿同时触发多个指令,把选项、内容都传入每一个注册的指令,对每一个指令都进行权限的判断。
Shigma 提到的都是一些技术上的问题,也许积重难返不好更改了。
这样就会导致:
依据你的愿望设想以下场景
乌拉!
,插件 B 同样注册了指令 foo,返回 foofoo
。session.execute
调用了指令 foo 并期待返回 乌拉!
。你觉得该怎么办呢?
foo:
messages:
return: 乌拉!
foo:
messages:
return: foofoo
如果在同时安装并启用了插件 A 与 B 情况下调用了指令 foo
,应该返回哪一个?
当某个地方禁止发送 乌拉!
,Bot 维护者为了机器人的安全,在同时安装并启用了插件 A 与 B 情况下试图禁止因为 foo 而触发 乌拉!
,但是禁止了 foo 指令之后 foofoo
也一起不允许了,该怎么办呢?
这不是技术上的问题,也不是积重难返不好更改,指令就应当是唯一的。
双胞胎长得再一样也得有不一样的身份证号码,这里的指令就是这个身份证号码。
这个比喻不太恰当,因为一个国家内也有很多重名的人,人名是人名,身份证号是身份证号。
现在的做法就相当于国家给国民任选身份证号,谁不想有个精巧的身份证号呢?
同一个插件能有多份配置,同一个事件名能有多个 listener,同一个指令名为什么不能有多个 action ?
可以给指令相关的函数如 ctx.command session.execute 都提供一个 multiple 选项。比如对于 execute 如果使用了这个选项则执行所有同名指令并返回一个结果数组;如果没有这个选项则执行第一个注册或最后一个注册的指令;如果想要执行某个特定的指令,应找出它的 ID。
在控制台的指令管理界面,每个指令指出定义它的多个插件,对于同名的多个指令,可以独立地对其中某个指令进行禁用、权限管理、本地化等。
这样对你提到的每个场景都有解决方法。
这个设计很愚蠢。 唯一标识符应具有不易发生冲突的属性。
愚蠢的是我自己。
先逐个回答一下:
跟人名有啥关系?这句意思很简单:即使是双胞胎身份证号也不一样。
所以鼓励使用复杂的名称注册指令,并让用户自行在 commands 中配置别称
这是一个游戏查询插件,注册了名为 lc 的指令。
描述:load card,用于加载用户卡牌
功能:将用户卡牌从网站加载,并以 hash(username + cardname) 方式保存这些卡牌到 /data/cache
指令返回:操作成功
这是一个清理插件,注册了名为 lc 的指令。
描述:little cache,用于清理缓存
功能:清理 /data/cache 目录的缓存文件
指令返回:操作成功
用户经历了这些:
如果你觉得这是场景举例本身有问题,那我觉得没有继续讨论下去的必要了,因为避重就轻和偷换概念不是一个好的讨论。
上述后果只是目前想到的冰山一角,重复指令我想不出任何优点。
如果你依然坚持,那么请:
所以说啦,回归原始,指令冲突了让俩开发者打一架就好辣()
这本身就是开发者间自己解决的事情,不需要也不应该浪费 koishi 产能在这种无意义的事情上。
Note: you can, and you should give your plugin command a relatively unique name, as the identifier for managing commands; in the meantime, you could also have aliases which easier to be recall to serve your functions. These two things did not conflict themselves.
我可以看出你是希望把指令唯一id和指令调用名拆成两个东西
然而即便如此也无法解决调用名的冲突问题,同时使用两个action函数是非常不实际的,两个指令大多数时候会有不同的参数列表
并且如此拆分损坏了目前提供的execute函数通过指令唯一id调用指令的功能,是严重的regression
我strong reject这个行为
很简单,因为Event Bus是触发者主导,而Command Router是监听者主导。
什么意思?
在Event Bus中,一个事件需要被触发,一定是对其定义了合适的、统一的类型的,而非随机匹配。在正常的软件设计中,你不会遇到事件名称是同一个,而它的事件参数完全不同的情况。你监听的事件是login,那么一定应当在触发时一个LoginEvent而不是Login2Event,如果你发现这种情况,那么很明显,你的代码有问题该修了。这是被写入类型的(至少在我接触的几个主流Event Bus实现中都是这样的),这些类型应该是在触发时就定义好的,因此这是"触发者主导"
但在指令系统中,不同的指令是完全有可能、也有机会拥有完全不同的参数列表的。因此你定义指令一定是在监听这个指令时定义,那么如果产生冲突,你觉得该怎么解决?
如果目标执行的指令并不是你需要的指令,怎么办?
这里举一个例子,我有两个指令,他们都叫execute,一个负责在本地执行一段bash代码(execute),一个负责在远程执行bash代码(execute.remote),如果我执行了execute rm /data/koishi.db,本来想清除本机的数据文件,结果却把另一台机子上的Koishi.db删除了,怎么办?反过来呢?
不一定所有的指令,都对于环境没有破坏性。你如何处理这种指令?
我想问:你这样做带来了什么好处?是用户的心智负担降低了,还是维护者的心智负担降低了?
首先,我们论证一下用户负担并没有降低: 如L所述,对于相同的指令,我们需要记住它的具体ID,这反而需要用户记忆更多,增加了用户的心智负担。
其次,我们论证一下维护者的心智负担没有降低:你说"一个指令可能被触发其中任意一个",那我请问:当你遇到"指令发生未知错误"时,你怎么知道哪一个插件出现了问题?你可能会说,显示一下现在被激活的指令不就行了?那我想说:Cordis(Koishi 核心)的插件加载顺序是不被保证的,你怎么保证这一次激活的指令,在下一次重启的时候还是激活的呢?
题外话,
这是完全不了解cordis,或者至少是Koishi开发理念的表现。Koishi开发有一个相当重要的性质是正交,即安装了插件B不允许侵入式改变插件A的行为。而这个特性很明显就是在侵入插件A的行为:如果两个插件都被安装,那么我们无法保证哪一个插件被正确执行。而cordis的特性决定了平行插件之间没有任何依赖关系。