QQ机器人
一、介紹
qqbot 是一個用 python 實現的、基于騰訊 SmartQQ 協議的 QQ 機器人,可運行在 Linux 、 Windows 和 Mac OSX 平臺下。
本項目 github 地址:https://github.com/pandolia/qqbot
你可以通過擴展 qqbot 來實現:
監控、收集 QQ 消息
自動消息推送
聊天機器人
通過 QQ 遠程控制你的設備
二、安裝方法
在 Python 2.7/3.4+ 下使用,用 pip 安裝:
pip install qqbot
或者下載源碼解壓后 cd 到該目錄并運行: “pip install .”
三、使用方法
1. 啟動 QQBot
在命令行輸入:qqbot,即可啟動一個 QQBot 。
啟動過程中會自動彈出二維碼圖片,需要用手機 QQ 客戶端掃碼并授權登錄。啟動成功后,會將本次登錄信息保存到本地文件中,下次啟動時,可以輸入:qqbot -q qq號碼,先嘗試從本地文件中恢復登錄信息(不需要手動掃碼),只有恢復不成功或登錄信息已過期時才會需要手動掃碼登錄。一般來說,保存的登錄信息將在 2 天之后過期。
注意: Linux 下,需要系統中有 gvfs-open 或者 shotwell 命令才能自動彈出二維碼圖片(一般安裝有 GNOME 虛擬文件系統 gvfs 的系統中都會含這兩個命令之一)。 Windows10 下,需要系統中已設置了 png 圖片文件的默認打開程序才能自動彈出二維碼圖片。
若系統無法自動彈出二維碼圖片,可以手動打開圖片文件進行掃碼,也可以將二維碼顯示模式設置為 郵箱模式 、 服務器模式 或 文本模式 進行掃碼,詳見本文檔的第七節。
2. 操作 QQBot
QQBot 啟動后,在另一個控制臺窗口使用 qq 命令操作 QQBot ,目前提供以下命令:
1) 幫助、停機和重啟命令
qq help|stop|restart|fresh-restart
2) 聯系人查詢、搜索命令
qq list buddy|group|discuss [$cinfo|$clike]
( $cinfo --> $qq|$name|$key=$val )
( $clike --> :like:$qq|:like:$name|$key:like:$name )
qq list group-member|discuss-member $oinfo|$olike [$cinfo|$clike]
( $oinfo --> $oqq|$oname|$okey=$oval )
( $cinfo --> $qq|$name|$key=$val )
( $olike --> :like:$oqq|:like:$oname|$okey:like:$oname )
( $clike --> :like:$qq|:like:$name|$key:like:$name )
3) 聯系人更新命令
qq update buddy|group|discuss
qq update group-member|discuss-member $ginfo
4) 消息發送命令
qq send buddy|group|discuss $rinfo $message
5) 群管理命令: 設置/取消管理員 、 設置/刪除群名片 、 群成員禁言 以及 踢除群成員
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,...
6) 加載/卸載/顯示插件
qq plug/unplug myplugin
qq plugins
list 命令提供強大的聯系人查詢和搜索功能,用法示例如下:
# 列出所有好友
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 號進行查詢,否則,按名稱進行查詢。
如果存在重名現象,會列出所有重名的聯系人。如:
qq list group 機器人測試
將列出所有名為 “機器人測試” 的群。
如果在 list 命令的第三、四個參數中加入 “:like:” ,則會按部分匹配的模式進行搜索,用法示例如下:
# 列出名稱中含有 “李” 的好友
qq list buddy :like:李
# 列出 QQ 中含有 “234” 的群
qq list group :like:234
# 列出備注名中含有 jack 的好友
qq list buddy mark:like:jack
# 列出 群“456班” 的中名稱中含有 “李” 的成員
qq list group-member 456班 :like:李
# 列出 群“456班” 中名片中含有 “mike” 的成員
qq list group-member 456班 card:like:mike
# 列出的 討論組“xx小組” 中名為 jack 的好友
qq list discuss-member :like:小組 jack
從 v2.2.5 版開始, list 命令采用表格的形式輸出聯系人列表,其輸出樣式示例如下:
為保證表格在終端中的顯示效果,建議將終端的輸出字體設置為 consolas 、且每行可打印的最大字符數大于 120 。另外需要注意:為保證表格的顯示效果,當聯系人的名稱、名片等屬性的長度太長或含有特殊字符時,將對這些屬性進行截斷或過濾后再輸出至終端。
update 命令更新指定的聯系人列表,其參數含義和 list 命令相同,如:
# 更新好友列表
qq update buddy
# 更新群列表
qq update group
# 更新 群“456班” 的成員列表
qq update group-member 456班
send 命令中第三個參數和 list 命令中的第三個參數格式一致。要注意,如果有重名現象,會給所有重名的聯系人發信息。 另外要注意,第二個參數只能是 buddy/group/discuss ,不能是 group-member/discuss-member 。示例:
# 給 好友“jack” 發消息 “你好”
qq send buddy jack 你好
# 給 群“198班” 發消息 “大家好”
qq send group 198班 大家好
# 給 QQ 為 12345 的好友發消息
qq send buddy 12345 xxx
# 給討論組發消息
qq send discuss MyDiscuss hello
可以在消息內容中嵌入“/可愛”等表情關鍵詞來向對方發送表情,詳見facemap.py。還可以在消息內容中使用
, 這兩個轉義字符(如: send buddy jack 第一行
第二行)。
群管理命令中的 $ginfo 和 $minfo 和 list 命令中的第三、四個參數格式一致。例如:
# 禁止 群“456班” 中的 jack,mike,jim 發言( 2 分鐘)
qq group-shut 456班 jack,mike,jm 120
以上所有命令都提供對應的 HTTP API 接口,供 web 前端開發者調用,接口的 url 地址為http://127.0.0.1:8188/{command},只需要將 qq 后面的命令各參數用 "/" 分隔開替換 url 中的 command 就可以了,如:http://127.0.0.1:8188/send/buddy/jack/hello,其他示例詳見urltestbot.md。注意:如果命令中含有中文或特殊字符,需要先進行 url 編碼( utf8 ),例如,調用http://127.0.0.1:8188/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 機器人非常簡單,只需要定義一個自己的消息響應函數并按插件加載。示例代碼:
# -*- coding: utf-8 -*-
def onQQMessage(bot, contact, member, content):
if content == '-hello':
bot.SendTo(contact, '你好,我是QQ機器人')
elif content == '-stop':
bot.SendTo(contact, 'QQ機器人已關閉')
bot.Stop()
注意,上面注冊的響應函數的函數名必須為 “onQQMessage” ,函數參數也必須和上面的一致。
將以上代碼另存為 sample.py (注意保存為 utf8 編碼的文件)。放到 ~/.qqbot-tmp/plugins/ 目錄下(~代表用戶主目錄, win7 下為 C:Usersxxx ),或系統中可以 import 到的目錄下(如 python 的安裝目錄下的 Lib/site-packages 目錄)。
之后,保持前面的 qqbot 進程運行,在另一個控制臺輸入 qq plug sample ,則可將此文件中的 onQQMessage 函數注冊到 QQBot 的相應事件上去。此時,用另外一個 QQ 向本 QQ 發送消息“-hello”,則會自動回復“你好,我是 QQ 機器人”,發送消息“-stop”則會關閉 QQ 機器人。
在控制臺輸入 qq unplug sample 可以卸載此插件及相應的回調函數。可以同時加載多個插件,此時各插件中的相應函數會依次被調用(但調用順序和加載次序無關)。
QQBot 開始運行后,每收到一條 QQ 消息,會將消息來源、消息內容以及一個 QQBot 對象傳遞給已注冊的消息響應函數。其中:
bot : QQBot 對象,提供 List/SendTo/Stop/Restart 等接口,詳見本文檔第五節
contact : QContact 對象,消息的發送者,具有 ctype/qq/uin/nick/mark/card/name 等屬性
member : QContact 對象,僅當本消息為 群消息或討論組消息 時有效,代表實際發消息的成員
content : str 對象,消息內容
contact 代表消息發送者,其 ctype 屬性可以為 'buddy'/'group'/'discuss' ,代表 好友/群/討論組 對象,表示本消息是 好友消息/群消息/討論組消息 。
member 僅當本消息為 群消息或討論組消息 時有效,代表實際發消息的成員,它的 ctype 屬性可以為 'group-member'/'discuss-member' ,代表 群成員/討論組成員 對象。當本消息為 好友消息 時, member 等于 None 。
contact 和 member 都是 QContact 對象,不同類型的 QContact 對象所具有的屬性含義見:qcontact-attr。注意所有 QContact 對象都是只讀對象,只能讀取它的屬性,不能設置它的屬性,也不能向它添加額外的屬性。
可以調用 QQBot 對象的 SendTo 接口向 QContact 對象發送消息,但要注意:只可以向 好友/群/討論組 發消息,不可以向 群成員/討論組成員 發送消息。也就是說,只可以調用 bot.SendTo(contact, 'xxx') , 不可以調用 bot.SendTo(member, 'xxx') 。
五、 QQBot 對象的公開接口和屬性
QQBot 對象提供 List/Update/SendTo/GroupSetAdmin/GroupSetCard/GroupShut/GroupKick/Plug/Unplug/Login/Stop/Restart/FreshRestart 共計 11 個公開接口,這些接口的第一個字母都是大寫的。另外,提供一個公開屬性 conf 保存全局的配置信息。
一般情況下,請勿 調用/存取 此對象的其他 方法/屬性 。特別的,請勿在子線程中調用這些接口。 以下介紹前 7 個接口和 conf 屬性。
如果需要在 IDE 或 python-shell 中運行或測試以上接口,需要先關閉 qqbot 進程,并在 IDE 或 python-shell 中運行以下代碼進行登錄:
>>> from qqbot import _bot as bot
>>> bot.Login(['-q', '1234'])
(1) bot.List(tinfo, [cinfo]) --> [contact0, contact1, ..., ]/[]/None
對應本文檔第三節的 list 命令。返回聯系人對象( QContact 對象)列表或者 None 。第一個參數 tinfo 是聯系人列表的代號,第二個參數是可選的(和 list 命令的第三個參數格式一致)。
參數 tinfo 用來代表某個聯系人列表,該參數在聯系人的查詢中非常重要,請務必理解以下兩種情況:
tinfo 的含義(情況1):tinfo 可以為 'buddy'/'group'/'discuss' ,分別代表 好友列表/群列表/討論組列表 。示例:
# 返回 好友列表:
>>> bot.List('buddy')
# 返回名為 'jack' 的好友的列表:
>>> bot.List('buddy', 'jack')
# 返回 群列表:
>>> bot.List('group')
# 返回名為 “機器人測試” 的群的列表:
>>> bot.List('group', '機器人測試')
tinfo 的含義(情況2):tinfo 也可以是一個 ctype 等于 'group'/'discuss' 的 QContact 對象,代表該 群/討論組 的成員列表。如以下第二句和第三句分別返回 群“456班” 的成員列表和該群中名片為 “jack” 的成員列表:
>>> g = bot.List('group', "456班")[0] # g 是一個 Group 對象(群“456班”)
>>> bot.List(g) # 返回 群“456班” 的成員列表
>>> bot.List(g, 'card=jack') # 返回 群“456班” 中名片為 “jack” 的成員列表
注意上面第三句不允許是 bot.List(g, card='jack') 的格式。
List 接口的內部執行順序:首先在 QQBot 的聯系人數據庫內查找 tinfo 所代表的聯系人列表;若數據庫內已有此列表,則在此列表內進行搜索,并返回一個包含 “此列表中所有和 cinfo 匹配的聯系人” 的列表;若數據庫內沒有此列表,則向 QQ 服務器請求數據獲取聯系人列表,獲取成功后將聯系人列表保存到數據庫內,然后再進行搜索并返回一個包含 “此列表中所有和 cinfo 匹配的聯系人” 的列表;如果在向 QQ 服務器請求數據的過程中出錯了,則打印相關的失敗信息,并返回 None 。
List 接口返回值的含義:返回一個非空列表表示 tinfo 所指定的聯系人列表內所有和 cinfo 匹配的聯系人;返回一個空列表表示該聯系人列表內沒有和 cinfo 匹配的聯系人;返回 None 表示向 QQ 服務器請求聯系人列表和資料失敗,不知道是否有相匹配的聯系人。
調用 List 接口后,務必先根據以上三種情況對返回值進行判斷,然后再執行后續代碼。
(2) bot.Update(tinfo) --> True/False
Update 接口的參數 tinfo 和 List 接口中的參數含義相同,調用此接口會立即向 QQ 服務器請求相應的聯系人列表并更新聯系人數據庫,并一直阻塞至更新成功。更新最慢的是好友列表,若好友較多可能會阻塞 5 ~ 10 秒。成員列表更新的較快,即便是 2000 人的大群,更新時間僅 1 ~ 2 秒。
若更新成功,返回 True ,否則,返回 False 。
示例:
# 更新 好友列表 :
>>> bot.Update('buddy')
# 更新 群列表 :
>>> bot.Update('group')
# 更新 某個群的成員列表 :
>>> gl = bot.List('group', "456班")
>>> if gl:
>>> g = gl[0]
>>> bot.Update(g)
(3) bot.SendTo(contact, content, resendOn1202=True) --> '向 xx 發消息成功'/'錯誤:...'
向聯系人發送消息。第一個參數為 QContact 對象,第二個參數為消息內容。再次提醒: 只可以向 好友/群/討論組 發消息,不允許向 群成員/討論組成員 發消息。
可以在消息內容中嵌入“/微笑”等表情關鍵詞來向對方發送表情,詳見facemap.py。
若發送成功,返回字符串('向 xx 發消息成功')。否則,返回含錯誤原因的字符串('錯誤:...')。
發消息時可能會重復發消息,這是因為 QQ 服務器返回代碼 1202 的原因。v2.1.17版已針對此問題在 bot.SendTo 接口中增加了一個參數: resendOn1202 ,若此參數為 True (默認值),則發消息時如果 QQ 服務器返回代碼 1202 (表明發消息可能失敗),還會繼續發送 3 次,直至返回代碼 0 , 若此參數為 False ,則不會嘗試重發。
設為 True 在絕大部分情況下能保證消息一定能發出去,但缺點是有時一條消息會重復發送。設為 False 則相反,消息不會重復發送,但有時消息發送不出去。
總之因為這個 1202 代碼的不確定性,沒有完美的解決辦法。請根據各自的實際情況選擇 resendOn1202 的值。
第一個參數 contact 必須是通過 bot.List 返回的 QContact 對象、或回調函數 onQQMessage 傳遞進來的第一個參數。示例:
# 向 QQ 為 12345 的好友發消息
>>> bl = bot.List('buddy', '12345')
>>> if bl:
>>> b = bl[0]
>>> bot.SendTo(b, 'hello')
(4) 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 中各成員的操作信息。示例代碼:
# 禁止 群“456班” 中名稱為 jack 的成員發言(120秒)
gl = bot.List('group', '456班')
if gl:
group = gl[0]
membs = bot.List(group, 'jack')
if membs:
bot.GroupShut(group, membs, 120)
注意: 1) 第二個參數 membs 是一個 list 對象(如: [memb0,memb1,...] ),而不是一個 QContact 對象; 2) 若 membs 中的某個成員是管理員,則除 SetCard 外的其他接口可能對其無效,盡管此時返回成功信息。 3) 使用這四個接口時,請自行保證登錄的用戶是該群的管理員,且 membs 中的各成員均屬于該群。
(5) bot.conf
bot.conf 中保存全局的配置信息,各項配置詳見本文檔第七節。如 bot.conf.termServerPort 保存 QQBot 命令行服務器的端口號, bot.conf.qq 保存本次登錄的 QQ 號碼。
注意: bot.conf 中保存的配置信息是只讀的,請勿修改這些配置信息。
六、 注冊回調函數、被他人 @ 的通知、判斷是否是自己發的消息、定制定時任務
注冊回調函數
除了上面提到的 onQQMessage 響應函數,還可以注冊 onInit/onQrcode/onStartupComplete/onInterval/onUpdate/onPlug/onUnplug/onExit 共計九種事件的回調函數,所有事件的回調函數參數格式、含義及示例詳見sampleslots.py。
程序的運行流程以及各回調函數的調用時機如下:
再次提醒:注冊的回調函數的函數名以及函數參數(數量和名稱)都不得更改。
被群內其他成員 @ 的通知
QQBot 收到群消息時,會先根據消息內容判斷是否有人 @ 自己。如果是,則在消息內容的開頭加一個 '[@ME] ' 的標記,再傳遞給 onQQMessage 函數;否則,將消息內容中的所有 '@ME' 替換成 '@Me' 再傳給 onQQMessage 。因此,在 onQQMessage 函數內,只需要判斷 content 內是否含有 '@ME' 就知道自己是否被消息發送者 @ 了。例如:
def onQQMessage(bot, contact, member, content):
if '@ME' in content:
bot.SendTo(contact, member.name+',艾特我干嘛呢?')
請注意,若群內有另一個成員的名字和自己的名字的開頭部分相同(如:自己的名字是 ab ,另一個成員的名字是 abc ),那么當有人 @abc 時,也會誤報成 @ME ,在這種情況下,需要修改自己的群名片,以免誤報。
判斷是否是自己發的消息
當本 QQ 在群內或討論組內發言時, QQBot 也會收到一條同樣的消息,此時 onQQMessage 中的 contact 參數就是該 群/討論組 對象, member 參數就是自己在該 群/討論組 中的成員對象,此時 member.uin 就是本次登錄的 QQ 號碼,因此,在 onQQMessage 中,只要判斷 member 的 uin屬性 是否是本次登錄的 QQ 號碼就可以知道是否是自己的發的消息了,例如:
from qqbot.utf8logger import INFO
def onQQMessage(bot, contact, member, content):
if getattr(member, 'uin', None) == bot.conf.qq: # 注意:不要使用 member.uin
INFO('你在 %s 內發言', contact)
定制定時任務
從 2.1.13 起, qqbot 提供一個功能強大的函數裝飾器 -- qqbotsched 來定制定時任務,示例代碼:
from qqbot import qqbotsched
@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, '同志們:開飯啦啦啦啦啦啦!!!')
以上代碼以插件形式加載后,每到 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:00, xx:05, xx:10, ..., xx:55 執行任務, day_of_week='mon-fri' (或 '0-4' ) 表示應在 星期一 ~ 星期五 執行任務。
qqbotsched 是對 Python 的定時任務框架 apscheduler 的簡單封裝,其各項參數應采用 Unix 系統中的 crontab 格式輸入。有關 crontab 以及 Python 的定時任務框架 apscheduler 的內容可參見以下參考資料:
https://code.tutsplus.com/tutorials/scheduling-tasks-with-cron-jobs--net-8800/
http://apscheduler.readthedocs.io/en/latest/userguide.html
https://lz5z.com/Python定時任務的實現方式/
http://debugo.com/apscheduler/
crontab 各項參數格式說明詳見:
http://apscheduler.readthedocs.io/en/latest/modules/triggers/cron.html
注冊回調函數和定制定時任務的注意事項
注冊回調函數和定制定時任務是對 QQBot 進行擴展的唯一方式,在編寫這些函數時,請注意以下事項:
回調函數的函數名、參數名、參數數量、參數順序都不得更改
定時任務的函數名可以自己定義,但參數有且只有一個,參數名必須為 bot ,為一個 QQBot 對象。
所有回調函數和定時任務都將在主線程中被依次調用,因此不必擔心全局變量的線程安全問題。
回調函數和定時任務的運行時間應盡量短,盡量不要再這些函數中進行阻塞式的操作,否則會阻塞整個程序的運行。一般來說,每個函數的運行時間在 5 秒以內是可以接受的。
絕對不要在回調函數、定時任務或 qqbot 主線程的內部調用 os.system 執行本 QQ 號對應的 qq 命令( 如 os.system('qq send buddy jack hello') )或請求本 QQ 號對應的 HTTP-API 接口,否則整個程序會形成死鎖(因為 os.system 要等 qq 命令執行完成后才返回、而 qq 命令要等 os.system 返回后才會被執行)。請直接使用 bot 的 SendTo/List/GroupXXX 等接口。
七、二維碼管理器、QQBot 配置、命令行參數以及工作目錄
二維碼的顯示模式
WebQQ 登錄時需要用手機 QQ 掃描二維碼圖片,在 QQBot 中,二維碼圖片可以通過以下四種模式顯示:
GUI模式: 在 GUI 界面中自動彈出二維碼圖片
郵箱模式: 將二維碼圖片發送到指定的郵箱
服務器模式: 在一個 HTTP 服務器中顯示二維碼圖片
文本模式: 在 Term 中以文本形式展示二維碼(需要自行安裝 pillow 和 wcwidth 庫)
GUI 模式是默認的模式,只適用于個人電腦。郵箱模式可以適用于個人電腦和遠程服務器。服務器模式一般只在有公網 ip 的系統中使用。如果使用 QQ 郵箱來接收二維碼,則發送二維碼圖片之后,手機 QQ 客戶端會立即收到通知,在手機 QQ 客戶端上打開郵件,再長按二維碼就可以掃描了。文本模式方便在開發過程或者服務器部署時使用,為開發者提供快捷方式登陸 QQ 。
注意:當開啟了 郵箱模式/服務器模式/文本模式 時, GUI 模式是關閉的,登陸時不會自動彈出二維碼圖片。
每次登錄時會創建一個二維碼管理器 ( QrcodeManager 對象) ,二維碼管理器會根據配置文件及命令行參數來選擇二維碼圖片的顯示方式。
配置文件的使用方法
配置文件為~/.qqbot-tmp/v2.x.conf,第一次運行 QQBot 后就會自動創建這個配置文件,其中內容如下:
{
# QQBot 的配置文件
# 使用 qqbot -u somebody 啟動程序時,依次加載:
# 根配置 -> 默認配置 -> 用戶 somebody 的配置 -> 命令行參數配置
# 使用 qqbot 啟動程序時,依次加載:
# 根配置 -> 默認配置 -> 命令行參數配置
# 用戶 somebody 的配置
"somebody" : {
# QQBot-term (HTTP-API) 服務器端口號(該服務器監聽 IP 為 127.0.0.1 )
# 設置為 0 則不會開啟本服務器(此時 qq 命令和 HTTP-API 接口都無法使用)。
"termServerPort" : 8188,
# 二維碼 http 服務器 ip,請設置為公網 ip 或空字符串
"httpServerIP" : "",
# 二維碼 http 服務器端口號
"httpServerPort" : 8189,
# 自動登錄的 QQ 號
"qq" : "3497303033",
# 接收二維碼圖片的郵箱賬號
"mailAccount" : "3497303033@qq.com",
# 該郵箱的 IMAP/SMTP 服務授權碼
"mailAuthCode" : "feregfgftrasdsew",
# 是否以文本模式顯示二維碼
"cmdQrcode" : False,
# 顯示/關閉調試信息
"debug" : False,
# QQBot 掉線后自動重啟
"restartOnOffline" : False,
# 在后臺運行 qqbot ( daemon 模式)
"daemon": False,
# 完成全部聯系人列表獲取之后才啟動 QQBot
"startAfterFetch" : False,
# 插件目錄
"pluginPath" : ".",
# 啟動時需加載的插件
"plugins" : [],
# 插件的配置(由用戶自定義)
"pluginsConf" : {},
},
# 可以在 默認配置 中配置所有用戶都通用的設置
"默認配置" : {
"qq" : "",
"pluginPath" : "",
"plugins" : [
'qqbot.plugins.sampleslots',
'qqbot.plugins.schedrestart',
],
"pluginsConf" : {
'qqbot.plugins.schedrestart': '8:00',
}
},
# # 注意:根配置是固定的,用戶無法修改(在本文件中修改根配置不會生效)
# "根配置" : {
# "termServerPort" : 8188,
# "httpServerIP" : "",
# "httpServerPort" : 8189,
# "qq" : "",
# "mailAccount" : "",
# "mailAuthCode" : "",
# "cmdQrcode" : False,
# "debug" : False,
# "restartOnOffline" : False,
# "daemon" : False,
# "startAfterFetch" : False,
# "pluginPath" : "",
# "plugins" : [],
# "pluginsConf" : {}
# },
}
可以在配置文件中添加自己的用戶配置(即在該文件的字典中新增一個 item ,此 item 的 key 就代表一個用戶),例如,該文件中已有的 somebody 項目就代表名為 somebody 的用戶,運行 QQBot 時,輸入qqbot -u somebody,則會加載 somebody 項目下的各項配置。
下面介紹配置文件中各項配置的功能,以下內容均假定已修改了 somebody 下的配置,且以qqbot -u somebody的方式運行。
郵箱模式的配置( mailAccount 和 mailAuthCode )
如果需要使用郵箱模式顯示二維碼,可以將 mailAccount 和 mailAuthCode 項中分別設置為郵箱帳號和授權碼,運行后,二維碼管理器會將二維碼圖片發送至該郵箱。
注意:授權碼不是郵箱的登錄密碼,而是郵箱服務商提供的開通IMAP/SMTP服務的授權碼(提醒:不是POP3/SMTP服務), QQ/網易 郵箱可以在網頁版的郵箱設置里面開通此項服務,并得到授權碼。如果只定義了 mailAccount 而沒定義 mailAuthCode ,則程序運行的開始時會要求手工輸入此授權碼。
郵箱模式已在 QQ 、 網易 和 Google 郵箱中測試過。
服務器模式的配置( httpServerIP 和 httpServerPort )
如果需要使用服務器模式,可以配置 httpServerIP 和 httpServerPort 項,一般來說應該設置為公網 ip 。服務器模式開啟后,可以通過http://{httpServerIP}:{httpServerPort}/{any}來訪問二維碼圖片。其中 {any} 可以是任何非空的數字或字母串。
當郵箱模式和服務器模式同時開啟時,發郵件時不會發送真正的圖片,只會將圖片地址發到郵箱中去,而且只發送一次,二維碼過期時刷新一下郵件就可以了。如果只開啟郵箱模式,則發郵件時會發送真正的圖片,當二維碼過期時,需要將郵件設置為已讀(用手機 QQ 點開郵件后該郵件就是已讀了),之后才會發送最新的二維碼圖片。
文本模式顯示二維碼(cmdQrcode)
若 cmdQrcode 項設置為 True ,則會在 term 中以文本模式顯示二維碼。注意:要使用文本模式,需要自行安裝 pillow 和 wcwidth 庫,可使用 pip 安裝。
自動登錄的 QQ 號碼( qq )
配置文件中每個用戶都有 qq 這一項,若此項已設置為某 QQ 號碼,則 QQBot 在啟動時會先使用此 QQ 號上次登錄保存的登錄信息來自動登錄。
掉線后自動重啟( restartOnOffline )
如果配置文件中將 restartOnOffline 項設置為 True ,則當 QQBot 掉線或出錯終止時,會自動重新啟動 QQBot 。
在后臺運行 qqbot ( daemon )
此選項僅在 UNIX 類系統中有效,將配置中的 daemon 選項設置為 True 則會以 daemon 模式運行程序。此時,標準輸出和標準錯誤會重定向到 daemon-$qq.log 文件(其中 $qq 是配置中 qq 選項的值)。
聯系人列表獲取完成后再啟動( startAfterFetch )
一般情況下,掃碼登錄完成就立即啟動 QQBot,只有在需要的時候才會去獲取聯系人列表并更新聯系人數據庫。如果將配置文件中的 startAfterFetch 設置為 True ,則QQBot 會等待所有聯系人列表獲取完成后才啟動,注意,如果聯系人較多,會耗費較長的時間。
QQBot-term 服務器端口號( termServerPort )
QQBot 啟動后,會開啟一個 QQBot-term 服務器監聽用戶通過 qq 命令行工具發過來的操作命令以及通過 HTTP API 接口發過來的操作命令,此服務器的監聽 IP 永遠為 127.0.0.1 ,監聽端口號默認為 8188 ,可以通過修改 termServerPort 的值來修改此端口號。
如果配置的 QQBot-term 服務器端口號不是默認的 8188 ,那么在運行 qq 命令時,需要在第一個參數中指定端口號,如:
$ qq 8100 send buddy jack hello
$ qq 8100 list group-member chatbot
同樣,HTTP API 接口的端口號也需要改變,如:http://127.0.0.1:8100/send/buddy/jack/hello。
如果不需要使用 qq 命令和 HTTP-API 接口,可以將此端口號設置為 0 ,此時 QQBot-term 服務器不會開啟。
如果需要在同一臺機器上登錄多個 QQ 號碼,可以直接在不同的終端中開啟多個 qqbot 進程進行登錄,但是,每個 qqbot 進程必須設置專有的 termServerPort 和 httpServerPort (或者全部設置為 0 或 空值 ),否則會造成端口號沖突。
調試模式( debug )
若 debug 項設置為 True ,則運行過程中會打印調試信息。
插件的配置( pluginPath 和 plugins )
一般情況下,插件需要存放在系統的 import 目錄下或 ~/.qqbot-tmp/plugins 目錄下,可以在 pluginPath 選項中配置其他的存放目錄。另外,在 plugins 選項中可以指定 QQBot 啟動時需要加載的插件。
命令行參數及配置的優先級
配置文件中的所有選項都有對應的命令行參數,在命令行參數中輸入的選項優先級比配置文件高。輸入qqbot -h可查看所有命令行參數格式。
程序一共有四個級別的配置,其優先級如下:
使用 qqbot -u somebody 啟動程序時,依次加載:
根配置 -> 默認配置 -> 用戶 somebody 的配置 -> 命令行參數配置
使用 qqbot 啟動程序時,依次加載:
根配置 -> 默認配置 -> 命令行參數配置
其中:根配置 是固定的,用戶無法修改; 默認配置 和 用戶配置 可由用戶在 v2.x.conf 文件中進行修改;最后,還可以在 命令行參數 中輸入配置。
工作目錄
qqbot 運行時,會在 工作目錄 下 搜索/創建 以下 文件/目錄 :
配置文件: v2.x.conf
插件目錄: plugins/
登錄文件: v2.x-pyx-xxxx.pickle
聯系人數據庫文件: 2017-05-06-20-03-12-xxxx-contact.db
臨時二維碼圖片: xxxx.png
保存QQ的文件: qq(pid9816)
以 daemon 模式運行時的 log 文件: daemon-xxx.log
默認的工作目錄為 ~/.qqbot-tmp/ ,可以在啟動 qqbot 時通過命令行參數 -b|--bench 指定其他工作目錄,例如: qqbot -b bench 。
八、 插件
插件的存放位置
插件實際上是一個 python 模塊,因此可以是一個 python 文件,也可以是一個 python package。 qqbot 會根據插件名在以下目錄中搜索插件:
配置中的 pluginPath 選項(命令行參數 -pp|--pluginPath )指定的目錄
工作目錄下的 plugins 目錄
python 的導入目錄
插件的加載/卸載
hot-plug 方式
可以在 qqbot 的運行過程中動態的加載/卸載插件,有以下三種方法:
利用 qq 命令行工具: qq plug pluginname 或 qq unplug pluginname
利用 http-api 接口:http://127.0.0.1:8188/plug/pluginname或http://127.0.0.1:8188/unplug/pluginname
利用 bot 對象的接口: bot.Plug('pluginname') 或 bot.Unplug('pluginname')
前面兩種方法是供 qqbot 進程的外部進程調用的,第三種方法是在 qqbot 進程內部使用的。請勿在 qqbot 進程的內部使用前面兩種方法。
注意:采用 hot-plug 方式加載的插件在 qqbot 重啟后會丟失。
auto-plug-at-start 方式
也可以在 qqbot 的啟動時自動加載插件,在配置中的 plugins 選項(命令行參數 -pl|--plugins )中指定需要加載的插件名就可以了。這些插件將在啟動時、登錄之前被加載。
另外,如果系統中(或插件目錄中)存在名為qqbotdefault的 package ,那么該 package 下面的所有子模塊都會被當成插件在啟動時自動加載(注意:qqbotdefault 本身不會作為插件加載)。
插件內的 onPlug 和 onUnplug 回調函數
插件被加載時,會執行 reload(pluginName) ,因此插件內的所有代碼都會被執行一次
當采用 hot-plug 的方式加載時,插件內的 onPlug 函數會緊接在 reload 成功后被執行
當采用 auto-plug-at-start 方式加載時,插件在啟動時、登錄之前被加載,但插件內的 onPlug 函數會延遲到登錄成功后才被執行
插件被卸載時,插件內的 onUnplug 被執行
插件的編寫
編寫插件主要就是編寫回調函數或定時任務函數,詳見第四~六節。
插件列表
| 名稱 | github作者 | 功能說明 | 是否默認加載 |
|---|---|---|---|
| qqbot.plugins.sampleslots | pandolia | 回調函數示例 | 是 |
| qqbot.plugins.schedrestart | pandolia | 定時重啟 | 是 |
| qqbot.plugins.miniirc | pandolia | IRC服務器 | 否 |
| adblock | feisuweb | 群廣告攔截 | 否 |
| chatlog | feisuweb | 聊天內容記錄 | 否 |
如果您有好用的插件分享,歡迎發郵件給我。
九、 命令行模式下使用 IRC 聊天
linux 系統下,由于無法使用 QQ 客戶端,可以使用插件 qqbot.plugins.miniirc 來實現用 IRC 聊天的功能。加載方式: qq plug qqbot.plugins.miniirc ,或啟動時加載: qqbot -pl qqbot.plugins.miniirc ,或者在配置文件中的 plugins 選項中加入 'qqbot.plugins.miniirc' 。
插件加載后將在 6667 端口開啟一個微型的 IRC 服務器,用戶可以使用 IRC 客戶端(如 weechat, irssi 等)連接此服務器來實現命令行模式下的聊天。以下以 weechat 為例介紹使用方法:
啟動 weechat : weechat
連接本服務器: /connect localhost
進入 群聊天 會話: /join group-name
進入 討論組聊天 會話: /join !discuss-name
進入 好友聊天 會話: /query buddy-name
進入 聊天會話 后,直接敲入文本并回車就可以向對方發送消息了。所有接收到的 QQ 消息也會被轉發給相應的 聊天會話 。
在聊天會話之間切換: ctrl+P 或 ctrl+N
顯示所有 群和討論組 的名稱: /list
以上幾乎就是此微型 IRC 服務器所提供的所有功能了,但已經足夠用來和 QQ 好友/群/討論組 聊天了。
十、 smartqq 協議支持及限制
本項目已實現絕大部分 smartqq 協議支持的功能,如下:
消息收/發
聯系人(包括 好友/群/討論組/群成員/討論組成員)資料獲取和查詢(包括 QQ號/昵稱/名稱/備注名/群成員名片)
聯系人資料根據需要動態更新
被群內其他成員 @ 的通知
群管理功能: 設置/取消管理員 、 設置/刪除群名片 、 群成員禁言 以及 踢除群成員
發送、接收表情(詳見facemap.py)
其他功能:
調用系統默認圖片瀏覽器顯示登錄二維碼、將登錄二維碼發送至郵箱、開啟一個 http 服務器用來顯示登錄二維碼、在命令行窗口使用文本模式顯示二維碼
用 qq 命令行工具發消息、查詢|更新聯系人、群管理
提供 HTTP-API 接口發消息、查詢|更新聯系人、群管理
提供 miniirc 插件,可以在命令行模式下使用 IRC 客戶端聊天
掉線后自動重啟功能(有時需要手工掃碼)
定時執行任務(通過 qqbotsched 實現)
因 smartqq 協議的限制,以下問題沒有好的解決辦法:
無法長時間保持在線狀態,每次登錄成功后的 cookie 會每在 1 ~ 2 天后失效,將被騰訊服務器強制下線,此時必須手工掃碼重新登錄。可以打開郵箱模式和自動重啟模式,并配合 qqbot.plugins.schedrestart 插件使用,每天在固定的時間掃碼登錄一次,基本上可以穩定的保持在線狀態。
無法發送圖片、文件、音頻、 xml 卡片消息
無法獲取到自己通過其他客戶端(手機 QQ 、PC-QQ)發送的 好友 消息(提示:自己發送的 群/討論組 消息可以獲取到)
當 好友/群/群成員 存在同名現象或名稱中含特殊字符時,無法綁定其實際 QQ
無法在群內 @ 其他成員,即便用本程序在群里發送了 “@jack xxx” 這樣的消息, jack 也只能收到這個純文本,收不到“有人@我”的提醒。
無法向 群/討論組 內的其他非好友成員發消息,也無法收到非好友成員發過來的臨時會話消息
在非常少的情況下,發消息時會重復發送多次,也可能對方已收到消息但返回發送失敗的結果
十一、其他
常見問題
更新日志
十二、參考資料
總結
- 上一篇: 广汽集团发布“1551”国际化战略,目标
- 下一篇: 滴耳油_功效作用注意事项用药禁忌用法用量