不花錢就能夠給企業微信作個提醒機器人

李成熙,Shopee Airpay 前端 Leader。2014年畢業加入騰訊AlloyTeam,前後負責過QQ羣、花樣直播、騰訊文檔等項目。後於2018年加入騰訊云云開發團隊。專一於性能優化、工程化和小程序服務。微博 | 知乎 | Github前端

到了新公司以後,發現竟然也是用企業微信。但惋惜的是,外部的企業微信竟然沒有機器人。這對之前在鵝廠裏習慣用企業微信作提醒的我以爲很不方便。終於,7月一開始企業微信終於上線機器人功能。node

右擊羣聊天卡片,能夠添加羣機器人。python

懸浮在機器人的頭像上,會顯示出 Webhook 地址。點擊這個地址,會跳到機器人的開發文檔。ios

提醒機器人的開發其實很簡單,其實就是向這個webhook地址,按文檔提供的格式發送請求,就能夠實現消息推送了。最簡單的示例,能夠用 Node.jsaxios 類庫: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能夠先自行安裝 pythonpip

而後就是進行配置:

scf configure set --region ap-guangzhou --appid 1253970223 --secret-id AKIxxxxxxxxxx --secret-key uxxlxxxxxxxx
複製代碼

appid, secret-idsecret-key 能夠在訪問密鑰頁面裏拿到。至於 region,則是你想部署雲函數的區域,比方說在雲函數的控制檯首頁,就能看到頂部的區域。選廣州就是 ap-guangzhou,選香港的就是 ap-hongkong。基本上是 ap- 加上國內市場的拼音或國外城市的英文。

image.png

而後我們初始化好項目(用node.js 8.9版本寫雲函數):

# 初始化雲函數
scf init --runtime nodejs8.9 --name wework-robot

cd wework-robot

# 初始化 node 項目
npm init -y
複製代碼

而後就能獲得該雲函數:

image.png

此次要用到 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!"
};
複製代碼

image.png

好了。是時候來寫提醒邏輯了。邏輯並不難,但主要注意的一點是時間。通過試驗,雲函數這裏的時間統一使用了標準的國際時間,也就是北京時間要比它晚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 裏面添加,能夠把註釋去掉,而後修改獲得:

image.png

CronExpression 具體能夠參考這個文檔:cloud.tencent.com/document/pr…

請使用推薦的寫法:

image.png

這裏有些參考的示例,直接套用便可:

image.png

我這裏寫的:0 */30 * * * MON-FRI *,表示每週一到週五,每30分鐘會觸發一次雲函數的調用。

固然,咱們還想開啓一下 HTTP 觸發器,來用地址直接訪問該雲函數進行一些邏輯的調試,看看是否真的能成功發消息。

咱們能夠再到 template.yaml 裏添加這樣的 HTTP 觸發器:

image.png

好了,萬事俱備,咱們只須要再用 SCF CLI 發佈便可。

# 打包
scf package -t template.yaml 
Generate deploy file 'deploy.yaml' success

# 發佈
scf deploy -t deploy.yaml 
Deploy function 'wework-robot' success
複製代碼

發佈完成後,咱們能夠到騰訊雲的控制檯看下,已經存在了:

image.png

點進去看看觸發方式,發現分別有一個定時觸發器,一個API網關觸發器(HTTP觸發)

如此,便大功告成了!看看效果:

相關文章
相關標籤/搜索