pandolia / qqbot

QQBot: A conversation robot base on Tencent's SmartQQ
Other
3.68k stars 877 forks source link

@me 有关的bug #101

Closed laishulu closed 7 years ago

laishulu commented 7 years ago

https://github.com/pandolia/qqbot/blob/ffd88210fc4ed20afb60b6f6674332c0486c38a9/qqbot/qqbotcls.py#L172

重现:

  1. 群中有人叫 abc
  2. 机器人叫 ab

群中出现 @abc, 本身不是 @ab 的,但是这种方式会认为 @ME. 其实我认为@ME 功能没必要,qqbot 应该是内容中立的,内容解释交给上层应用就行了。 比如这里,每个应用检测 @ 的特征都是不同的,你作为一个库去做吃力不讨好。

langrenfengzi commented 7 years ago

这种判断最好应该多匹配一个空格

pandolia commented 7 years ago

@chenhouwu 感谢提醒。我已经在文档中提醒了这一情况,同时提醒用户注意修改自己的群名片,以免误报。我想只能是用户自己来避免这种情况了,在程序内部来精确判断也不是做不到,只不过成本比较大,需要遍历整个成员列表来搜索,可能使程序变慢。 另外,@ME 这个功能需求的人还是很多的,所以还是保留。对于需要的人来说,还是要方便一点。

laishulu commented 7 years ago

自己判断 @ME 的话,也只不过是几行代码的事(你的代码也不过是几行), 而且很直观,为什么要放到库中呢? 库这样做违反了一般来讲库要 内容中立 的原则。

如果一定要放到库中,可否在bot初始化时提供一个 可选的 detect_at_me_func 作为参数传递进去? 如果此参数为None的话,你在库中提供一个默认实现。

hexsum commented 7 years ago

认为@ME功能没有必要的观点实际上都是建立在“webqq本身不支持真正的艾特,只能通过文本识别的方式来检测艾特”

1、但从一个库的角度来说,其他开发者的可能并不一定了解这些底层的技术限制,你认为就几行代码没有必要放在库里是因为你很了解这些内部细节,但其他人使用库的时候可能只是希望需要的功能库本身可以支持

2、webqq也一直在发展演化,未来可能随时会支持真正的艾特也未必不可能,这种情况下更需要库来做特殊支持

3、即便是文本识别也是有技术性的,艾特在消息开头会带空格,艾特在消息结尾可能又没有空格 (web微信上的艾特还会多一些隐藏不可见字符)所以要想识别的准,还是需要库本身提供最正统的对象方法

综上,我认为这个功能是库本身必须具备的,这才是库本身“易用性”“封装性”“注重用户体验”等原则的体现 py一向是秉承“做任何事只需要一种最好的方法” 既然库本身可以提供最好的方法就不需要开发者再去自己瞎折腾了,如果按照“非必要”的角度去考量一个库,那php语言会被人诟病死,大量没必要的函数充斥在整个语言里

hexsum commented 7 years ago

上面没说完,“但php是世界上最好的语言”

laishulu commented 7 years ago

@sjdy521

我目前遇到的情况是,库提供的不堪用,除了fork外也没有办法注入自己的检测逻辑。所以我给出了以下建议:

如果一定要放到库中,可否在bot初始化时提供一个 可选的 detect_at_me_func 作为参数传递进去? 如果此参数为None的话,你在库中提供一个默认实现。

hexsum commented 7 years ago

没办法注入自己的检测逻辑,这就是库本身设计的问题了 让作者看看如何完善

pandolia commented 7 years ago

我也同意 @sjdy521 的看法,@ME 确实是很有必要提供的。至于 @chenhouwu 需要的 “自定义检测逻辑替换默认检测逻辑的功能”,其实也很好实现的,我会将 “默认检测逻辑" 的代码分离出来作为 QQBot 类的一个方法。比如:

class QQBot:
    def detectAtMe(self, nameInGroup, content):
        if ('@'+nameInGroup) in content:            
            content = '[@ME] ' + content.replace('@'+nameInGroup, '')
            return True, content
        else:
            content = content.replace('@ME', '@Me')
            return False, content

    def onPollComplete(self, ctype, fromUin, memberUin, content):
        # ...

        atMe, content = self.detectAtMe(nameInGroup, content)

        if atMe:
            INFO('有人 @ 我:%s[%s]' % (contact, member))

        # ...

如果需要自己定义检测逻辑,只需要在某个时刻,定义一个自己的检测函数(如: myDetectAtMe),然后执行: QQBot.detectAtMe = myDetectAtMe 。就可以了。

pandolia commented 7 years ago

自定义检测函数甚至可以放在插件中,在运行的过程中动态加载。

pandolia commented 7 years ago

@chenhouwu v2.1.17已分离出 detectAtMe 方法,如果需要自己定义检测逻辑,可以按我上面说的方式覆盖。不过覆盖之前请先看一下原有的代码。