Tian-que / nonebot-adapter-kaiheila

Kaiheila adapter for nonebot2
MIT License
27 stars 10 forks source link

含 KMarkdown 语法时消息的构造问题 #42

Closed MeetWq closed 6 months ago

MeetWq commented 6 months ago

问题来源: https://github.com/noneplugin/nonebot-plugin-memes/issues/68

问题是这样的: nb 的 on_command 会去除消息中的命令,并重新构造消息段: https://github.com/nonebot/nonebot2/blob/fa3bb96417872285dfb247a469dc486bc913f8d7/nonebot/rule.py#L106-L137

如果收到了如下形式的消息:

[MessageSegment(type='kmarkdown', data={'content': '摸 (met)114514(met)', 'raw_content': '摸 @user'})]

命令为“摸”,那么 CommandArg() 得到的消息段类型会变成 text 而不是 kmarkdown

[MessageSegment(type='text', data={'content': '(met)114514(met)'})]

这样会影响对于消息段类型的判断,比如 nonebot-plugin-alconnakmarkdown 消息段中提取 Athttps://github.com/nonebot/plugin-alconna/blob/f9a54133e44a7162c53d0401f1d5148a3bc81385/src/nonebot_plugin_alconna/uniseg/segment.py#L355-L361

所以是否应该修改 Message 传入 str 时的构造方式, 1、默认按 kmarkdown 处理 2、或者增加对于 kmarkdown 的解析或判断,把 textkmarkdown 消息段区分开

ssttkkl commented 6 months ago

这段逻辑是我写的,我说下吧:

kmarkdown消息段的is_text返回true就是为了让on_command能够匹配,但是事实上kmarkdown确实不符合text的定义。

1、默认按 kmarkdown 处理肯定是不可取的。要是用户发送的指令包含*~_之类的markdown符号,构造的时候不转义肯定会出事,转义了插件又没法直接用。 2、解析这个一直没想好怎么做。nb的消息是线性的,kmarkdown是树形的。简单地parse下把最顶层纯文本拿出来还比较可行。(不过member们一直都没时间搞这个

ssttkkl commented 6 months ago

还有个解决方案是把消息中的艾特都单独提出来,比如原始消息是[KMarkdown: /command (met)123(met)]的话,就变成[KMarkdown: /command (met)123(met)][Mention: 123]

MeetWq commented 6 months ago

还有个解决方案是把消息中的艾特都单独提出来,比如原始消息是[KMarkdown: /command (met)123(met)]的话,就变成[KMarkdown: /command (met)123(met)][Mention: 123]

但是我不只要提取at,还需要剩下的文本

ssttkkl commented 6 months ago

还有个解决方案是把消息中的艾特都单独提出来,比如原始消息是[KMarkdown: /command (met)123(met)]的话,就变成[KMarkdown: /command (met)123(met)][Mention: 123]

但是我不只要提取at,还需要剩下的文本

实现这个功能需要一个markdown parser,能够在parse之后获取md元素到文本位置的映射关系,才能把纯文本和kmd分割开。下午看了一圈py的markdown parser没有一个有这种功能的。

说实话我觉得这个功能很难做,短期内估计是没法做的,大概率是最后trade off一下(

ssttkkl commented 6 months ago

可以在这个issue里讨论下 #43

ssttkkl commented 6 months ago

v0.3.0版本引入Mention消息段,并实现了简单消息(KMarkdown消息除了mention的部分以外都是纯文本)直接构造由纯文本与相应Mention构成的消息,应该可以实现大部分插件处理mention的场景