如何用node寫qq機(jī)器人

必要的要的模塊

const cryto = require('crypto'); //配合oicq進(jìn)行登錄
const oicq = require("oicq"); //關(guān)鍵的npm包 別人封裝好的qq登錄

初始demo可以去看 oicq 官方文檔

這里要注意的一個(gè)點(diǎn)就是 初次使用手機(jī)登錄可能會(huì)報(bào)安全問題,建議使用手表登錄,然后用返回的鏈接用手機(jī)認(rèn)證一下。然后再重新登錄就不會(huì)出現(xiàn)驗(yàn)證登錄或者你賬號(hào)問題了。

然后就可以寫你自己的功能了。
我這里寫了一個(gè)游戲群的群機(jī)器人,配合去爬取嗶哩嗶哩和豆瓣的數(shù)據(jù)來給群里面進(jìn)行每日任務(wù)和每周復(fù)刻信息。
碼云地址

主要代碼預(yù)覽

const express = require('express');
const router = express.Router();
const cryto = require('crypto')
const oicq = require("oicq");
const https = require('https')
const xpath = require('xpath')
const dom = require('xmldom').DOMParser
const schedule = require('node-schedule');
const zaoCi = require('./zao')
const kuaCi = require('./kua')
const defaultConfig = require('./config');


// 圖片配置
const xianList =
  defaultConfig.xianList
// 群配置
const qunList =
  defaultConfig.qunList
// 托管的QQ號(hào)配置
const {
  uin,
  pwd
} =
defaultConfig.account
// defaultConfig.accountTest
// 每日任務(wù)upid
const upId =
  defaultConfig.upId

// 復(fù)刻消息
let fukeTime = ''
let fukeImg = ''
// 每日任務(wù)
let imgList = []
// 運(yùn)行時(shí)獲取一次
// 獲取每日 
getImgList()
// 定時(shí)處理
scheduleCronstyle()
// 獲取復(fù)刻
getAncestor()


const password_md5 = cryto.createHash('md5').update(pwd).digest('hex')
const config = {
  platform: 3, //登陸類型 1手機(jī) 2平板 3手表(不支持部分群事件)
  // log_level: "info", //日志級(jí)別,有trace,debug,info,warn,error,fatal,off
  log_level: "off", //日志級(jí)別,有trace,debug,info,warn,error,fatal,off
  kickoff: false, //被擠下線是否在3秒后反擠對(duì)方
  ignore_self: true, //群聊是否無(wú)視自己的發(fā)言
}
const client = oicq.createClient(uin, config);
client.login(password_md5);

// 登錄
client.on("system.login.captcha", () => {
  process.stdin.once("data", input => {
    client.captchaLogin(input);
  });
});

// 監(jiān)聽信息
client.on("message", data => {
  console.log(data)
  console.log(data.message)

  // 私聊小助手時(shí)
  if (data.message_type == "private") {
    setTimeout(() => {
      defaultMessage(data)
    }, 0)
  }

  if (qunList[data.group_id]) {
    // @小助手時(shí)處理
    if (data.message[0].type == "at" && data.message[0].data.qq == uin) {
      // 處理消息
      setTimeout(() => {
        messageProcess(data, data.message[1].data.text)
      }, 0)
    }
    if (qunList[data.group_id].ka) {
      messagePraise(data)
      return false
    }
    // 日常消息處理
    setTimeout(() => {
      defaultMessage(data)
    }, 0)

  }
});
client.on("request", data => console.log(data));
client.on("notice", data => console.log(data));


// 發(fā)送夸人消息
function messagePraise(data) {
  client.sendGroupMsg(data.group_id, kuaCi[getRandomInt(72)])
}


// 消息處理函數(shù)
function messageProcess(data, text) {
  let sex = data.sender.sex == "male" ? '靚仔' : '靚妹'
  switch (text) {
    case " 0":
      qunList[data.group_id].ka = false
      client.sendGroupMsg(data.group_id, `嗚嗚嗚~小可愛再見呀!\n [CQ:image,cache=0,file=http://localhost:1001/images/ku.jpg]`)
      break
    case " 再見":
      qunList[data.group_id].ka = false
      client.sendGroupMsg(data.group_id, `嗚嗚嗚~小可愛再見呀!\n [CQ:image,cache=0,file=http://localhost:1001/images/ku.jpg]`)
      break
    case " 安靜":
      qunList[data.group_id].ka = false
      client.sendGroupMsg(data.group_id, `嗚嗚嗚~小可愛再見呀!\n [CQ:image,cache=0,file=http://localhost:1001/images/ku.jpg]`)
      break
    case " 1":
      qunList[data.group_id].ka = true
      client.sendGroupMsg(data.group_id, `美好的一天美好的你,美好的話語(yǔ)送給你!`)
      break
    case " 開啟夸人模式":
      qunList[data.group_id].ka = true
      client.sendGroupMsg(data.group_id, `美好的一天美好的你,美好的話語(yǔ)送給你!`)
      break
    case " 夸我":
      qunList[data.group_id].ka = true
      client.sendGroupMsg(data.group_id, `美好的一天美好的你,美好的話語(yǔ)送給你!`)
      break
    default:
      client.sendGroupMsg(data.group_id, `${sex}小助手現(xiàn)在能為你做的事情為
      1.定時(shí)任務(wù)
        每日8點(diǎn)報(bào)每日任務(wù)(數(shù)據(jù)來源為b站up:彤魚不吃魚吖_),每周報(bào)最新復(fù)刻信息(數(shù)據(jù)來源于豆瓣小組(放我出趕due)的返場(chǎng)先祖記錄貼)\n
      2.聊天關(guān)鍵詞(消息攜帶)
        (每日任務(wù)|今日任務(wù)) 會(huì)觸發(fā)小助手私聊每日任務(wù)
        (近期先祖|最新復(fù)刻) 會(huì)觸發(fā)小助手私聊最新復(fù)刻信息
        (先祖在哪里|先祖位置) 會(huì)觸發(fā)小助手私聊詢問你想知道哪里先祖的位置,回答小助手會(huì)發(fā)送對(duì)應(yīng)攻略
        (小金人在哪里|小金人位置) 會(huì)觸發(fā)小助手私聊詢問你想知道哪里小金人的位置,回答小助手會(huì)發(fā)送對(duì)應(yīng)攻略
        (近期活動(dòng)) 會(huì)觸發(fā)小助手私聊發(fā)送官方微博地址
        (群沒有開啟私聊的話請(qǐng)自行添加小助手)\n
      3.特殊功能
        @我 (1|開啟夸人模式|夸我) 開啟彩虹屁模式
        @我 (0|再見|安靜) 關(guān)閉彩虹屁模式 
      `)
  }

}




// 處理對(duì)話
function defaultMessage(data, type) {
  let text = data.message[0].data.text ? data.message[0].data.text : ''
  let sex = data.sender.sex == "male" ? '靚仔' : '靚妹'

  if (text.indexOf("今日任務(wù)") != -1 || text.indexOf("今天任務(wù)") != -1 || text.indexOf("每日任務(wù)") != -1) {
    client.sendPrivateMsg(data.user_id, imgList + '\n以上就是今日份的小小幸運(yùn)喲~')
  } else if (text.indexOf("近期先祖") != -1 || text.indexOf("最新先祖") != -1 || text.indexOf("最新復(fù)刻") != -1) {
    client.sendPrivateMsg(data.user_id, `近期復(fù)刻先祖消息!${fukeTime}\n [CQ:image,cache=0,file=${fukeImg}] \n數(shù)據(jù)來源于豆瓣小組(放我出趕due)的返場(chǎng)先祖記錄貼`)
  } else if (text.indexOf("近期活動(dòng)") != -1) {
    client.sendPrivateMsg(data.user_id, `${sex}請(qǐng)?jiān)诠俜轿⒉┎榭?https://m.weibo.cn/u/6355968578#_loginLayer_1602073018866`)
  } else if ((text.indexOf("先祖在哪里") != -1 || text.indexOf("先祖位置") != -1) && text.indexOf("復(fù)刻先祖") == -1) {
    client.sendPrivateMsg(data.user_id, `${sex}請(qǐng)告訴我你想知道的先祖位置!\n 例如 晨島`)
  } else if (text.indexOf("小金人在哪里") != -1 || text.indexOf("小金人位置") != -1) {
    client.sendPrivateMsg(data.user_id, `${sex}請(qǐng)告訴我你想知道的小金人位置! \n 例如 晨島小金人`)
  } else {
    // 處理先祖位置
    if (data.message_type == "private") {
      if (xianList.indexOf(text) != -1) {
        client.sendPrivateMsg(data.user_id, `${xianList[xianList.indexOf(text)]}位置來咯!\n [CQ:image,cache=0,file=http://localhost:1001/images/${xianList[xianList.indexOf(text)]}.jpg]`)
      }
    }
  }
}


// 獲取復(fù)刻先祖圖片
function getAncestor() {
  let option = {
    hostname: 'www.douban.com',
    path: '/group/topic/169143556/',
    headers: {
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
      "Accept-Language": "zh-CN,zh;q=0.9",
      "Cache-Control": "max-age=0",
      "Connection": "keep-alive",
      "Host": "www.douban.com",
      "Sec-Fetch-Dest": "document",
      "Sec-Fetch-Mode": "navigate",
      "Sec-Fetch-Site": "none",
      "Sec-Fetch-User": "?1",
      "Upgrade-Insecure-Requests": "1",
      "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"

    }
  };
  return new Promise(resFn => {
    https.get(option, function (okdata) {
      let json = ""
      okdata.setEncoding("utf8")
      okdata.on("data", chunk => json += chunk)
      okdata.on("end", () => {

        var doc = new dom().parseFromString(json)
        let imgList = xpath.select("http://div[@class='image-wrapper']/img/@src", doc)
        let text = xpath.select("http://div[@class='rich-content topic-richtext']/p/text()", doc)
        imgList.forEach((v, i) => {
          if (i == imgList.length - 2) {
            fukeImg = v.value
          }
        })
        text.forEach((v, i) => {
          if (i == text.length - 3) {
            fukeTime = v.nodeValue
          }
        })
        resFn()
      })
    })
  })
}


// 獲取每日任務(wù) 
function getImgList() {
  return new Promise(resFn => {
    https.get(`https://api.bilibili.com/x/space/article?mid=${upId}`, function (okdata) {
      let json = ""
      okdata.setEncoding("utf8")
      okdata.on("data", chunk => json += chunk)
      okdata.on("end", () => {
        let id = JSON.parse(json).data.articles[0].id
        https.get(`https://www.bilibili.com/read/cv${id}`, function (okdata) {
          let datas = ""
          okdata.setEncoding("utf8")
          okdata.on("data", chunk => datas += chunk)
          okdata.on("end", () => {
            let titleList = []
            var doc = new dom().parseFromString(datas)
            xpath.select("http://figure/figcaption/text()", doc).forEach(item => {
              titleList.push(item.data)
            })
            let i = -1
            imgList = xpath.select("http://figure/img/@data-src", doc).map((item, index) => {
              if (item.value.indexOf('.jpg') != -1) {
                i++
                return `[CQ:image,cache=0,file=https:${item.value}]\n ${titleList[i] == undefined?'這個(gè)圖片我就不解釋咯!':titleList[i]}`
              }
            }).join(" ")
            resFn()
          })
        })
      })
    })
  })

}
// 定時(shí)函數(shù)
function scheduleCronstyle() {
  //每天早上:
  schedule.scheduleJob('59 59 7 * * *', async () => {
    await getImgList()
    Object.keys(qunList).forEach(async (item) => {
      if (!qunList[item].no) {
        qunList[item].ka = false
        await sendMsg(item, true)
      }

    });
  });
  //每周三發(fā)送:
  schedule.scheduleJob('59 59 6 * * 3', async () => {
    await getAncestor()
    Object.keys(qunList).forEach(async (item) => {
      await sendMsg(item)
    });
  });
}

// 發(fā)送定時(shí)消息
function sendMsg(item, type) {
  return new Promise(resFn => {
    if (type) {
      client.sendGroupMsg(item, imgList + '\n' + zaoCi[getRandomInt(100)])
    } else {
      client.sendGroupMsg(item, `近期復(fù)刻先祖消息!${fukeTime}\n [CQ:image,cache=0,file=${fukeImg}] \n數(shù)據(jù)來源于豆瓣小組(放我出趕due)的返場(chǎng)先祖記錄貼`)
    }
    resFn()
  })
}

// 隨機(jī)取一句話
function getRandomInt(number) {
  return Math.floor(Math.random() * number)
}

/* GET users listing. */
router.get('/', function (req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

測(cè)試機(jī)器人群號(hào) 334014763

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容