主要使用 Wechaty 库来进行
const { Wechaty } = require('wechaty');
const bot = new Wechaty({ name: 'xxx' }) // 记录一个签名用于免扫码登陆
const Qrcode = require('qrcode-terminal'); //可以在终端显示二维码
const autoBot = require('./utils/getReply'); //引入自动回复
const config = require('./config')
const initTask = require('./utils/timeTask') //定时任务
bot.start().then(() => console.log('开始登陆微信'))
.catch(e => console.error(e));
bot.on('scan', (qrcode, status) => {
let qrcodeSrc = `https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(qrcode)}`
Qrcode.generate(qrcode, { small: true });
})
bot.on('login', handleLogin)
bot.on('message', handleMessage) //处理消息
async function handleLogin(user) {
console.log(`用户${user}登陆成功`);
initTask(_=>{
console.log('执行定时任务=====>')
init();
})
}
async function handleMessage(messge) {
let contact = messge.from(); //发送人
const room = messge.room(); //群消息
const alias = await contact.alias(); //发送人的备注 name()发送人昵称
const name = await contact.name();
const content = messge.text().trim(); //发送的消息
if (messge.self()) {
console.log(`跳过自己的回复,${contact.name()}`)
return
}
if (room) {
console.log(`群名:${await room.topic()} 发消息人:${contact.name()} 内容:${content}`)
//可以回复群里消息
if(await room.topic() === '好好学习天天向上'){
let reply = await autoBot.getBotReply(content)
room.say(reply);
}
} else {
//这里的逻辑可以自己写 都可以调用getReply.js里的接口来进行回复
if (content.includes('天气')) {
let reply = await autoBot.getWetherInfo()
contact.say(reply);
}
console.log(`类型: ${contact}`)
console.log(`发消息人备注: ${await contact.alias()} 消息内容: ${content}`)
}
}
//初始化任务 发送天气预报
async function init() {
const friend = await bot.Contact.find({ name: config.NICK_NAME }) || await bot.Contact.find({ alias: config.ALISA })
let reply = await autoBot.getWetherInfo()
//还可以发送 新闻 每日一说 自己调用就行了
await friend.say(reply);
}
在当前目录下可以新建一个config.js来自定义设置
//建议大家自己注册
module.exports = {
TULING_KEY:'d6cdb25d7e1145f5877bf8d3dc915cb6', //图灵机器人api
TIANXING_KEY:'cba50d45aca1560837508d06932b88cf', //天行api
TIME_TASK:['12:01','23:59'], //定时任务时间
NICK_NAME:''", //昵称
ALISA:'xxx' , //备注名
LOCATION:'贵阳' , //别加 市
GROUPNAME:['好好学习天天向上'],
}
因为要使用定时任务 所以用到了node-schedule模块
新建一个utils文件夹
//timeTask.js
const schedule = require('node-schedule');
const config = require('../config')
/**
* @param{function} 执行回调函数
*
* scheduleJob arguments :
* ┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ |
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, OPTIONAL)
*/
module.exports = function task(callback) {
if(typeof callback !== 'function' && !callback){
console.log('参数错误');
return
}
for(let t of config.TIME_TASK){
let c = t.split(':');
schedule.scheduleJob(`0 ${c[1]} ${c[0]} * * *`, _=>callback());
}
}
定时执行有了现在需要获取自动回复的机器人接口
//在utils文件夹下新建getReply.js
const cry = require("crypto");
const { machineIdSync } = require('node-machine-id');
const config = require('../config')
const http = require('./http')
const cheerio = require('cheerio');
let md5 = cry.createHash('md5');
let userId = md5.update(machineIdSync()).digest('hex');
//这里我用了几个接口来获取
//新闻,天气,机器人,每日一句
const touTiaoApi = 'http://api.tianapi.com/topnews/index';
//获取机器人回复
//因为这api需要每次访问提供一个唯一的id 所以使用 node-machine-id' 和 md5 模块来生成唯一id
async function getBotReply(word) {
let data = {
"reqType": 0,
"perception": {
"inputText": {
"text": word || '你叫什么名字',
},
"selfInfo": {
"location": {
"city": config.LOCATION,
}
},
},
"userInfo": {
"apiKey": config.TULING_KEY,
"userId": userId
}
};
let response = await http('http://openapi.tuling123.com/openapi/api/v2', 'post', data);
let content = response.data;
return content.results[0].values.text || '机器人api获取出错'
}
//获取今日天气
async function getWetherInfo(){
const res = await http(`http://api.tianapi.com/txapi/tianqi/index?key=${config.TIANXING_KEY}&city=${encodeURI(config.LOCATION)}`,'get')
if(res.data.code == 200){
let result = res.data.newslist[0];
let str = `今日天气早知道:\n${result.date} ${result.week} \n天气:${result.weather} 最高温:${result.lowest} 最低温:${result.highest} \n风力:${result.windspeed} 风向:${result.wind} 空气质量等级:${result.air_level} 空气质量指数:${result.air} \ntip:${result.tips}`
return str || '天气获取出错'
}
}
//用node版的jq cheerio模块来爬去数据
async function getOneText(){
const response = await http('http://wufazhuce.com/','get')
const $ = cheerio.load(response.data);
const parent = $('#carousel-one .carousel-inner .item');
const text = $(parent[0]).find('.fp-one-cita').text().trim()
return text || '每日一句获取出错'
}
//获取新闻热点
let count = '5' //新闻条数
async function getTopNews(){
let url = `${touTiaoApi}?key=${config.TIANXING_KEY}&num=${count}`
const response = await http(url,'get');
if(response.data.code == 200){
const list = response.data.newslist;
let text = `今日新闻: \n${list.map(item=>{
return `${item.ctime} \n${item.title}\n${item.description}\n<a src=${item.url} >查看详情</a>`
})}`
return text
}
return '获取新闻出错'
}
module.exports = {
getBotReply,
getWetherInfo,
getOneText,
getTopNews
}
因为简单封装了一下http请求,所以在utls下新建http.js
//http.js
const axios = require('axios');
function http(url,method,param){
return new Promise((resove,reject)=>{
const options = {
method,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
url,
data: param
}
axios(options).then(res=>{
try {
resove(res)
} catch (error) {
reject(error)
}
})
})
}
module.exports = http