wechatBot
微信每日說,每日自動發送微信消息給你心愛的人
項目介紹
靈感來源
在掘金看到了一篇《用Node + EJS寫一個爬蟲腳本每天定時女朋友發一封暖心郵件》後,
在評論區偶然看到一位讀者說可不可以用微信實作一下。然後最近剛好在做微信機器人的小項目,那就把這個定時任務放到微信上去做吧,說幹就幹,撸了一下午終于撸出來了。
項目位址
github:https://github.com/gengchen528/wechatBot
使用庫
- wechaty - 微信操作
- node-schedule - 定時任務
- superagent - 爬取頁面資訊
- cheerio - 抓取頁面
- qrcode-terminal - 終端顯示二維碼
功能
- 定時給朋友發送每日天氣提醒以及每日一句
- 根據關鍵詞自動加好友和自動拉群功能
- 後續繼續擴充吧...(你有好的想法也可以提pr)
資料來源
- 每日一句和上面的大佬一樣也是來自one
- 天氣資訊來自墨迹天氣
定時任務
node-schedule非你莫屬了,
可以定時每個月、每個禮拜、每天具體什麼時候執行什麼任務
實作效果
由于是微信定時發送消息,較郵件來說,微信無法把圖檔和文字放在同一消息框中,是以美觀度來說可能沒有郵件好,不過文字進行排版後還是可以的,由于時間倉促,是以文字比較少,後續會繼續增加内容;
代碼說明
目錄結構
- config: 存放公共變量和superagent的配置
- schedule: 任務排程的配置
- superagent: 擷取每日一句和天氣資訊
- untils: 抽取的共用方法
核心代碼
index.js
關于微信的登入,定時任務的建立,發送資訊的擷取都在這個檔案裡
/**
* WechatBot
* - https://github.com/gengchen528/wechatBot
*/
const {Wechaty,Friendship} = require(\'wechaty\')
const schedule = require(\'./schedule/index\')
const config = require(\'./config/index\')
const untils = require(\'./untils/index\')
const superagent = require(\'./superagent/index\')
const {FileBox} = require(\'file-box\') //檔案讀取子產品
// 二維碼生成
function onScan (qrcode, status) {
require(\'qrcode-terminal\').generate(qrcode) // 在console端顯示二維碼
const qrcodeImageUrl = [
\'https://api.qrserver.com/v1/create-qr-code/?data=\',
encodeURIComponent(qrcode),
].join(\'\')
console.log(qrcodeImageUrl)
}
// 登入
async function onLogin (user) {
console.log(`貼心小助理${user}登入了`)
// 登陸後建立定時任務
schedule.setSchedule(config.SENDDATE,()=>{
console.log(\'你的貼心小助理開始工作啦!\')
main()
})
}
//登出
function onLogout(user) {
console.log(`${user} 登出`)
}
// 監聽對話 根據關鍵詞自動加群
async function onMessage (msg) {
const contact = msg.from() // 發消息人
const content = msg.text() //消息内容
const room = msg.room() //是否是群消息
const roomCodeUrl = FileBox.fromUrl(config.ROOMCODEURL) //來自url的檔案
const roomCodeLocal = FileBox.fromFile(config.ROOMLOCALPATH) //添加本地檔案
if (msg.self()) {
return
}
if(room){ // 如果是群消息
const topic = await room.topic()
console.log(`群名: ${topic} 發消息人: ${contact.name()} 内容: ${content}`)
}else { // 如果非群消息
console.log(`發消息人: ${contact.name()} 消息内容: ${content}`)
let addRoomReg = eval(config.ADDROOMWORD)
let roomReg = eval(config.ROOMNAME)
if(addRoomReg.test(content)&&!room){
let keyRoom = await this.Room.find({topic: roomReg})
if(keyRoom){
try{
await contact.say(roomCodeLocal||roomCodeUrl)
await keyRoom.say(\'微信每日說:歡迎新朋友\', contact)
}catch (e) {
console.error(e)
}
}
}else {
await contact.say(\'你好,不要輕易調戲我,我隻會發群二維碼,不會聊天的!\')
await contact.say(\'請回複暗号:加群 擷取群二維碼圖檔\')
}
}
}
// 自動加好友功能
async function onFriendShip(friendship) {
let logMsg
try {
logMsg = \'添加好友\' + friendship.contact().name()
console.log(logMsg)
switch (friendship.type()) {
/**
*
* 1. New Friend Request
*
* when request is set, we can get verify message from `request.hello`,
* and accept this request by `request.accept()`
*/
case Friendship.Type.Receive:
let addFriendReg = eval(config.ADDFRIENDWORD)
if (addFriendReg.test(friendship.hello())) {
logMsg = \'自動添加好友,因為驗證資訊中帶關鍵字‘每日說’\'
await friendship.accept()
} else {
logMsg = \'沒有通過驗證 \' + friendship.hello()
}
break
/**
*
* 2. Friend Ship Confirmed
*
*/
case Friendship.Type.Confirm:
logMsg = \'friend ship confirmed with \' + friendship.contact().name()
break
}
} catch (e) {
logMsg = e.message
}
console.log(logMsg)
}
// 自動發消息功能
async function main() {
let contact = await bot.Contact.find({name:config.NICKNAME}) || await bot.Contact.find({alias:config.NAME}) // 擷取你要發送的聯系人
let one = await superagent.getOne() //擷取每日一句
let weather = await superagent.getWeather() //擷取天氣資訊
let today = await untils.formatDate(new Date())//擷取今天的日期
let memorialDay = untils.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 bot = new Wechaty()
bot.on(\'scan\', onScan)
bot.on(\'login\', onLogin)
bot.on(\'logout\', onLogout)
bot.on(\'message\', onMessage)
bot.on(\'friendship\', onFriendShip)
bot.start()
.then(() => console.log(\'開始登陸微信\'))
.catch(e => console.error(e))
superagent/index.js
const superagent = require(\'../config/superagent\')
const config = require(\'../config/index\')
const cheerio = require(\'cheerio\')
async function getOne() { // 擷取每日一句
let res = await superagent.req(config.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;
}
async function getWeather() { //擷取墨迹天氣
let url = config.MOJI_HOST+config.CITY+\'/\'+config.LOCATION
let res = await superagent.req(url,\'GET\')
let $ = cheerio.load(res.text)
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
}
module.exports ={
getOne,getWeather
}
項目運作
由于需要安裝chromium, 是以要先配置一下鏡像,注意由于wechaty的限制,最好使用node10以上版本
npm
npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist
npm config set puppeteer_download_host https://npm.taobao.org/mirrors
yarn
yarn config set registry https://registry.npm.taobao.org
yarn config set disturl https://npm.taobao.org/dist
yarn config set puppeteer_download_host https://npm.taobao.org/mirrors
然後進行項目安裝
git clone [email protected]:gengchen528/wechatBot.git
cd wechatBot
npm install 或 cnpm install
參數配置
wechatBot/config/index.js
// 配置檔案
module.exports ={
// 基礎定時發送功能配置項(必填項)
NAME:\'A兔子\',//備注姓名
NICKNAME:\'嗯哼\', //昵稱
MEMORIAL_DAY:\'2015/04/18\', //你和收信者的紀念日
CITY:\'shanghai\',//收信者所在城市
LOCATION:\'pudong-new-district\',//收信者所在區 (可以通路墨迹天氣網站後,查詢區的英文拼寫)
SENDDATE:\'0 0 8 * * *\',//定時發送時間 每天8點0分0秒發送,規則見 /schedule/index.js
ONE:\'http://wufazhuce.com/\',////ONE的web版網站
MOJI_HOST:\'https://tianqi.moji.com/weather/china/\', //中國墨迹天氣url
//進階功能配置項(非必填項)
AUTOADDFRIEND:false,//自動加好友功能 預設關閉
AUTOADDROOM:false,//自動拉群功能 預設關閉
AUTOREPLY:false,//自動聊天功能 預設關閉
AIBOTAPI:\'http://www.tuling123.com/openapi/api\',//圖靈機器人API 注冊位址http://www.turingapi.com/
APIKEY:\'你的圖靈機器人apikey\',//圖靈機器人apikey
ROOMNAME:\'/^你的群名/i\', //群名(請隻修改中文,不要删除符号,這是正則)
ADDFRIENDWORD:\'/你要觸發的關鍵詞/i\',//自動加好友觸發的關鍵詞(請隻修改中文,不要删除符号,這是正則)
ADDROOMWORD:\'/加群/\',//自動發送群圖檔觸發關鍵詞(請隻修改中文,不要删除符号,這是正則)
ROOMCODEURL:\'http://image.bloggeng.com/qun.png\',//群二維碼url連結(與本地群二維碼路徑選填一個)
ROOMLOCALPATH:\'./static/qun.png\',//本地群二維碼圖檔路徑(與群url選填一個)
}
開始運作
npm run start
然後掏出你的手機,最好使用小号,掃描控制台的二維碼即可
待解決問題
- 由于微信登入和郵件登入不同,是以無法使用程序守護工具,目前沒有測試是否能夠長時間登入(目前已經解決,第一次需要使用node啟動,生成狀态維持檔案,生成後即可使用pm2等程序守護工具)
- 因為node的原因,如果發生錯誤,可能會導緻任務無法進行,需要手動重新開機并登入(已解決)
- 最好能夠使用小号登入,如果是常用微信登入,在電腦用戶端登陸後可能會wechaty擠掉
- 墨迹天氣頁面在擷取的時候可能會存在延時,有時可能擷取不到
後續功能
- 為了防止占用你的微信号,你和你的夫妻添加我的微信後。你發送指定内容,我将會每天幫你發送消息(已實作)
- 添加了圖靈機器人聊天功能(已實作)
- 日常定時小提醒功能 (已實作https://github.com/gengchen528/wechat-assistant)
- 還有在思考中...(你有好的想法也可以提出來)
最後
因為給這個微信加了自動加好友和拉群功能,是以有興趣的小夥伴可以加我的微信進行測試,記得在加好友的時候帶上暗号:
微信每日說
,加好友後發送
加群
,會自動發送群的二維碼;
注意 加好友請在驗證中填寫
微信每日說
才可以自動加好友
趕快親自試一試吧,相信你會挖掘出更多好玩的功能
github:https://github.com/gengchen528/wechatBot
另外我的公衆号已經接入微軟小冰,關注後發語音會有小姐姐的聲音陪你聊天,也可以和她文字聊天,有興趣可以試試看,單身的歡迎來撩