Closed EZForever closed 1 year ago
@EZForever 请尝试使用最新开发版进行验证
考虑到
app.send_message()
的作用就是发送消息,消息发送成功就应当返回成功的结果,所以更根本的解决方案是将所有消息发送成功后出现的异常降级为warning,或者至少令其不要体现在异常或返回值上。
很遗憾,Python 不像其他语言可以预先了解所有可能的异常/错误,所以只能暂时先如此修复
理解,这也不能算是Python语言的问题(当然Java只用Checked Exception的话当我没说),考虑到目前只有action=Safe
会试图重发信息,只要这个可重试的异常列表是完备的,这个修复方案没问题。
不过issue这种情况的存在表示了app.send_message()
的报错状态并不能完全代表消息发送成功与否,而这是反用户直觉的。在例如说有人自己使用action=Ignore
然后判断返回值是否为None
的情况下,可能会造成迷惑。建议更新action
的文档和app.send_message()
的文档添加提示,并且列出实际代表消息发送失败的异常列表。
问题
由文档,
app.send_message()
的action
参数可以决定当消息发送失败时该方法的行为,而graia.ariadne.util.send.Safe
可以自动在发送失败后进行若干规避且重发消息。https://github.com/GraiaProject/Ariadne/blob/4b8f52b897d35a69806c95d8255c31902a477dc0/src/graia/ariadne/util/send.py#L78-L82
问题在于
app.send_message()
在发送消息成功后仍有可能产生异常(虽然这种情况极其少见,例如日志记录故障之类),这种情况下app.send_message(action=Ignore)
会像消息发送失败一样返回None
,导致graia.ariadne.util.send.Safe
多次试图重发已经发出的消息,造成简短的消息轰炸,并可能造成风控察觉。这个行为直接把Safe
变成了不安全的。如何复现
这里借用Python的一个bug python/cpython#104231 ,以及issue中举的一个例子,构造一个日志抛异常的情形。这种情形在现实应用中也可能出现,例如使用toml读取发送内容的时候。
之后向机器人私聊任意消息,可以观察到hello被连续回复了六次。
预期行为
最直接的workaround是令
graia.ariadne.util.send.Safe
使用app.send_message(action=Strict)
,之后自行判断哪些异常是致命的,但这样在将来可能还是会出现语义问题。考虑到
app.send_message()
的作用就是发送消息,消息发送成功就应当返回成功的结果,所以更根本的解决方案是将所有消息发送成功后出现的异常降级为warning,或者至少令其不要体现在异常或返回值上。使用环境:
日志/截图
无。