日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用koa2+wechaty打造个人微信小秘书

發布時間:2023/12/8 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用koa2+wechaty打造个人微信小秘书 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

開篇連連問?

  • 你是不是有閑置的微信號?
  • 你想不想有個小秘書定時提醒你將要做的事情?
  • 你是否為忘記一些紀念日而懊惱?
  • 你是否加班到很晚,而忘記了今天和別人有約?
  • 你是不是下班還記得拿快遞,到家后才發現忘記了?
  • 你是不是想學習一下如何做一個微信小秘書?

如果以上問題你有一條符合的話,那就可以安心讀下去了,因為微信小秘書可以幫你解決大部分的問題。當然沒有符合的話,也可以繼續讀下去,因為既然來了就說明你還是有興趣的?。

當然小秘書不符合你要求的話《用Node+wechaty寫一個爬蟲腳本每天定時給女(男)朋友發微信暖心話》也可以看一下奧!

技術棧

node: 建議最新穩定版,由于wechaty依賴,所以至少node > 10以上版本
Koa: web開發框架,用來編寫服務端應用程序

MongoDB:非關系數據庫

mongoose:連接 mongodb的一個庫

wechaty:提供網頁版微信相關操作api接口

node-schedule - 定時任務

項目地址

github:https://github.com/gengchen528/wechat-assistant

功能

很聽你話的私人小秘書,幫你創建定時任務,每日提醒,紀念日提醒,當日提醒

文字支持格式:(關鍵詞之間需要用空格分開,特別是昵稱和時間要分隔開才行的,時間是24小時制,暫時還不支持表情?)

  • “提醒 我 18:30 快要下班了,準備一下,不要忘記帶東西” (當天指定時間提醒)
  • “提醒 其他人昵稱 2019-09-10 10:00 工作再忙,也要記得喝水”(委托小秘書提醒其他人)
  • “提醒 我 每天 8:00 出門記得帶鑰匙,公交卡還有飯盒”(每日指定時間提醒)
  • “提醒 wo 2019-09-10 10:00 還有兩天就是女朋友的生日,要提前準備一下” (指定日期時間提醒)

效果圖如下:

提醒自己

委托提醒(前提是你和你想要提醒的人都是小秘書的好友,采用的是昵稱查找用戶,不是備注要注意)

數據庫中已添加任務

準備工作

由于本項目使用了MongoDB數據庫,所以需要在電腦或服務器中自行安裝,這里就不在贅述安裝過程啦,不懂怎么安裝的小伙伴可以戳鏈接,MongoDB的可視化工具,我在Mac上使用的是mongobooster,有需要的小伙伴可以去下載一下。

代碼說明

目錄結構

  • config: koa,定時任務器,superagent的配置目錄
  • mongodb: mongodb連接相關配置文件,schema設計與model的主要目錄
  • untils: 抽取的共用方法

wechaty核心代碼

index.js

微信登錄,定時任務初始化,小秘書具體實現的主要文件。接口getScheduleList在每次登陸后會從數據庫拉取未執行的定時任務并進行初始化,防止意外掉線后無法恢復定時任務。同時每次設置定時任務,接口addSchedule會直接向數據庫中插入一條任務記錄并把任務添加到定時任務列表中。每次任務執行完畢后,接口updateSchedule都會更新數據庫中指定任務的狀態,防止任務重復執行。

const { Wechaty, Friendship } = require('wechaty') const schedule = require('./config/schedule') const { FileBox } = require('file-box') const Qrterminal = require('qrcode-terminal') const { request } = require('./config/superagent') const untils = require('./untils/index') const host = 'http://127.0.0.1:3008/api'// 每次登錄初始化定時任務 initSchedule = async(list) => {try {for (item of list) {let time = item.isLoop ? item.time : new Date(item.time)schedule.setSchedule(time, async() => {let contact = await bot.Contact.find({ name: item.subscribe })console.log('你的專屬提醒開啟啦!')await contact.say(item.content)if (!item.isLoop) {request(host + '/updateSchedule', 'POST', '', { id: item._id }).then((result) => {console.log('更新定時任務成功')}).catch(err => {console.log('更新錯誤', err)})}})}} catch (err) {console.log('初始化定時任務失敗', err)} }// 二維碼生成 onScan = (qrcode, status) => {Qrterminal.generate(qrcode)const qrImgUrl = ['https://api.qrserver.com/v1/create-qr-code/?data=', encodeURIComponent(qrcode)].join('')console.log(qrImgUrl) }// 登錄事件 onLogin = async(user) => {console.log(`貼心助理${user}登錄了`)request(host + '/getScheduleList', 'GET').then((res) => {let text = JSON.parse(res.text)let scheduleList = text.dataconsole.log('定時任務列表', scheduleList)initSchedule(scheduleList)}).catch(err => {console.log('獲取任務列表錯誤', err)}) }// 登出事件 onLogout = (user) => {console.log(`${user} 登出了`) }// 消息監聽 onMessage = async(msg) => {const contact = msg.from()const content = msg.text()const room = msg.room()if (msg.self()) returnif (room) {const roomName = await room.topiac()console.log(`群名: ${roomName} 發消息人: ${contact.name()} 內容: ${content}`)} else {console.log(`發消息人: ${contact.name()} 消息內容: ${content}`)let keywordArray = content.replace(/\s+/g, ' ').split(" ") // 把多個空格替換成一個空格,并使用空格作為標記,拆分關鍵詞console.log("分詞后效果", keywordArray)if (keywordArray[0] === "提醒") {let scheduleObj = untils.contentDistinguish(contact, keywordArray)addSchedule(scheduleObj)contact.say('小助手已經把你的提醒牢記在小本本上了')} else {contact.say('很高興你能和我聊天,來試試我的新功能吧!回復案例:“提醒 我 18:30 下班回家”,創建你的專屬提醒,記得關鍵詞之間使用空格分隔開')}} }// 添加定時提醒 addSchedule = async(obj) => {request(host + '/addSchedule', 'POST', '', obj).then(async(res) => {res = JSON.parse(res.text)let nickName = res.data.subscribelet time = res.data.timelet Rule1 = res.data.isLoop ? time : new Date(time)let content = res.data.contentlet contact = await bot.Contact.find({ name: nickName })schedule.setSchedule(Rule1, async() => {console.log('你的專屬提醒開啟啦!')await contact.say(content)if (!res.isLoop) {request(host + '/updateSchedule', 'POST', '', { id: res.data._id }).then((result) => {console.log('更新定時任務成功')}).catch(err => {console.log('更新錯誤', err)})}})}).catch(err => {console.log('錯誤', err)}) }// 自動加好友 onFriendShip = async(friendship) => {let logMsgtry {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:await friendship.accept()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) } const bot = new Wechaty({ name: 'WechatEveryDay' }) 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))

untils/index.js

這里主要是輸入關鍵詞后的處理方法,在index.js中,我把用戶輸入的關鍵詞根據空格來進行分詞處理,放到一個數組中,然后傳入contentDistinguish()方法中。根據關鍵詞的不同來進行處理是否是屬于每日任務,當日定時任務,還是屬于指定日期任。因為不同的定時任務類型,在時間格式上是有所區分的,每日任務我采用的是Cron風格定時器,類似0 30 8 * * *(每天8點30提醒)這種,而指定日期時間和當日任務我使用的是new Date('2019-9-10 12:30:00')來處理。
同時為了兼容性,在日期處理上采用了全角替換半角的冒號格式,內容上為了更符合秘書的身份,將主語我全部替換成你,也處理了自己給自己創建定時任務與你給別人創建定時任務內容上的不同。

getToday = () => { // 獲取今天日期const date = new Date()let year = date.getFullYear()let month = date.getMonth() + 1let day = date.getDate()return year + '-' + month + '-' + day + ' ' }convertTime = (time) => { // 轉換定時格式let array = time.split(':')return "0 " + array[1] + ' ' + array[0] + ' * * *' }contentDistinguish = (contact, keywordArray) => {let scheduleObj = {}let today = getToday()scheduleObj.setter = contact.name() // 設置定時任務的用戶scheduleObj.subscribe = (keywordArray[1] === "我") ? contact.name() : keywordArray[1] // 定時任務接收者if (keywordArray[2] === "每天") { // 判斷是否屬于循環任務console.log('已設置每日定時任務')scheduleObj.isLoop = truescheduleObj.time = convertTime(keywordArray[3])scheduleObj.content = (scheduleObj.setter === scheduleObj.subscribe) ? scheduleObj.content = "親愛的" + scheduleObj.subscribe + ",溫馨提醒:" + keywordArray[4].replace('我', '你') : "親愛的" + scheduleObj.subscribe + "," + scheduleObj.setter + "委托我提醒你," + keywordArray[4].replace('我', '你')} else if (keywordArray[2] && keywordArray[2].indexOf('-') > -1) {console.log('已設置指定日期時間任務')scheduleObj.isLoop = falsescheduleObj.time = keywordArray[2] + ' ' + keywordArray[3].replace(':', ':')scheduleObj.content = (scheduleObj.setter === scheduleObj.subscribe) ? scheduleObj.content = "親愛的" + scheduleObj.subscribe + ",溫馨提醒:" + keywordArray[4].replace('我', '你') : "親愛的" + scheduleObj.subscribe + "," + scheduleObj.setter + "委托我提醒你," + keywordArray[4].replace('我', '你')} else {console.log('已設置當天任務')scheduleObj.isLoop = falsescheduleObj.time = today + keywordArray[2].replace(':', ':')scheduleObj.content = (scheduleObj.setter === scheduleObj.subscribe) ? scheduleObj.content = "親愛的" + scheduleObj.subscribe + ",溫馨提醒:" + keywordArray[3].replace('我', '你') : "親愛的" + scheduleObj.subscribe + "," + scheduleObj.setter + "委托我提醒你," + keywordArray[3].replace('我', '你')}return scheduleObj } module.exports = {getToday,convertTime,contentDistinguish }

koa核心代碼

koa就不用多說了,TJ大神繼express后的又一神作,很輕量,而且擺脫了“回調地獄”的問題,放一張大神頭像鎮樓(發型很帥啊,哈哈)

koa服務默認使用3008端口,如果修改的話,需要在index.js中修改host的地址。這里目前寫了三個接口,分別是添加定時任務,獲取定時任務列表和更新任務列表,對應的數據庫curd操作均在mongodb/model.js中完成

config/koa.js

const Koa = require("koa") const Router = require("koa-router") const bodyParser = require('koa-bodyparser') const model = require("../mongodb/model")const app = new Koa() const router = new Router() app.use(bodyParser())router.post('/api/addSchedule', async(ctx, next) => { // 添加定時任務let body = ctx.request.body;console.log('接收參數', body)let res = await model.insert(body);ctx.body = { code: 200, msg: "ok", data: res }next() })router.get('/api/getScheduleList', async(ctx, next) => { // 獲取定時任務列表const condition = { hasExpired: false }let res = await model.find(condition)ctx.response.status = 200;ctx.body = { code: 200, msg: "ok", data: res }next() }) router.post('/api/updateSchedule', async(ctx, next) => { // 更新定時任務const condition = { _id: ctx.request.body.id }let res = await model.update(condition)ctx.response.status = 200;ctx.body = { code: 200, msg: "ok", data: res }next() })const handler = async(ctx, next) => {try {await next();} catch (err) {ctx.respose.status = err.statusCode || err.status || 500;ctx.response.type = 'html';ctx.response.body = '<p>出錯啦</p>';ctx.app.emit('error', err, ctx);} }app.use(handler) app.on('error', (err) => {console.error('server error:', err) })app.use(router.routes()) app.use(router.allowedMethods()) app.listen(3008, () => {console.log('[demo] route-use-middleware is starting at port 3008') })

mongose核心代碼

mongodb/config.js

這里主要是MongoDB的主要配置文件,使用了mongoose鏈接MongoDB數據庫,默認端口27017,創建了一個名為wechatAssitant的庫

const mongoose = require("mongoose")const db_url = 'mongodb://localhost:27017/wechatAssitant' let db = mongoose.connect(db_url, { useNewUrlParser: true })//連接成功 mongoose.connection.on('connect', () => {console.log("Mongoose connection open to " + db_url) })//連接異常 mongoose.connection.on('error', (err) => {console.log("Mongoose connection erro " + err); });//連接斷開 mongoose.connection.on('disconnected', () => {console.log("Mongoose connection disconnected "); });module.exports = mongoose

mongodb/schema.js

在Mongoose里一切都是從Schema開始的,每一個Schema都會映射到MongoDB的一個collection上。Schema定義了collection里documents的模板(或者說是框架),如下代碼定義了定時任務的Schema:

const mongoose = require('./config') const Schema = mongoose.Schemalet assistant = new Schema({subscribe: String, // 訂閱者setter: String, // 設定任務者content: String, // 訂閱內容time: String, // 定時日期isLoop: Boolean, // 是否為循環定時任務hasExpired: { type: Boolean, default: false }, // 判斷任務是否過期createdAt: { type: Date, default: Date.now }, })module.exports = mongoose.model('Assistant', assistant)

mongodb/model.js

為了使用定義好的Schema,我們需要把Schema轉換成我們可以使用的model(其實是把Schema編譯成model,所以對于Schema的一切定義都要在compile之前完成)。也就是說model才是我們可以進行操作的handle,具體實現代碼mongoose.model('Assistant', assistant),這里我們已經在schema.js文件中直接導出,直接在model.js中引用

const Assistant = require('./schema')module.exports = {insert: (conditions) => { // 添加定時任務return new Promise((resolve, reject) => {Assistant.create(conditions, (err, doc) => {if (err) return reject(err)console.log('創建成功', doc)return resolve(doc)})})},find: (conditions) => { // 獲取定時任務列表return new Promise((resolve, reject) => {Assistant.find(conditions, (err, doc) => {if (err) return reject(err)return resolve(doc)})})},update: (conditions) => { // 更新定時任務狀態return new Promise((resolve, reject) => {Assistant.updateOne(conditions, { hasExpired: true }, (err, doc) => {if (err) return reject(err)return resolve(doc)})})} }

項目運行

由于需要安裝chromium,所以要先配置一下鏡像,注意由于wechaty的限制,必須使用node10以上版本

npm或者yarn 配置淘寶源

(很重要,防止下載chromium失敗,因為下載文件在150M左右,所以在執行npm run start后需要等待下載大概一兩分鐘以上,請耐心等待)
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 git@github.com:gengchen528/wechat-assistant.git cd wechat-assistant.git npm install npm run start

掃描登錄

用微信掃描控制臺顯示的二維碼,在手機上同意登錄即可。使用其他微信發送指定格式文字進行添加定時任務。

服務器部署

1、如果需要在服務器中部署,需要先掃描二維碼登錄一次,生成微信維持登錄狀態的json文件,如下圖:


2、生成此文件后,可以使用pm2工具進行進程守護。由于為了方便,本地開發的時候,我設置的npm run start同時執行了兩條命令,所以在服務器端部署的時候,建議先啟動koa.js后再啟動index.js

常見問題

  • 我的微信號無法登陸

    從2017年6月下旬開始,使用基于web版微信接入方案存在大概率的被限制登陸的可能性。 主要表現為:無法登陸Web 微信,但不影響手機等其他平臺。 驗證是否被限制登陸: https://wx.qq.com 上掃碼查看是否能登陸。 更多內容詳見:

    Can not login with error message: 當前登錄環境異常。為了你的帳號安全,暫時不能登錄web微信。

    [謠言] 微信將會關閉網頁版本

    新注冊的微信號無法登陸

  • 執行npm run start時無法安裝puppet-puppeteer&&Chromium

    • Centos7下部署出現以下問題

      問題原因:https://segmentfault.com/a/1190000011382062

      解決方案:

      #依賴庫yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y#字體yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y
    • windows下,下載puppeteer失敗

      鏈接:https://pan.baidu.com/s/1YF09nELpO-4KZh3D2nAOhA
      提取碼:0mrz

      把下載的文件放到如下圖路徑,并解壓到當前文件夾中即可

  • 支持 紅包、轉賬、朋友圈… 嗎

    支付相關 - 紅包、轉賬、收款 等都不支持

  • 更多關于wechaty功能相關接口

    參考wechaty官網文檔

  • 其他問題解決方案

    • 本地是否安裝了mongodb數據庫
    • 先檢查node版本是否大于10
    • 確認npm或yarn已經配置好淘寶源
    • 存在package-lock.json文件先刪除
    • 刪除node_modules后重新執行npm install 或cnpm install
  • 注意

    本項目屬于個人興趣開發,開源出來是為了技術交流,請勿使用此項目做違反微信規定或者其他違法事情。
    建議使用小號進行測試,有被微信封禁網頁端登錄權限的風險(客戶端不受影響),請確保自愿使用。

    最后

    我的小秘書已經學會了自動加好友功能,所以有興趣的小伙伴可以加我的微信進行測試,她也可以是你的私人小秘書?(注意別發太多信息,會把她玩壞的)

    趕快親自試一試吧,相信你會挖掘出更多好玩的功能

    github:https://github.com/gengchen528/wechat-assistant

    另外我的公眾號已經接入微軟小冰,關注后發語音會有小姐姐的聲音陪你聊天,也可以和她文字聊天,有興趣可以試試看,單身的歡迎來撩

    總結

    以上是生活随笔為你收集整理的使用koa2+wechaty打造个人微信小秘书的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。