李成熙,Shopee Airpay 前端 Leader。2014年畢業加入騰訊AlloyTeam,前後負責過QQ羣、花樣直播、騰訊文檔等項目。後於2018年加入騰訊云云開發團隊。專一於性能優化、工程化和小程序服務。微博 | 知乎 | Github前端
到了新公司以後,發現竟然也是用企業微信。但惋惜的是,外部的企業微信竟然沒有機器人。這對之前在鵝廠裏習慣用企業微信作提醒的我以爲很不方便。終於,7月一開始企業微信終於上線機器人功能。node
右擊羣聊天卡片,能夠添加羣機器人。python
懸浮在機器人的頭像上,會顯示出 Webhook 地址。點擊這個地址,會跳到機器人的開發文檔。ios
提醒機器人的開發其實很簡單,其實就是向這個webhook地址,按文檔提供的格式發送請求,就能夠實現消息推送了。最簡單的示例,能夠用 Node.js
的 axios
類庫:git
const axios = require('axios')
async function bookLunch() {
let result = await axios.post(baseUrl, {
msgtype: 'text',
text: {
content: '大佬,訂午飯啦!',
mentioned_list: ['@all'] // 可使用郵箱或者手機號碼
}
})
return result.data
}
bookLunch.then((res) => {
console.log(res)
})
複製代碼
以上是最簡單的例子。除了普通文本內容,還能夠發送 markdown
,圖文等內容,你們能夠自行去看文檔。github
但問題來了:通常來講提醒,都是須要定時的,好比說每早提醒你們寫計劃,每週五傍晚提醒你們寫週報,怎麼可讓機器人在這些時間點出現提醒你們呢?你可能會想到買一臺服務器,而後在上面部署 cronjob
服務,定時去調度服務。沒錯,這當然是最通俗的作法。可是買一臺服務器要花錢呀,便宜的也得幾十塊錢一臺虛擬機,並且只在上面跑一個這麼簡單的服務顯然是不值的。有沒有性價比高的作法呢?有,用雲函數!web
我我的的理解,雲函數跟傳統的服務主要的區別有幾點,一個是它是一種事件型的服務,由不一樣的事件觸發(HTTP、數據更改、對象存儲的變動等),第二個它是非長駐的,運行必定時間後會冷卻或者銷燬,第三個因爲以上兩種特性,對於一些負載不是很高的服務,用雲函數比較省錢。而對於這種提醒機器人,正正是一種負載不是很高的服務,很是合適。對小型團隊的這種提醒服務,在最近各大廠商都在推廣的時期,真的能夠作到不要錢。npm
這裏我對騰訊雲的雲函數最爲熟悉,所以就用它來作實踐。axios
首先爲了方便,咱們能夠用騰訊雲提供的 SCF CLI 來初始化咱們的雲函數和配置文件。我用的電腦是 Macbook,能夠直接安裝如下的命令進行安裝:小程序
pip install scf
複製代碼
若是不是Macbook能夠先自行安裝 python
和 pip
而後就是進行配置:
scf configure set --region ap-guangzhou --appid 1253970223 --secret-id AKIxxxxxxxxxx --secret-key uxxlxxxxxxxx
複製代碼
appid
, secret-id
和 secret-key
能夠在訪問密鑰頁面裏拿到。至於 region
,則是你想部署雲函數的區域,比方說在雲函數的控制檯首頁,就能看到頂部的區域。選廣州就是 ap-guangzhou
,選香港的就是 ap-hongkong
。基本上是 ap-
加上國內市場的拼音或國外城市的英文。
而後我們初始化好項目(用node.js 8.9版本寫雲函數):
# 初始化雲函數
scf init --runtime nodejs8.9 --name wework-robot
cd wework-robot
# 初始化 node 項目
npm init -y
複製代碼
而後就能獲得該雲函數:
此次要用到 axios,那咱們就安裝這個依賴:
npm i --save axios
複製代碼
打開 index.js
是以下一段代碼,async
表示該函數能夠用 Node.js
的新特性 async/await
。
'use strict';
exports.main_handler = async (event, context, callback) => {
console.log("%j", event);
return "hello shopee!"
};
複製代碼
我進行一些刪減後,成這樣。將函數名字改成 main
,並且因爲用 async/await
就能夠不用 callback
處理異步了。但改了名字也要改 template.yaml
,將 main_handler
改成 main
exports.main = async (event, context) => {
return "hello shopee!"
};
複製代碼
好了。是時候來寫提醒邏輯了。邏輯並不難,但主要注意的一點是時間。通過試驗,雲函數這裏的時間統一使用了標準的國際時間,也就是北京時間要比它晚8小時,詳細邏輯能夠看如下代碼的註釋:
const axios = require('axios')
const baseUrl =
'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=7f399641-40aa-45c8-ad3d-c46e1ee085a7'
async function bookLunch() {
let result = await axios.post(baseUrl, {
msgtype: 'text',
text: {
content: '大佬,訂午飯啦!',
mentioned_list: ['@all'] // 提醒全部人
}
})
return result.data
}
async function bookTaxi() {
let result = await axios.post(baseUrl, {
msgtype: 'text',
text: {
content: '辛苦了,早點回家休息吧。9點打車能夠報銷哦。',
mentioned_list: ['@all']
}
})
return result.data
}
async function remindWeeklyReport() {
let result = await axios.post(baseUrl, {
msgtype: 'text',
text: {
content: '週五了,記得寫週報看看你這周有沒偷懶!',
mentioned_list: ['@all']
}
})
return result.data
}
async function remindGoHome() {
let result = await axios.post(baseUrl, {
msgtype: 'text',
text: {
content: '11點半了,早點休息吧!'
}
})
return result.data
}
// 是否週五
function isFriday(day) {
return day === 5
}
// 是否工做日
function isWeekDay(day) {
return day > 0 && day < 6
}
// 是否30分,多預留1分鐘以防雲函數延遲啓動或執行
function isHalfHour(min) {
return min >= 30 && min <= 31
}
// 是否正點,多預留1分鐘以防雲函數延遲啓動或執行
function isSharp(min) {
return min >= 0 && min <= 1
}
exports.main = async (event, context) => {
let d = new Date() // js 時間對象
let day = d.getDay() // 獲取今天是星期幾,0 表示週日
let hour = d.getHours() // 獲取當前的 時
let min = d.getMinutes() // 獲取當前的 分
let hourGap = 8 // 我們在東8區
hour += hourGap // 獲取當前準確的時間數
// 打一下 log 看看具體時間
console.log(`day: ${day} hour: ${hour} min: ${min} hourGap: ${hourGap}`)
// 每週五4點到4點半通知寫週報
if (isFriday(day) && hour === 4 && isHalfHour(min)) {
return await remindWeeklyReport()
}
// 工做日天天11點提醒訂餐
if (isWeekDay(day) && hour === 11 && isSharp(min)) {
return await bookLunch()
}
// 工做日天天晚上9點提醒打車能夠報銷
if (isWeekDay(day) && hour === 21 && isSharp(min)) {
return await bookTaxi()
}
// 工做日天天晚上11點半提醒休息
if (isWeekDay(day) && hour === 23 && isHalfHour(min)) {
return await remindGoHome()
}
return 'hi shopee!'
}
複製代碼
邏輯都寫好了,可是,咱們須要讓它定時執行,好比每30分鐘執行一次。這個時候,咱們就須要添加「定時觸發器」 了。定時觸發咱們能夠在 template.yaml
裏面添加,能夠把註釋去掉,而後修改獲得:
CronExpression
具體能夠參考這個文檔:cloud.tencent.com/document/pr…
請使用推薦的寫法:
這裏有些參考的示例,直接套用便可:
我這裏寫的:0 */30 * * * MON-FRI *
,表示每週一到週五,每30分鐘會觸發一次雲函數的調用。
固然,咱們還想開啓一下 HTTP 觸發器,來用地址直接訪問該雲函數進行一些邏輯的調試,看看是否真的能成功發消息。
咱們能夠再到 template.yaml
裏添加這樣的 HTTP
觸發器:
好了,萬事俱備,咱們只須要再用 SCF CLI
發佈便可。
# 打包
scf package -t template.yaml
Generate deploy file 'deploy.yaml' success
# 發佈
scf deploy -t deploy.yaml
Deploy function 'wework-robot' success
複製代碼
發佈完成後,咱們能夠到騰訊雲的控制檯看下,已經存在了:
點進去看看觸發方式,發現分別有一個定時觸發器,一個API網關觸發器(HTTP觸發)
如此,便大功告成了!看看效果: