目录

  • 1.介绍
  • 2.插件安装运行
  • 3.快速上手


1.介绍

本项目主要是node wechaty的一个小应用,其核心原理主要通过wechaty插件登录网页版微信接受消息进行通信以及其他功能等。这里只做了聊天接收展示,图灵机器人接入指定人聊天,通过爬虫每日一说,墨迹天气定时给指定人发送消息等

1.主要功能
登录后可在微信发送以下内容
‘开启:’ 开启图灵机器人聊天(可指定微信好友)

‘关闭:’ 关闭灵机器人聊天

定时给女友发送暖心问候 1.墨迹天气 2.每日一句

2.插件安装运行

本项目主要需要安装一下插件

"dependencies": {
    "cheerio": "^1.0.0-rc.3", // 网络抓取要识别Web页面,并将其转换成结构化数据
    "node-schedule": "^1.3.2", // Nodejs定时任务
    "qrcode-terminal": "^0.12.0",// 在终端输出二维码
    "request": "^2.88.2", // node request请求
    "request-promise": "^4.2.5", // request请求promise形式回调返回
    "wechaty": "^0.38.4" // 开源的微信SDK
  }

没装yarn 的可以使用npm

安装依赖 yarn install

运行yarn start

3.快速上手

1.所有配置项均在 config/index.js文件中

// 配置文件
  module.exports = {
    NAME: 'xxx', //女朋友备注姓名
    NICKNAME: 'xxx', //女朋友昵称
    MEMORIAL_DAY: '2017/05/11', //你和女朋友的纪念日
    SENDDATE: '00 00 08 * * *', //定时发送时间 每天8点0分0秒发送,规则见 npm schedule
    MOJI_HOST: 'https://tianqi.moji.com/weather/china/',
    CITY:'shaanxi',//收信者所在城市
    LOCATION:'yanta-district',//收信者所在区
    ONE: 'http://wufazhuce.com/',
    //图灵机器人功能配置项
    AUTOREPLY: false, //自动聊天功能 默认关闭 开启设置为: true
    TULINGURL: 'http://openapi.tuling123.com/openapi/api/v2',
    TULINGKEY: '',//图灵机器人apikey,需要自己到图灵机器人官网申请,并且需要认证http://www.turingapi.com/

  }

2.代码实现

const { Wechaty } = require('wechaty')
const QrcodeTerminal = require('qrcode-terminal')
const cheerio = require('cheerio')
const schedule = require('node-schedule')
const { post, get } = require('./utils/request')
const tools = require('./utils/timeTools')
const config = require('./config/index')

/**
 *
 * 获取图灵机器人消息
 * @param {*} text 传入聊天内容
 * @returns
 */
const getNews = (text) => {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res
    reject = rej
  })
  post(config.TULINGURL, {
    reqType:0,
      perception: {
          inputText: {
            text
          },
      },
      userInfo: {
        apiKey: config.TULINGKEY,
        userId: "485b3f76446f8b99"
      }
  })
  .then((res) => {
    if (res.intent.code !=0 && res.intent.code > 10000) {
      resolve(res)
    } else {
      reject(res)
    }
  })
  .catch(res => {
    reject(res)
  })
  return promise
}
// 获取每日一句
const getOne = async() =>{
  // 获取每日一句
  try {
    let res = await get(config.ONE);
    let $ = cheerio.load(res);
    let todayOneList = $('#carousel-one .carousel-inner .item');
    let todayOne = $(todayOneList[0])
      .find('.fp-one-cita')
      .text()
      .replace(/(^\s*)|(\s*$)/g, '');
    return todayOne;
  } catch (err) {
    console.log('错误', err);
    return err;
  }
}
// 获取墨迹天气
const getWeather = async() => {
  let url = config.MOJI_HOST + config.CITY+'/'+config.LOCATION
  let res = await get(url)
  let $ = cheerio.load(res)
  let weatherTips = $('.wea_tips em').text()
  const today = $('.forecast .days').first().find('li');
  let todayInfo = {
      Day:$(today[0]).text().replace(/(^\s*)|(\s*$)/g, ""),
      WeatherText:$(today[1]).text().replace(/(^\s*)|(\s*$)/g, ""),
      Temp:$(today[2]).text().replace(/(^\s*)|(\s*$)/g, ""),
      Wind:$(today[3]).find('em').text().replace(/(^\s*)|(\s*$)/g, ""),
      WindLevel:$(today[3]).find('b').text().replace(/(^\s*)|(\s*$)/g, ""),
      PollutionLevel:$(today[4]).find('strong').text().replace(/(^\s*)|(\s*$)/g, "")
  }
  let obj = {
    weatherTips:weatherTips,
    todayWeather:todayInfo.Day + ':' + todayInfo.WeatherText + '<br>' + '温度:' + todayInfo.Temp +  '<br>'
        + todayInfo.Wind + todayInfo.WindLevel + '<br>' + '空气:' + todayInfo.PollutionLevel + '<br>'
  }
  return  obj

}
// 定时任务
const main = async() => {
  let  contact = await bot.Contact.find({name:config.NICKNAME}) || await bot.Contact.find({alias:config.NAME}) // 获取你要发送的联系人
  let one = await getOne() //获取每日一句
  let weather = await getWeather() //获取天气信息
  let today = await tools.formatDate(new Date())//获取今天的日期
  let memorialDay = tools.getDay(config.MEMORIAL_DAY)//获取纪念日天数
  let str = today + '<br>' + '今天是我们在一起的第' + memorialDay + '天'
      + '<br><br>今日天气早知道<br><br>' + weather.weatherTips +'<br><br>' +weather.todayWeather+ '每日一句:<br><br>'+one+'<br><br>'+'------来自最爱你的我'
  await contact.say(str)//发送消息
}

//  二维码生成
const onScan = (qrcode, code) => {
  QrcodeTerminal.generate(qrcode) // 在console端显示二维码
  const qrcodeImageUrl = [
    'https://api.qrserver.com/v1/create-qr-code/?data=',
    encodeURIComponent(qrcode),
  ].join('')
  console.log(qrcodeImageUrl)
}
// 登录
const onLogin = (user) => {
  console.log(`User ${user} logined`)
  schedule.scheduleJob(config.SENDDATE, () => {
    console.log('小助理开始工作啦!')
    main()
  })
}
// 登出
const onLogout = (user) => {
  console.log(`User ${user} 登出`)
}
// 监听消息
/**
 *
 *
 * @param {*} message 消息
 */
const onMessage = async(message) => {
  const contact = message.from() // 发消息人
  const content = message.text().trim() // 消息内容
  const room = message.room() // 是否是群消息
  const alias = await contact.alias(); // 发消息人备注
  const isText = message.type() === bot.Message.Type.Text; // 是否是文字
  if (content === '开启:') { // 通过输入内容开启关闭图灵机器人
    config.AUTOREPLY = true
  } else if (content === '关闭:'){
    config.AUTOREPLY = false
  }
  if (message.self()) {
    return
  }
  if (room && isText) {
    // 如果是群消息 目前只处理文字消息
    const topic = await room.topic();
    console.log(`群名: ${topic} 发消息人: ${contact.name()} 内容: ${content}`);
  } else if (isText) {
    // 如果非群消息 目前只处理文字消息
    console.log(`发消息人: ${alias} 消息内容: ${content}`);
    if(alias == config.NAME) {
      if (config.AUTOREPLY) {
        const news = await getNews(content).catch(err => console.log(err,'机器人接口出错啦'))
        await message.say(news.results[0].values.text)
      }
    }
    
  }
}
const bot = new Wechaty({ name: 'yeshen' });

bot.on('scan', onScan)
  .on('login', onLogin)
  .on('logout', onLogout)
  .on('message', onMessage)

bot.start()
   .then(() => console.log('开始登录微信'))
   .catch(err => console.error(err))

项目github