使用go-cqhttp搭建QQ機(jī)器人
序言
go-cqhttp是基于 Mirai 以及 MiraiGo 的 OneBot Golang 原生實(shí)現(xiàn)(此句照搬文檔)
個(gè)人使用(不知道是不是只能使用)Python語(yǔ)言進(jìn)行編寫,僅供教程,不做完全分享
官方文檔地址
github項(xiàng)目地址
安裝環(huán)境
Python語(yǔ)言環(huán)境配置下載Python
要勾選Add python.exe to PATH
點(diǎn)擊Next
勾選Add Python to environment variables
Install
安裝完畢后Win + R打開(kāi)運(yùn)行輸入cmd
鍵入Python
如上圖所示即為安裝成功
配置項(xiàng)目
下載go-cqhttp.exe后,雙擊運(yùn)行,無(wú)視彈窗內(nèi)容直接確定(因?yàn)橐眠\(yùn)行完exe生成的bat來(lái)啟動(dòng)exe才是正確啟動(dòng)),三次確定后出現(xiàn)go-cqhttp.bat,雙擊運(yùn)行。
配置config.yml(客戶端信息)
選擇HTTP通信,提示退出,打開(kāi)config.yml
賬號(hào)密碼可不配置,拉到最下面
修改為以下內(nèi)容
//可將從server部分完全替換
servers:
# 添加方式,同一連接方式可添加多個(gè),具體配置說(shuō)明請(qǐng)查看文檔
#- http: # http 通信
#- ws: # 正向 Websocket
#- ws-reverse: # 反向 Websocket
#- pprof: #性能分析服務(wù)器
- http: # HTTP 通信設(shè)置
address: 0.0.0.0:5700 # HTTP監(jiān)聽(tīng)地址
timeout: 5 # 反向 HTTP 超時(shí)時(shí)間, 單位秒,<5 時(shí)將被忽略
long-polling: # 長(zhǎng)輪詢拓展
enabled: false # 是否開(kāi)啟
max-queue-size: 2000 # 消息隊(duì)列大小,0 表示不限制隊(duì)列大小,謹(jǐn)慎使用
middlewares:
<<: *default # 引用默認(rèn)中間件
post: # 反向HTTP POST地址列表
#- url: '' # 地址
# secret: '' # 密鑰
# max-retries: 3 # 最大重試,0 時(shí)禁用
# retries-interval: 1500 # 重試時(shí)間,單位毫秒,0 時(shí)立即
url: http://127.0.0.1:5701/ # 地址
secret: '' # 密鑰
max-retries: 10 # 最大重試,0 時(shí)禁用
retries-interval: 1000 # 重試時(shí)間,單位毫秒,0 時(shí)立即
這里要特別注意的是,http配置的address與下方post的url端口不能相同(可以修改)
保存后運(yùn)行bat,嘗試登錄
[2023-01-07 00:23:26] [INFO]: 當(dāng)前版本:v1.0.0-rc4
[2023-01-07 00:23:26] [INFO]: 將使用 device.json 內(nèi)的設(shè)備信息運(yùn)行Bot.
[2023-01-07 00:23:26] [INFO]: Bot將在5秒后登錄并開(kāi)始信息處理, 按 Ctrl+C 取消.
[2023-01-07 00:23:31] [INFO]: 開(kāi)始嘗試登錄并同步消息...
[2023-01-07 00:23:31] [INFO]: 使用協(xié)議: Android Phone
[2023-01-07 00:23:32] [INFO]: Protocol -> connect to server: 36.155.206.145:8080
[2023-01-07 00:23:32] [WARNING]: Protocol -> device lock is disable. http api may fail.
[2023-01-07 00:23:35] [INFO]: 收到服務(wù)器地址更新通知, 將在下一次重連時(shí)應(yīng)用.
[2023-01-07 00:23:35] [INFO]: 登錄成功 歡迎使用: acao
[2023-01-07 00:23:35] [INFO]: 開(kāi)始加載好友列表...
[2023-01-07 00:23:35] [INFO]: 共加載 23 個(gè)好友.
[2023-01-07 00:23:35] [INFO]: 開(kāi)始加載群列表...
[2023-01-07 00:23:36] [INFO]: 共加載 7 個(gè)群.
[2023-01-07 00:23:36] [INFO]: 資源初始化完成, 開(kāi)始處理信息.
[2023-01-07 00:23:36] [INFO]: アトリは、高性能ですから!
[2023-01-07 00:23:36] [INFO]: HTTP POST上報(bào)器已啟動(dòng): http://127.0.0.1:5701/
[2023-01-07 00:23:36] [INFO]: 正在檢查更新.
[2023-01-07 00:23:36] [INFO]: CQ HTTP 服務(wù)器已啟動(dòng): [::]:5700
[2023-01-07 00:23:48] [INFO]: 檢查更新完成. 當(dāng)前已運(yùn)行最新版本.
[2023-01-07 00:23:48] [INFO]: 開(kāi)始診斷網(wǎng)絡(luò)情況
[2023-01-07 00:23:51] [INFO]: 網(wǎng)絡(luò)診斷完成. 未發(fā)現(xiàn)問(wèn)題
[2023-01-07 00:23:58] [WARNING]: 上報(bào) Event 數(shù)據(jù)到 http://127.0.0.1:5701/ 失敗: Post "http://127.0.0.1:5701/": dial tcp 127.0.0.1:5701: connectex: No connection could be made because the target machine actively refused it. 將進(jìn)行第 1 次重試
[2023-01-07 00:24:02] [WARNING]: 上報(bào) Event 數(shù)據(jù)到 http://127.0.0.1:5701/ 失敗: Post "http://127.0.0.1:5701/": dial tcp 127.0.0.1:5701: connectex: No connection could be made because the target machine actively refused it. 將進(jìn)行第 2 次重試
這里上報(bào)出現(xiàn)了許多錯(cuò)誤,是正常現(xiàn)象,因?yàn)槲覀儧](méi)有監(jiān)聽(tīng)程序,沒(méi)地方上報(bào)
等我們接下來(lái)寫完監(jiān)聽(tīng)程序就不會(huì)這樣了
注:第七行的[WARNING]: Protocol -> device lock is disable. http api may fail.
屬于正?,F(xiàn)象,不需要找問(wèn)題(不影響)
在 config.yml 中,還可以設(shè)置在線狀態(tài),參考在線狀態(tài)
配置device.json(賬號(hào)信息)
{
"display": "MIRAI.619943.001",
"product": "mirai",
"device": "mirai",
"board": "mirai",
"model": "mirai",
"finger_print": "mamoe/mirai/mirai:10/MIRAI.200122.001/0642953:user/release-keys",
"boot_id": "8cfd480f-5acb-cb0f-0462-9dd269b378c3",
"proc_version": "Linux version 3.0.31-MJXB114B (android-build@xxx.xxx.xxx.xxx.com)",
"protocol": 1,
"imei": "121268379926671",
"brand": "mamoe",
"bootloader": "unknown",
"base_band": "",
"version": {
"incremental": "5891938",
"release": "10",
"codename": "REL",
"sdk": 29
},
"sim_info": "T-Mobile",
"os_type": "android",
"mac_address": "00:50:56:C0:00:08",
"ip_address": [10, 0, 1, 3],
"wifi_bssid": "00:50:56:C0:00:08",
"wifi_ssid": "\u003cunknown ssid\u003e",
"imsi_md5": "90b7592b208260238577eb697e1f426b",
"android_id": "49ebbf42888f6b36",
"apn": "wifi",
"vendor_name": "MIUI",
"vendor_os_name": "mirai"
}
這是格式化過(guò)的?。?!不是你的出了問(wèn)題?。?!
主要注意的是Protocol,這是你的登錄狀態(tài),默認(rèn)5位ipad協(xié)議,這里我改用了Android協(xié)議
Android協(xié)議:登錄狀態(tài)顯示,前面config.yml有設(shè)置的,但是手機(jī)端無(wú)法再登錄Bot的QQ
ipad協(xié)議優(yōu)點(diǎn):運(yùn)行Bot后可在手機(jī)端登錄,但是登錄狀態(tài)會(huì)顯示為WiFi在線-2G
值得一提的是,在config.yml的38行,有一個(gè)是否上報(bào)自身消息,也就是所謂的自觸發(fā),以及40行的是否移除replay自帶at效果,根據(jù)自身需要打開(kāi)(False是關(guān)閉,True是打開(kāi))
消息監(jiān)聽(tīng)
消息上報(bào)內(nèi)容
也就是我們要從go-cqhttp那里接收上報(bào)的消息了
先來(lái)了解一下監(jiān)聽(tīng)上報(bào)的消息格式內(nèi)容(普通消息)
{
'post_type': 'message',
'message_type': 'group',
'time': 1672415467,
'self_id': 3054770279,
'sub_type': 'normal',
'font': 0,
'group_id': 594875964,
'user_id': 423866219,
'message_id': -731133797,
'sender': {
'age': 0,
'area': '',
'card': '',
'level': '',
'nickname': '福建第一深情',
'role': 'owner',
'sex': 'unknown',
'title': '',
'user_id': 423866219
},
'anonymous': None,
'message': '6',
'message_seq': 4452,
'raw_message': '6'
}
這是一條消息(當(dāng)然也是格式化之后的)
其中post_type是我們接收到的消息類型,即message
message_type是指我們接收到的是group(群聊消息)或是private(私聊消息)
group_id為群號(hào),user_id為QQ號(hào),self_id為Bot本身的QQ號(hào)
那我們開(kāi)始寫一個(gè)監(jiān)聽(tīng)程序
監(jiān)聽(tīng)程序
我們用的是Python的pip庫(kù)中的Flask,Win+R打開(kāi)運(yùn)行輸入cmd后點(diǎn)擊確定,先更新一下pip
C:\User\afanm> python -m pip install --upgrade pip
更新完成后再安裝Flask
C:\User\afanm> pip install flask
將flask替換成其它,再安裝requests
打開(kāi)一個(gè).py文件隨意命名(我這里叫main.py)
監(jiān)聽(tīng)如下
from flask import Flask,request
import afan
app = Flask(__name__)
@app.route('/', methods=["POST"])
def post_data():
data = request.get_json()
print(data)
if data['post_type'] == 'message':
message = data['message']
print(message)
afan.messagex()
elif data['post_type'] == 'notice':
pass
else:
print("忽略上報(bào)")
return "OK"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5701)
導(dǎo)入初始化Flask,我們將request得到的數(shù)據(jù)賦值給data,意思就是data這個(gè)變量就是我們收到上報(bào)的消息,并調(diào)用我們寫在afan.py的回復(fù),這里的port就是我們剛剛post設(shè)置的端口
(插入)go-cqhttp運(yùn)行的原理
go-cqhttp客戶端將我們電腦配置成為微型服務(wù)器,開(kāi)放了5700和5701端口進(jìn)行通訊,通過(guò)訪問(wèn)我們自己電腦上的API接口進(jìn)行發(fā)送,所以即使沒(méi)有程序,我們?cè)L問(wèn)接口依舊可以運(yùn)行
例如發(fā)送消息接口終結(jié)點(diǎn)為send_msg,在運(yùn)行客戶端后,網(wǎng)址訪問(wèn)127.0.0.1/send_msg依舊可以發(fā)送消息(需要提交參數(shù))
消息回復(fù)
那么我們封裝一個(gè)接口,直接調(diào)用就可以發(fā)送消息,不需要反復(fù)寫API
由官方API文檔,我們能了解到:
消息的終結(jié)點(diǎn)為send_msg
需要的參數(shù)為群號(hào),消息內(nèi)容,發(fā)送類型,我們以群消息為例
class API:
@staticmethod
def send(message):
url = "http://127.0.0.1:5700/send_msg"#這里要加上http://,不然會(huì)報(bào)錯(cuò)
data = request.get_json()#獲取上報(bào)消息
params = {
"message_type":data['message_type'],
"group_id":data['group_id'],
"message":message
}
requests.get(url,params=params)
這樣,當(dāng)我們?cè)诤蠓皆~庫(kù)調(diào)用該函數(shù)時(shí),只需傳入消息內(nèi)容便可以發(fā)送了,私聊的話只需要判斷消息來(lái)源進(jìn)行微調(diào)即可
接下來(lái),創(chuàng)建文件afan.py,導(dǎo)入main.py以及一些其它庫(kù)
我們前面寫道,如果消息類型為message的話,調(diào)用afan.messagex(),導(dǎo)入afan后,定義一個(gè)函數(shù)messagex()
我的Bot名為阿草,我先寫一個(gè)當(dāng)我發(fā)送 阿草 時(shí)回復(fù) 阿草在哦 的詞庫(kù)
import requests
from flask import Flask,request
from main import API
def messagex():
data = request.get_json()
message = data['message']
if "阿草" == message:
API.send("阿草在哦")
else:
print("指令錯(cuò)誤")#這里不是發(fā)送,是打印到我們后臺(tái)監(jiān)聽(tīng)程序
這樣,當(dāng)消息為阿草的時(shí)候,調(diào)用API發(fā)送阿草在哦
接下來(lái)我們只要運(yùn)行main.py,然后啟動(dòng)go-cq客戶端就可以了
至于其它東西,我們只需要根據(jù)上報(bào)收到的消息進(jìn)行設(shè)置就行了,上報(bào)消息內(nèi)容,我們依然可以在文檔的 Event上報(bào) 處查看
實(shí)現(xiàn)其它內(nèi)容,只需要封裝其它接口進(jìn)行調(diào)用即可
注意:封裝接口時(shí)調(diào)用的端口是5700,客戶端監(jiān)聽(tīng)5700,消息post上報(bào)到5701,再有main.py進(jìn)行監(jiān)聽(tīng)5701調(diào)用詞庫(kù)回復(fù),可根據(jù)需要自行修改,不要運(yùn)行afan.py詞庫(kù)文件,會(huì)造成端口沖突的,我們只需要運(yùn)行main.py和go-cq客戶端即可
代碼整合
最后送上上面整合的監(jiān)聽(tīng)以及回復(fù)代碼
main.py文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-779909.html
from flask import Flask,request
import requests
import afan
app = Flask(__name__)
class API:
@staticmethod
def send(message):
url = "http://127.0.0.1:5700/send_msg"#這里要加上http://,不然會(huì)報(bào)錯(cuò)
data = request.get_json()#獲取上報(bào)消息
params = {
"message_type":data['message_type'],
"group_id":data['group_id'],
"message":message
}
requests.get(url,params=params)
@app.route('/', methods=["POST"])
def post_data():
data = request.get_json()
print(data)
if data['post_type'] == 'message':
message = data['message']
print(message)
afan.messagex()
else:
print("忽略消息")
return "OK"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5701)
afan.py文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-779909.html
import requests
from flask import Flask,request
from main import API
def messagex():
data = request.get_json()
message = data['message']
if "阿草" == message:
API.send("阿草在哦")
else:
print("指令錯(cuò)誤")#這里不是發(fā)送,是打印到我們后臺(tái)監(jiān)聽(tīng)程序
到了這里,關(guān)于使用go-cqhttp搭建QQ機(jī)器人的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!