Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1076682
  • 博文数量: 165
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1351
  • 用 户 组: 普通用户
  • 注册时间: 2016-03-11 14:13
个人简介

狂甩酷拽吊炸天

文章分类

全部博文(165)

文章存档

2024年(1)

2023年(1)

2022年(3)

2021年(4)

2020年(17)

2019年(37)

2018年(17)

2017年(35)

2016年(50)

分类: Python/Ruby

2017-06-05 18:48:14

一、介绍

QQBot 是一个用 python 实现的、基于腾讯 SmartQQ 协议的简单 QQ 机器人,可运行在 Linux 、 Windows 和 Mac OSX 平台下。

本项目 github 地址:

你可以通过扩展 QQBot 来实现:

  • 监控、收集 QQ 消息
  • 自动消息推送
  • 聊天机器人
  • 通过 QQ 远程控制你的设备

二、安装方法

在 Python 2.7/3.4/3.5 下使用,用 pip 安装:

1
pip install qqbot

原 2.0 版的用户请先到 issue74 查看 2.1 版的升级和改动。

注:一般安装有 Python 的系统都已经自带 pip 了。 Windows 下,请确保安装 Python 的时候勾选了 pip 和 Add python.exe to Path。如果系统中没有 pip ,请到 pip主页 下载 get-pip.py 并运行,可将 pip 安装至系统中。

三、使用方法

1. 启动 QQBot

在命令行输入: qqbot 。启动过程中会自动弹出二维码图片,需要用手机 QQ 客户端扫码并授权登录。启动成功后,会将本次登录信息保存到本地文件中,下次启动时,可以输入: qqbot -q qq号码 ,先尝试从本地文件中恢复登录信息(不需要手动扫码),只有恢复不成功或登录信息已过期时才会需要手动扫码登录。一般来说,保存的登录信息将在 2 天之后过期。

注意: Linux 下,需要系统中有 gvfs-open 或者 shotwell 命令才能自动弹出二维码图片(一般安装有 GNOME 虚拟文件系统 gvfs 的系统中都会含这两个命令之一)。 Windows10 下,需要系统中已设置了 png 图片文件的默认打开程序才能自动弹出二维码图片。

若系统无法自动弹出二维码图片,可以手动打开图片文件进行扫码,也可以将二维码显示模式设置为 邮箱模式/服务器模式/文本模式 进行扫码,详见本文档的第七节。

2. 操作 QQBot

QQBot 启动后,在另一个控制台窗口使用 qq 命令来操作 QQBot ,目前提供以下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1) 帮助、停机和重启命令
    qq help|stop|restart
 
2) 联系人查询命令
    qq list buddy|group|discuss|group-member|discuss-member [oqq|oname|okey=oval] [qq|name|key=val]
 
3) 消息发送命令
    qq send buddy|group|discuss qq|name|key=val message
 
4) 群管理命令: 设置/取消管理员 、 设置/删除群名片 、 群成员禁言 以及 踢除群成员
    qq group-set-admin ginfo minfo1,minfo2,...
    qq group-unset-admin ginfo minfo1,minfo2,...
    qq group-set-card ginfo minfo1,minfo2,... card
    qq group-unset-card ginfo minfo1,minfo2,...
    qq group-shut ginfo minfo1,minfo2,... [t]
    qq group-kick ginfo minfo1,minfo2,...
 
5) 加载/卸载/显示 插件
    qq plug/unplug plugin-name
    qq plugins

list 命令提供强大的联系人查询功能,用法示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 列出所有好友
qq list buddy
 
# 列出 QQ 为 123456 的群
qq list group 123456
 
# 列出备注名为 jack 的好友
qq list buddy mark=jack
 
# 列出 群“456班” 的所有成员
qq list group-member 456班
 
# 列出 群“456班” 中名片为 “mike” 的成员
qq list group-member 456班 card=mike
 
# 列出 讨论组“XX小组” 中名为 jack 的好友
qq list discuss-member XX小组 jack

其中第三、四个参数如果是 key=val 的格式,则应为 name=xx|nick=xx|mark=xx|card=xx|qq=xx 的格式,如果不是 key=val 的格式,则按以下原则进行处理:若是一串数字,则按 QQ 号进行查询,否则,按名称进行查询。

如果存在重名现象,会列出所有重名的联系人。如:

1
qq list group 机器人测试

将列出所有名为 “机器人测试” 的群。

send 命令中第三个参数和 list 命令中的第三、四个参数格式一致。要注意,如果有重名现象,会给所有重名的联系人发信息。 另外要注意,第二个参数只能是 buddy/group/discuss ,不能是 group-member/discuss-member 。

可以在消息内容中嵌入“/微笑”等表情关键词来向对方发送表情,详见 facemap.py。还可以在消息内容中使用 \n,\t 这两个转义字符(如: send buddy jack 第一行\n第二行)。

群管理命令中的 ginfo 和 minfo 和 list 命令中的第三、四个参数格式一致。例如:

1
2
3
4
5
# 设置 jack,mike,jim 为 群“456班” 的管理员
qq group-set-admin 456班 jack,mike,jm
 
# 禁止 群“456班” 中的 jack,mike,jim 发言( 2 分钟)
qq group-shut 456班 jack,mike,jm 120

以上所有命令都提供对应的 HTTP API 接口,供 web 前端开发者调用,接口的 url 地址为 {command} ,只需要将 qq 后面的命令各参数用 "/" 分隔开替换 url 中的 command 就可以了,如: send/buddy/jack/hello ,其他示例详见 urltestbot.txt 。注意:如果命令中含有中文或特殊字符,需要先进行 url 编码( utf8 ),例如,调用 send/buddy/jack/nihao%20%E4%BD%A0%E5%A5%BD%20wohao 将发送消息 ”nihao 你好 wohao“ 。(提示:在 JavaScript 中,可以使用 encodeURIComponent 函数进行编码)。

另外,QQBot 启动后,用另外一个 QQ 向本 QQ 发送 “--version” ,则 QQBot 会自动回复: “QQBot-v2.x.x” 。

四、实现你自己的 QQ 机器人

实现自己的 QQ 机器人非常简单,只需要注册一个自己的消息响应函数。示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
from qqbot import QQBotSlot as qqbotslot, RunBot
 
@qqbotslot
def onQQMessage(bot, contact, member, content):
    if content == '-hello':
        bot.SendTo(contact, '你好,我是QQ机器人')
    elif content == '-stop':
        bot.SendTo(contact, 'QQ机器人已关闭')
        bot.Stop()
 
if __name__ == '__main__':
    RunBot()

注意,上面注册的响应函数的函数名必须为 “onQQMessage” ,函数参数也必须和上面的一致。

将以上代码另存为 sample.py ,关掉前面的 qqbot 进程,再在命令行输入 “python sample.py -q QQ号码” ,就可以启动自己的 QQ 机器人。此时,用另外一个 QQ 向本 QQ 发送消息 “-hello”,则会自动回复 “你好,我是 QQ 机器人”,发送消息 “-stop” 则会关闭 QQ 机器人。

QQBot 开始运行后,每收到一条 QQ 消息,会将消息来源、消息内容以及一个 QQBot 对象传递给上面注册的消息响应函数。其中:

1
2
3
4
bot     : QQBot 对象,提供 List/SendTo/Stop/Restart 四个接口,详见本文档第五节
contact : QContact 对象,消息的发送者,具有 ctype/qq/uin/nick/mark/card/name 属性,这些属性都是 str 对象
member  : QContact 对象,仅当本消息为 群或讨论组 消息时有效,代表实际发消息的成员
content : str 对象,消息内容

一个 QContact 对象代表一个联系人,它的 ctype 属性可以为 'buddy'/'group'/'discuss'/'group-member'/'discuss-member' ,代表 好友/群/讨论组/群成员/讨论组成员 。注意所有 QContact 对象都是 只读对象 ,只能读取它的属性,不能设置它的属性,也不能向它添加额外的属性。 不同类型的 QContact 对象的 nick/mark/card/name 属性所代表的含义有所不同,参见 contact-attr-meannings.png 。

可以调用 QQBot 对象的 SendTo 接口向 QContact 对象发送消息,但要注意:只可以向 好友/群/讨论组 发消息, 不可以向 群成员/讨论组成员 发送消息

除了直接运行 sample.py 文件,还可以将此文件当做一个插件,在 qqbot 的运行过程中动态的加载和卸载。将该文件保存在系统中可以 import 到的目录下(如 python 的安装目录下的 Lib/site-packages 目录),之后,运行 qqbot ,待 QQBot 完全启动后,在另一个控制台输入 qq plug sample ,则可以将此文件中的 onQQMessage 函数注册到 QQBot 的相应事件上去。输入 qq unplugin sample 可以卸载此插件。可以同时加载多个插件,此时各插件中的相应函数会依次被调用(但调用顺序和加载次序无关)。

如果按插件的形式加载 sample.py ,则该文件的内容可简化为:

1
2
3
4
5
6
def onQQMessage(bot, contact, member, content):
    if content == '-hello':
        bot.SendTo(contact, '你好,我是QQ机器人')
    elif content == '-stop':
        bot.SendTo(contact, 'QQ机器人已关闭')
        bot.Stop()

插件本质上是一个模块,因此,它可以是一个 py 文件,也可以是一个 package ,只要它放在系统中可以 import 到的目录即可(本文档第七节介绍了指定插件目录的方法)。建议尽量使用插件的形式来扩展 QQBot 。

原 2.1.10 版中的使用继承 QQBot 类来进行扩展的方式可以继续使用,但是,若使用此方式,则插件功能无法使用。

五、 QQBot 对象的接口

QQBot 对象提供 List/SendTo/GroupSetAdmin/GroupSetCard/GroupShut/GroupKick/Stop/Restart 八个公开接口,一般情况下,请勿 调用/存取 此对象的其他 方法/属性 。以下介绍前 6 个接口。

(1) bot.List(tinfo, [cinfo]) --> [contact0, contact1, ..., ]/[]/None

对应上面的 list 命令。返回联系人对象( QContact 对象)列表或者 None 。

List 接口的第一个参数 tinfo 可以为 'buddy'/'group'/'discuss' ,第二个参数是可选的(和 list 命令的第三个参数格式一致)。示例:

1
2
3
4
5
# 返回所有好友的列表:
>>> bot.List('buddy')
 
# 返回名为 “机器人测试” 的群的列表:
>>> bot.List('group', '机器人测试')

List 接口的第一个参数 tinfo 也可以是一个 ctype 等于 'group'/'discuss' 的 QContact 对象,此时,返回的是该 群/讨论组 的成员列表,如以下第二句和第三句分别返回 群“456班” 的成员列表和该群中名片为 “jack” 的成员列表:

1
2
3
>>> g = bot.List('group', "456班")[0]
>>> bot.List(g)
>>> bot.List(g, 'card=jack')

注意上面第三句不允许是 bot.List(g, card='jack') 的格式。

List 接口的内部执行顺序: 首先在 QQBot 的联系人数据库内查找 tinfo 所代表的联系人列表;若数据库内已有此列表,则在此列表内进行搜索,并返回一个包含 “此列表中所有和 cinfo 匹配的联系人” 的列表;若数据库内没有此列表,则向 QQ 服务器请求数据获取联系人列表,获取成功后将联系人列表保存到数据库内,然后再进行搜索并返回一个包含 “此列表中所有和 cinfo 匹配的联系人” 的列表;如果在向 QQ 服务器请求数据的过程中出错了,则打印相关的失败信息,并返回 None 。

List 接口返回值的含义: 返回一个非空列表表示 tinfo 所指定的联系人列表内所有和 cinfo 匹配的联系人;返回一个空列表表示该联系人列表内没有和 cinfo 匹配的联系人;返回 None 表示向 QQ 服务器请求联系人列表和资料失败,不知道是否有相匹配的联系人。

调用 List 接口后, 务必 先根据以上三种情况对返回值进行判断,然后再执行后续代码。

(2) bot.SendTo(contact, content) --> '向 xx 发消息成功'/'错误:...'

向联系人发送消息。第一个参数为 QContact 对象,第二个参数为消息内容。再次提醒: 只可以向 好友/群/讨论组 发消息, 不允许向 群成员/讨论组成员 发消息

可以在消息内容中嵌入“/微笑”等表情关键词来向对方发送表情,详见 facemap.py。

若发送成功,返回字符串('向 xx 发消息成功')。否则,返回含错误原因的字符串('错误:...')。

(3) bot.GroupXXX(group, membs[, arg]) --> ['成功:...', '成功:...', '错误:...']

对应第三节的群管理命令,共四个接口:

  • 设置/取消管理员: bot.GroupSetAdmin(group, membs, admin=True)
  • 设置/取消群成员名片: bot.GroupSetCard(group, membs, card)
  • 禁止群成员发言: bot.GroupShut(group, membs, t=60)
  • 踢除群成员: bot.GroupKick(group, membs)

其中第一个参数 group 为 群对象( ctype 等于 'group' 的 QContact 对象),第二个参数 membs 为被操作的成员列表。返回值为 membs 中各成员的操作信息。

注意: 1) 第二个参数 membs 是一个 list 对象(如: [memb0,memb1,...] ),而不是一个 QContact 对象; 2) 若 membs 中的某个成员是管理员,则除 SetCard 外的其他接口可能对其无效,尽管此时返回成功信息。 3) 使用这四个接口时,请自行保证登录的用户是该群的管理员,且 membs 中的各成员均属于该群。

六、 注册回调函数、被他人 @ 的通知、定制定时任务

注册回调函数

除了上面提到的 onQQMessage 响应函数,还可以注册 onNewContact/onLostContact/onInterval/onStartupComplete/onFetchComplete 五种事件的回调函数,所有事件以及函数参数格式、含义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@qqbotslot
def onQQMessage(bot, contact, member, content):
    # 当收到 QQ 消息时被调用
    # bot     : QQBot 对象,提供 List/SendTo/Stop/Restart 四个接口,详见文档第五节
    # contact : QContact 对象,消息的发送者,具有 ctype/qq/uin/name/nick/mark/card 属性,这些属性都是 str 对象
    # member  : QContact 对象,仅当本消息为 群或讨论组 消息时有效,代表实际发消息的成员
    # content : str 对象,消息内容
    if content == '--version':
        bot.SendTo(contact, 'QQbot-' + bot.conf.version)
 
@qqbotslot
def onNewContact(bot, contact, owner):
    # 当新增 好友/群/讨论组/群成员/讨论组成员 时被调用
    # 一般情况下联系人变动事件滞后 5 ~ 10 分钟,可以将关心的联系人列表加入到配置文件的 monitorTables 中去
    # 若 monitorTables 中的列表数量较少,则被监视的列表中的联系人变动事件滞后时间将大幅缩短
    # bot     : QQBot 对象
    # contact : QContact 对象,代表新增的联系人
    # owner   : QContact 对象,仅在新增 群成员/讨论组成员 时有效,代表新增成员所在的 群/讨论组
    pass
 
@qqbotslot
def onLostContact(bot, contact, owner):
    # 当失去 好友/群/讨论组/群成员/讨论组成员 时被调用
    # 一般情况下联系人变动事件滞后 5 ~ 10 分钟,可以将关心的联系人列表加入到配置文件的 monitorTables 中去
    # 若 monitorTables 中的列表数量较少,则被监视的列表中的联系人变动事件滞后时间将大幅缩短
    # bot     : QQBot 对象
    # contact : QContact 对象,代表失去的联系人
    # owner   : QContact 对象,仅在失去 群成员/讨论组成员 时有效,代表失去成员所在的 群/讨论组
    pass
 
@qqbotslot
def onInterval(bot):
    # 每隔 5 分钟被调用
    # bot : QQBot 对象
    pass
 
@qqbotslot
def onStartupComplete(bot):
    # 启动工作完成时被调用(本函数被调用后,开始监听 QQ 消息和 qq 命令行工具的命令)
    # bot : QQBot 对象
    pass
 
@qqbotslot
def onFetchComplete(bot):
    # 完成一轮联系人列表刷新时被调用
    # bot : QQBot 对象
    pass

再次提醒:注册的响应函数的函数名以及函数参数(数量和名称)必须和上面一致,不允许注册其他名称的函数

被群内其他成员 @ 的通知

QQBot 收到群消息时,会先根据消息内容判断是否有人 @ 自己。如果是,则在消息内容的开头加一个 '[@ME] ' 的标记,再传递给 onQQMessage 函数;否则,将消息内容中的所有 '@ME' 替换成 '@Me' 再传给 onQQMessage 。因此,在 onQQMessage 函数内,只需要判断 content 内是否含有 '@ME' 就知道自己是否被消息发送者 @ 了。例如:

1
2
3
4
@qqbotslot
def onQQMessage(bot, contact, member, content):
    if '@ME' in content:
        bot.SendTo(contact, member.name+',又在想我了吧')

定制定时任务

从 2.1.13 起, qqbot 中提供一个功能强大的函数装饰器 -- QQBotSched 来定制定时任务,示例代码:

1
2
3
4
5
6
7
8
9
10
11
from qqbot import QQBotSched as qqbotsched, RunBot
 
@qqbotsched(hour='11,17', minute='55')
def mytask(bot):
    gl = bot.List('group', '456班')
    if gl is not None:
        for group in gl:
            bot.SendTo(group, '同志们:开饭啦啦啦啦啦啦!!!')
 
if __name__ == '__main__':
    RunBot()

以上代码运行(或以插件形式加载)后,每到 11:55 和 17:55 ,都会自动向 群“456班” 发送消息:“同志们:开饭啦啦啦啦啦啦!!!” 。

QQBotSched 装饰器接受 year, month, day, week, day_of_week, hour, minute, second, start_date, end_date, timezone 共计 11 个关键词作为参数,每个参数表示任务的定制时间的分量所应匹配的值。例如: hour='11,17' 表示应在 11:xx 或 17:xx 执行任务, minute='55' 表示应在 xx:55 执行任务, minute='0-55/5' 表示应在 xx:x0 或 xx:x5 执行任务。

QQBotSched 是对 Python 的定时任务框架 apscheduler 的简单封装,其各项参数应采用 Unix 系统中的 crontab 格式输入。有关 crontab 以及 Python 的定时任务框架 apscheduler 的内容可参见以下参考资料:

  • %E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F/

注册回调函数和定制定时任务的注意事项

  • 回调函数的函数名、参数名、参数数量、参数顺序都不得更改,必须和以上 6 个函数完全一致。
  • 定时任务的函数名可以自己定义,但参数有且只有一个,参数名必须为 bot ,为一个 QQBot 对象。
  • 如果采用插件的形式编写,则回调函数前面的 @qqbotslot 是可以省略的,定时任务前面的 @qqbotsched 不能省略。
  • 所有回调函数和定时任务都将在主线程中被调用,因此不必担心数据的线程安全问题。
  • 所有回调函数和定时任务的运行时间应尽量短,不应在这些函数中进行阻塞式的 IO 操作,否则会阻塞整个程序的运行。

七、二维码管理器、QQBot 配置及命令行参数

二维码的显示模式

SmartQQ 登录时需要用手机 QQ 扫描二维码图片,在 QQBot 中,二维码图片可以通过以下三种模式显示:

  • GUI模式: 在 GUI 界面中自动弹出二维码图片
  • 邮箱模式: 将二维码图片发送到指定的邮箱
  • 服务器模式: 在一个 HTTP 服务器中显示二维码图片
  • 文本模式: 在 Term 中以文本形式展示二维码(需要自行安装 pillow 库)

GUI 模式是默认的模式,只适用于个人电脑。邮箱模式可以适用于个人电脑和远程服务器。服务器模式一般只在有公网ip的系统中使用。如果使用 QQ 邮箱来接收二维码,则当发送二维码图片后,手机 QQ 客户端会立即收到通知,在手机 QQ 客户端上打开邮件,再长按二维码就可以扫描了。文本模式方便在开发过程或者服务器部署时使用,为开发者提供快捷方式登陆 QQ ,注意:文本模式在某些 terminal 中(如 gnome-terminal , mate-terminal )的显示效果不太好。

注意:当开启了 邮箱模式/服务器模式/文本模式 时, GUI 模式是关闭的,登陆时不会自动弹出二维码图片。

每次登录时会创建一个二维码管理器 (QrcodeManager 对象) ,二维码管理器会根据配置文件及命令行参数来选择二维码图片的显示方式。

配置文件的使用方法

配置文件为 ~/.qqbot-tmp/v2.1.conf ,第一次运行 QQBot 后就会自动创建这个配置文件,其中内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
{
    # QQBot 的配置文件
    # 使用 qqbot -u somebody 启动程序时,依次加载:
    #     根配置 -> 默认配置 -> 用户 somebody 的配置 -> 命令行参数配置
    # 使用 qqbot 启动程序时,依次加载:
    #     根配置 -> 默认配置 -> 命令行参数配置
     
    # 用户 somebody 的配置
    "somebody" : {
         
        # QQBot-term 服务器端口号(HTTP-API也将使用这个端口)
        "termServerPort" : 8188,
         
        # 二维码 http 服务器 ip,请设置为公网 ip 或空字符串
        "httpServerIP" : "127.0.0.1",
         
        # 二维码 http 服务器端口号
        "httpServerPort" : 8189,
         
        # 自动登录的 QQ 号
        "qq" : "3497303033",
         
        # 接收二维码图片的邮箱账号
        "mailAccount" : "3497303033@qq.com",
         
        # 该邮箱的 IMAP/SMTP 服务授权码
        "mailAuthCode" : "feregfgftrasdsew",
 
        # 是否以文本模式显示二维码
        "cmdQrcode" : False,
     
        # 显示/关闭调试信息
        "debug" : False,
 
        # QQBot 掉线后自动重启
        "restartOnOffline" : False,
         
        # 完成一轮联系人列表刷新后的间歇时间
        "fetchInterval" : 120,
         
        # 完成全部联系人列表获取之后才启动 QQBot
        "startAfterFetch" : False,
         
        # 需要被特别监视的联系人列表
        # 'buddy'/'group'/'discuss' 表示需要特别监视:
        #     好友列表/群列表/讨论组列表 中的联系人变动事件
        # 'group-member-456班'/'discuss-member-xx小组' 表示需要特别监视:
        #     群”456班“成员列表/讨论组”xx小组“成员列表 中的联系人变动事件
        # 若此项中的列表的数量较少,则被特别监视的列表中的联系人变动事件滞后时间可大幅缩短
        "monitorTables" : ['buddy', 'group-member-456班'],
         
        # 插件目录
        "pluginPath" : ".",
         
        # 启动时需加载的插件
        "plugins" : ['sample1'],
     
    },
     
    # 可以在 默认配置 中配置所有用户都通用的设置
    "默认配置" : {
        "qq" : "",
        "pluginPath" : "",
        "plugins" : [],
    },
     
    # # 注意:根配置是固定的,用户无法修改(在本文件中修改根配置不会生效)
    # "根配置" : {
    #     "termServerPort" : 8188,
    #     "httpServerIP" : "",
    #     "httpServerPort" : 8189,
    #     "qq" : "",
    #     "mailAccount" : "",
    #     "mailAuthCode" : "",
    #     "cmdQrcode" : False,
    #     "debug" : False,
    #     "restartOnOffline" : False,
    #     "fetchInterval" : 120,
    #     "startAfterFetch" : False,
    #     "monitorTables" : [],
    #     "pluginPath" : "",
    #     "plugins" : [],
    # },
 
}

可以在配置文件中添加自己的用户配置(即在该文件的字典中新增一个 item ,此 item 的 key 就代表一个用户),例如,该文件中已有的 somebody 项目就代表名为 somebody 的用户,运行 QQBot 时,输入 qqbot -u somebodypython sample.py -u somebody ,则会加载 somebody 项目下的各项配置。

下面介绍配置文件中各项配置的功能,以下内容均假定已修改了 somebody 下的配置,且以 qqbot -u somebodypython sample.py -u somebody 的方式运行。

邮箱模式的配置( mailAccount 和 mailAuthCode )

如果需要使用邮箱模式显示二维码,可以将 mailAccount 和 mailAuthCode 项中分别设置为邮箱帐号和授权码,运行后,二维码管理器会将二维码图片发送至该邮箱。

注意:授权码不是邮箱的登录密码,而是邮箱服务商提供的开通 IMAP/SMTP 服务的授权码, QQ 邮箱可以在网页版的邮箱设置里面开通此项服务,并得到授权码。如果只定义了 mailAccount 而没定义 mailAuthCode ,则程序运行的开始时会要求手工输入此授权码。

由于网易的邮箱对 IMAP 协议的支持非常有限,无法在 QQBot 中使用。 QQ 的邮箱已通过测试,其他服务商的邮箱还未测试过,因此建议还是使用 QQ 邮箱。

服务器模式的配置( httpServerIP 和 httpServerPort )

如果需要使用服务器模式,可以配置 httpServerIP 和 httpServerPort 项,一般来说应该设置为公网 ip 。服务器模式开启后,可以通过 来访问二维码图片。

当邮箱模式和服务器模式同时开启时,发邮件时不会发送真正的图片,只会将图片地址发到邮箱中去,而且只发送一次,二维码过期时刷新一下邮件就可以了。如果只开启邮箱模式,则发邮件时会发送真正的图片,当二维码过期时,需要将邮件设置为已读(用手机 QQ 打开邮件后该邮件就是已读了),之后才会发送最新的二维码图片。

自动登录的 QQ 号码( qq )

配置文件中每个用户都有 qq 这一项,若此项已设置为某 QQ 号码,会先使用此 QQ 号上次登录保存的登录信息来自动登录。

掉线后自动重启( restartOnOffline )

如果配置文件中将 restartOnOffline 项设置为 True ,则当 QQBot 掉线或出错终止时,会自动重新启动 QQBot 。

联系人列表更新的间歇时间( fetchInterval )

QQBot 启动后,会在后台获取并更新联系人列表,当所有联系人列表获取完毕后,会 sleep 两分钟然后开始下一轮获取及更新。可以在配置文件中将 fetchInterval 项设置为其他值(单位:秒)来控制这个间歇时间。如果此值设置为负数,则只进行一次联系人列表获取(之后再也不获取了)。

联系人列表获取完成后再启动( startAfterFetch )

一般情况下,扫码登录完成就立即启动 QQBot,同时开始在后台获取并更新联系人列表。如果将配置文件中的 startAfterFetch 设置为 True ,则 QQBot 会等待所有联系人列表获取完成后才启动 ,注意,如果联系人较多,会耗费较长的时间。

QQBot-term 服务器端口号( termServerPort )

QQBot 启动后,会开启一个 QQBot-term 服务器监听用户通过 qq 命令行工具发过来的操作命令以及通过 HTTP API 接口发过来的操作命令,此服务器端口号默认为 8188 ,可以通过修改 termServerPort 的值来修改此端口号。

如果配置的 QQBot-term 服务器端口号不是默认的 8188 ,那么在运行 qq 命令时,需要在第一个参数中指定端口号,如:

1
2
$ qq 8100 send buddy jack hello
$ qq 8100 list group-member chatbot

同样,HTTP API 接口的端口号也需要改变,如: 。

如果需要在同一台机器上登录多个 QQ 号码,则需要对不同的 QQ 号码设置不同的 termServerPort 和 httpServerPort ,以免端口号冲突。

文本模式显示二维码(cmdQrcode)

若 cmdQrcode 项设置为 True ,则会在 term 中以文本模式显示二维码。注意:要使用文本模式,需要自行安装 pillow 库,可使用 pip 安装。

调试模式( debug )

若 debug 项设置为 True ,则运行过程中会打印调试信息。

需要被监视的联系人列表( monitorTables )

一般情况下联系人变动事件(onNewContact/onLostContact)滞后 5 ~ 10 分钟,可以将关心的联系人列表加入到配置文件的 monitorTables 中去,若 monitorTables 中的列表数量较少,则被监视的列表中的联系人变动事件延后时间将大幅缩短。例如,如果关心 群”456班“ 的联系人变动,可以设置 monitorTables = ['group-member-456班'] ,则该群的成员变动事件仅滞后 1~3 秒。

插件的配置( pluginPath 和 plugins )

一般情况下,插件需要存放在系统的 import 目录下,可以在 pluginPath 选项中配置插件的存放目录,放在该选项指定的目录下也可以被 QQBot 动态加载。另外,在 plugins 选项中可以指定 QQBot 启动时需要加载的插件(注意:这些插件需要保存在系统的 import 目录下或 pluginPath 所指定的目录下)。

命令行参数及配置的优先级

配置文件中的所有选项都有对应的命令行参数,在命令行参数中输入的选项优先级比配置文件高。输入 qqbot -hpython sample.py -h 可查看所有命令行参数格式。

程序一共有四个级别的配置,其优先级如下:

1
2
3
4
5
使用 qqbot -u somebody 启动程序时,依次加载:
    根配置 -> 默认配置 -> 用户 somebody 的配置 -> 命令行参数配置
 
使用 qqbot 启动程序时,依次加载:
    根配置 -> 默认配置 -> 命令行参数配置

其中:根配置 是固定的,用户无法修改; 默认配置 和 用户配置 可由用户在 v2.1.conf 文件中进行修改;最后,还可以在 命令行参数 中输入配置。

八、 smartqq 协议支持及限制

本项目已实现绝大部分 smartqq 协议支持的功能,如下:

  • 消息收/发
  • 联系人(包括 好友/群/讨论组/群成员/讨论组成员)资料获取和查询(包括 QQ号/昵称/名称/备注名/群成员名片)
  • 联系人资料动态更新,新增和丢失 好友/群/讨论组/群成员/讨论组成员 事件的通知
  • 被群内其他成员 @ 的通知
  • 群管理功能: 设置管理员 、 设置群名片 、 群成员禁言 以及 踢除群成员
  • 发送、接收表情(详见 facemap.py)

其他功能

  • 调用系统默认图片浏览器显示登录二维码、将登录二维码发送至邮箱、开启一个 http 服务器用来显示登录二维码、在命令行窗口使用文本模式显示二维码
  • 用 qq 命令行工具发消息和查询联系人
  • 掉线后自动重启功能(有时需要手工扫码)
  • 定时执行任务(通过 QQBotSched 实现)

因 smartqq 协议的限制,以下问题无解决办法

  • 无法长时间保持在线状态,每次登录成功后的 cookie 会每在 1 ~ 2 天后失效,将被腾讯服务器强制下线,此时 必须 手工扫码重新登录。可以将二维码显示模式设置为邮箱模式并打开自动重启模式,在被下线时自动重启并将二维码发送到邮箱,实现远程扫码
  • 无法发送图片、文件、音频、 xml 卡片消息
  • 无法获取到自己通过其他客户端(手机 QQ 、PC-QQ)发送的消息
  • 无法在群内 @ 其他成员,即便用本程序在群里发送了 “@jack xxx” 这样的消息, jack 也只能收到这个纯文本,收不到“有人@我”的提醒。
  • 无法向 群/讨论组 内的其他非好友成员发消息,也无法收到非好友成员发过来的临时会话消息
  • 在非常少的情况下,发消息时会重复发送多次,也可能对方已收到消息但返回发送失败的结果

九、参考资料

QQBot 参考了以下开源项目:

  • ScienJus/qqbot (ruby)
  • floatinghotpot/qqbot (node.js)
  • sjdy521/Mojo-Webqq (perl)

在此感谢以上三位作者的无私分享,特别是感谢 ScienJus 对 SmartQQ 协议所做出的深入细致的分析。

阅读(21685) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~