基于wechaty的定时消息推送(可以哄女朋友)、智能聊天和私人助理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于wechaty的定时消息推送(可以哄女朋友)、智能聊天和私人助理相关的知识,希望对你有一定的参考价值。

参考技术A ---

title: "基于wechaty的定时消息推送(可以哄女朋友)、智能聊天和私人助理"

author: jasonlovesharon

email: 54027901@163.com

tags:

  - nodejs

  - wechaty

  - wechaty-puppet-padplus

---

## 前言

- 自从2017年微信web端API限制以后,itchat等一大批bot歇菜了,一直都在找一款合适的替品

- 目前来看,大部分都是针对windows微信客户端,基于HOOK的dll注入实现对微信的操控,有一定的封号风险,只能用固定的版本,部署在linux服务器端比较困难,意味着只能一直开着电- -wechaty,支持IPAD,,MAC等多种协议,不用去调用WEB网页API,并且可以布署在服务器,满足我所有需求。[项目地址](https://github.com/wechaty/wechaty)

- 看完官方文档后([token官方介绍](https://github.com/juzibot/welcome/wiki/everything-about-wechaty)), 发现需要申请Token,并且python版本的Token是要付费的,但没有学过typescript,有点想放弃,浏览了一下ding-dong-bot的Example,似乎可以看懂,那就边学习边摸索吧。(ps:后来偶然见发现了另一篇可以使用将token转变一下实现python版wechaty,但此时已经基本用TS写完了,如果想用Python等其他语言可以参考[官方文档](https://github.com/wechaty/wechaty/issues/1985)。)

## 具备功能

### 1. 关键词触发功能

1.1 关键词"介绍一下自己"、 "自我介绍一下"、 "你是谁"触发自我介绍

1.2 地名+天气 触发天气查询

### 2. 智能聊天功能

2.1群外直接聊天

2.2群内成员皆有聊天权限“@bot” 聊天

2.3不会回复 @其他群成员 的消息

## 实现过程

Talk is cheap,show your code

### 1. 主程序

```typescript

import Wechaty, Message, UrlLink,log, from 'wechaty'

import PuppetPadplus from 'wechaty-puppet-padplus'

import EventLogger, QRCodeTerminal from 'wechaty-plugin-contrib'

import WechatyWeixinOpenAI, from 'wechaty-weixin-openai'

import setSchedule, from './schedule/index'

import getDay, formatDate, from './utils/index'

import getOne, getTXweather, getSweetWord, from './superagent/index'

// 创建微信每日说定时任务

async function initDay()

  console.log(`已经设定每日说任务`);

  setSchedule('0 40 0 * * *', async () =>

    console.log('你的贴心小助理开始工作啦!')

    let logMsg

    let contact =

      (await bot.Contact.find( name: 'Jason' )) ||

      (await bot.Contact.find( alias: 'boss' )) // 获取你要发送的联系人

    let one = await getOne() //获取每日一句

    let weather = await getTXweather() //获取天气信息

    let today = await formatDate(new Date()) //获取今天的日期

    let memorialDay = getDay('2009/08/07') //获取纪念日天数

    let sweetWord = await getSweetWord()

    let str = `$today\n我们相爱的第$memorialDay天\n\n元气满满的一天开始啦,要开心噢^_^\n\n今日天气\n$weather.weatherTips\n$

      weather.todayWeather

    \n每日一句:<br>$one<br><br>每日土味情话:<br>$sweetWord<br><br>————————最爱你的我`

    try

      logMsg = str

      await delay(2000)

      await contact.say(str) // 发送消息

    catch (e)

      logMsg = e.message

   

    console.log(logMsg)

  )



const padplusToken = '你自己的TOKEN'

const puppet = new PuppetPadplus(

  token: padplusToken,

)

const bot = new Wechaty(

  name: 'jason-assistant',

  puppet,

)

bot.use(EventLogger())

bot.use(QRCodeTerminal( small: true ))

//在Wechaty里面引用和配置插件

const openAIToken = '你自己的机器人TOKEN' //需要在微信对话开放平台申请,点击机器人设置》绑定应用》在页面最下方即可看到

const openAIEncodingAESKey = '你自己的EncodingAESKey' //微信对话开放平台申请,点击机器人设置》绑定应用》在页面最下方即可看到

const preAnswerHook = async (message: Message) =>

  const isCommonMaterial = await processCommonMaterial(message)

  if (isCommonMaterial)

    return false

 



/**

* 获得boss联系名片,当机器人找不到问题答案时,将BOSS的名片推送过去

*/

const getBoss = async () =>

    const contact = bot.Contact.load('boss微信ID')

    await contact.sync()

    return contact

 

  const noAnswerHook = async (message: Message) =>

    const room = message.room()

    const from = message.from()

    if (!room)

      const boss = await getBoss()

      await message.say('你的问题我不会回答,你可以联系我的老板')

      await message.say(boss)

      return;

   

    const members = await room.memberAll()

    const bossInRoom = members.find(m => m.id === 'boss微信id')

    if (bossInRoom)

      await room.say`$bossInRoom,$from问的问题我不知道,你帮我回答一下吧。`

    else

      const boss = await getBoss()

      await room.say`$from,你的问题我不会回答,你可以联系我的老板`

      await room.say(boss)

   

 

/**

* 用wechaty-weixin-openai可以实现快速接入微信对话平台

*/

bot.use(WechatyWeixinOpenAI(

    token: openAIToken,

    encodingAESKey: openAIEncodingAESKey,

    noAnswerHook, //在机器人无法回答时,推送设定的回答

    preAnswerHook, //判断是否是关键字,如果是关键字,触发关键字回答而不接入微信开放平台

  ))

const processCommonMaterial = async (message: Message) =>

    const room = message.room()

    // const from = message.from()

    const mentionSelf = await message.mentionSelf()

    const text = message.text()

    let intro = 'Jason,爱好广泛,广交天下豪杰,上得了九天摘月,下得了五洋捉鳖,俗话说的好,不会烘培的飞行员不是好户外人,不会玩音乐的水族爱好者不是好厨师,不会画画的极限爱好者不是好程序员,这就是我的老板Jason,吼吼吼~~'

    if (room !== null && mentionSelf)

      if (/jason|你老板|你上司/.test(text))

        await room.say(intro)

        await room.say(new UrlLink(

            description: '户外贱客 & Fighting,fighting,finghting and finghting,读万卷书,行万里路,学习AND吃,喝,玩,乐',

            thumbnailUrl: '',

            title: 'Jason',

            url: 'http://mp.weixin.qq.com/s?__biz=MzkxODE3MjAyNQ==&mid=100000001&idx=1&sn=d05de320c6fbe6c9f9149a09a4da81ec&chksm=41b4391776c3b001c143ac2c284c58ac8b08de41d95cab682aa5a07022e32096567f5780d5be#rd',

          ))

        return true

      else if (/户外贱客/.test(text))

        await room.say(new UrlLink(

            description: '户外贱客 & Fighting,fighting,finghting and finghting,读万卷书,行万里路,学习AND吃,喝,玩,乐',

            thumbnailUrl: '',

            title: 'Jason',

            url: 'http://mp.weixin.qq.com/s?__biz=MzkxODE3MjAyNQ==&mid=100000001&idx=1&sn=d05de320c6fbe6c9f9149a09a4da81ec&chksm=41b4391776c3b001c143ac2c284c58ac8b08de41d95cab682aa5a07022e32096567f5780d5be#rd',

          ))

        return true

     

   

    return false



// 登录

async function onLogin(user)

  console.log(`贴心小助理$user登录了`)

  // 登陆后创建定时任务

  await initDay()



bot.on('login', onLogin)

bot.start()

  .then(() => log.info('StarterBot', 'Starter Bot Started.'))

  .catch(e => log.error('StarterBot', e))

```

### 2.创建schedule定时函数

```typescript

import schedule from 'node-schedule'

// date 参数

//其他规则见 https://www.npmjs.com/package/node-schedule

// 规则参数讲解    *代表通配符

//

// *  *  *  *  *  *

// ┬ ┬ ┬ ┬ ┬ ┬

// │ │ │ │ │  |

// │ │ │ │ │ └ 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)

// 每分钟的第30秒触发: '30 * * * * *'

//

// 每小时的1分30秒触发 :'30 1 * * * *'

//

// 每天的凌晨1点1分30秒触发 :'30 1 1 * * *'

//

// 每月的1日1点1分30秒触发 :'30 1 1 1 * *'

//

// 每周1的1点1分30秒触发 :'30 1 1 * * 1'

function setSchedule(date,callback)

  schedule.scheduleJob(date, callback)



export function setSchedule()

```

### 3.创建几个功能函数,爬取ONE网站的每日一句,提取通过API获取的消息

```typescript

import * as cheerio from 'cheerio'

import * as superagent from 'superagent'

const ONE = 'http://wufazhuce.com/' // ONE的web版网站

const TXHOST = 'http://api.tianapi.com/txapi/' // 天行host

function req(url,method, params, data, cookies)

  return new Promise(function (resolve,reject)

    superagent(method, url)

      .query(params)

      .send(data)

      .set('Content-Type','application/x-www-form-urlencoded')

      .end(function (err, response)

        if (err)

        reject(err)

       

        resolve(response)

      )

    )



async function getOne()

  // 获取每日一句

  try

    let res = await req(ONE, 'GET')

    let $ = cheerio.load(res.text)

    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

 



async function getTXweather()

  // 获取天行天气

  let url = TXHOST + 'tianqi/'

  try

    let res = await req(url, 'GET',

      key: '你自己的KEY',//需要自己去天行申请,地址https://www.tianapi.com/signup.html?source=474284281

      city: 'Arlington'

    )

    let content = JSON.parse(res.text)

    if (content.code === 200)

      let todayInfo = content.newslist[0]

      let obj =

        weatherTips: todayInfo.tips,

        todayWeather:`阿林顿今天$todayInfo.weather\n温度:$todayInfo.lowest/$todayInfo.highest

        \n$todayInfo.wind风: $todayInfo.windspeed\n紫外线指数:$todayInfo.uv_index\n湿度

        $todayInfo.humidity`

      ;

      console.log('获取天行天气成功', obj)

      return obj

    else

      console.log('获取接口失败', content.code)

   

  catch (err)

    console.log('获取接口失败', err)

 



async function getSweetWord()

  // 获取土味情话

  let url = TXHOST + 'saylove/'

  try

    let res = await req(url, 'GET', key: '' )

    let content = JSON.parse(res.text)

    if (content.code === 200)

      let sweet = content.newslist[0].content

      let str = sweet.replace('\r\n', '<br>')

      return str

    else

      console.log('获取接口失败', content.msg)

   

  catch (err)

    console.log('获取接口失败', err)

 



export getOne, getTXweather, getSweetWord,

```

### 计算距离某日(生日,结婚纪念日等)还有多少天

```typescript

function getDay(date)

  var date2 = new Date()

  var date1 = new Date(date)

  var iDays = parseInt(

    Math.abs(date2.getTime() - date1.getTime()) / 1000 / 60 / 60 / 24

  )

  return iDays



function formatDate(date)

  var tempDate = new Date(date)

  var year = tempDate.getFullYear()

  var month = tempDate.getMonth() + 1

  var day = tempDate.getDate()

  var hour = tempDate.getHours()

  var min = tempDate.getMinutes()

  var second = tempDate.getSeconds()

  var week = tempDate.getDay()

  var str = ''

  if (week === 0)

    str = '星期日'

  else if (week === 1)

    str = '星期一'

  else if (week === 2)

    str = '星期二'

  else if (week === 3)

    str = '星期三'

  else if (week === 4)

    str = '星期四'

  else if (week === 5)

    str = '星期五'

  else if (week === 6)

    str = '星期六'

 

  if (hour < 10)

    hour = '0' + hour

 

  if (min < 10)

    min = '0' + min

 

  if (second < 10)

    second = '0' + second

 

  return year + '-' + month + '-' + day + '日 ' + hour + ':' + min + ' ' + str



export getDay, formatDate

```

![关键字触发消息](https://wechaty.js.org/assets/2020/daily-message-and-chatbot/keyword-push.png)

![无法回答推送名片](https://wechaty.js.org/assets/2020/daily-message-and-chatbot/push-contact.png)

![定时推送消息](https://wechaty.js.org/assets/2020/daily-message-and-chatbot/daily-message.png)

![智能聊天](https://wechaty.js.org/assets/2020/daily-message-and-chatbot/talk-to-bot.png)

## 后记

到此已经实现了私人人助理和定时推送消息的功能([项目地址](https://github.com/jasonlovesharon/my_bot)),由于对Typescript不熟,很多功能都是借鉴很多大神的轮子实现的,还是对Python熟悉点,下步准备用Python来实现以上功能,并进一步拓展更多有趣的功能。

我开发了一个女朋友陪聊系统!全天24小时推送问候,自动回复女友的微信消息

一名名叫李恺祥的软件开发工程师发了一条动态,没想到自己火的如此之快。

起因是因为工作忙,老是不能及时回复女友的消息,于是就写了一段程序,这段程序可以:

【全天24小时推送问候,自动回复女友的微信消息】

具体效果是这样的:


 

看到没,程序员要是急了,自己绿自己。

1

正当这名程序员在社交平台,晒出自己的战绩的时候,被女朋友抓了一个现行:


 

喂狗粮这事儿咱就不说了,程序员的女朋友居然是产品,这就好比是灰太狼娶了美羊羊,杰瑞和汤姆握手言和一样不可思议。

产品和开发,这一对天敌,居然能成为恋人?

这种现象并不稀奇,甚至是一种常态,比方说吐槽大会的庞博,他也是一名程序员,老婆同样是产品经理。

孙子说:“不战而屈人之兵,善之善者也”,依我看,“把敌人变成朋友”,可比不战屈人之兵的境界高多了。

是什么原因,让开发和产品走上了爱的殿堂呢?

直到我回忆起了前段时间,闹得沸沸扬扬的“根据手机壳改变主题颜色,产品和程序员打架”的新闻,才发现了问题。


 

用一句话总结就是:“一山不容二虎,除非一公和一母。”

在这里强烈建议,所有公司在招聘开发和产品的时候,一定要男女搭配,而且要极力撮合产品和开发。

在爱情的滋润下,他们就不容易打起来。如果还是发生了怎么办?

不用担心,他们不敢的,因为根据我国刑法规定,家暴情节严重的,可以入刑。


 

谁说产品开发是天敌?其实我们是水和鱼!

谁说我们冰与火?我们是蜜蜂和花朵!

谁说针尖对麦芒?我们是织女和牛郎!

谁说一见就不高兴?我们是潘金莲和西门庆!

 

2

回头,再来说说这个“自动回复女朋友消息”的程序,聊天哄女朋友虽好,但有一个问题欠考虑了,要是女朋友发来语音,这可咋办?

不同的人,有不同的解决方式。

刚入行的程序员在想:“回复‘对不起,识别不了该内容’就好了”

初级程序员在想:“弄个语音转文字功能上去。”

中级程序员在想:“语音转文字要加上去,而且要放5条内容进去,随机回复。”

高级程序员在想:“识别出语音后,回复‘嘘!工作时间语音不方便,打字聊’。”

高手不在于技术水平多高,而在于解决问题的能力。


 

当大师兄也在想这个问题的时候,突然想到一个细思极恐的问题。

对面的女朋友,要是也使用了聊天机器人……


 

这是十分有可能的,因为作者已经把源码开放了出来。

换句话说:女朋友太多,工作太忙,不用烦恼不忧伤,不怕被抓不用藏,爬虫脚本帮你忙。

不管你是转行也好,初学也罢,进阶也可,如果你想学编程,进阶程序员~

【值得关注】我的 编程学习交流俱乐部 !【点击进入】

C语言入门资料(网盘链接免费分享):


 

C语言推荐书籍(PDF免费分享):


 

以上是关于基于wechaty的定时消息推送(可以哄女朋友)、智能聊天和私人助理的主要内容,如果未能解决你的问题,请参考以下文章

当知道前男友交女友后,我用Python15行代码每天定时免费发送暧昧手机短信推送消息,结果......

如何哄女朋友开心(转)

微信公众号 模板消息 定时推送 java

巧用钉钉群机器人定时推送单图文消息

微星极光公众号激活宝——微信公众号48小时内无限制定时推送消息

哄女朋友利器 —— 赶紧对她说我爱你,程序猿的专属浪漫(附源码)