# 飞书通知机器人 ## 目标 & 背景 前段时间钉钉的 webhook 机器人,进行了改版,现如今已经和企业微信通知差不多了,比之前麻烦了很多,正好我司接下来要换到飞书,借着这个机会对飞书的机器人相关内容熟悉了一下 首先明确在接入机器人时,我希望最终接入时,仅需要引入 shell 脚本,不需要借助其他语言二次开发 ## 创建企业 app 首先来到 [飞书开放平台](https://open.feishu.cn),创建企业自建应用,对于通知类型的机器人,我们需要添加 **机器人** 能力,以及对应的通知权限 ![](https://blog.liuocean.synology.me:9001/blog/old/17032098531026.jpg) ![](https://blog.liuocean.synology.me:9001/blog/old/17032098758746.jpg) 这里的权限一般需要企业的管理员进行审核后,才可以使用 ## 消息卡片模板 飞书提供了很多种消息类型,其中我个人比较喜欢的是 card 类型,可以完成很多复杂的消息推送,而且飞书还通了一个可视化的搭建工具,具体可点击链接尝试 [消息卡片搭建工具](https://open.feishu.cn/tool/cardbuilder) ![](https://blog.liuocean.synology.me:9001/blog/old/17032115183434.jpg) 这里我使用模板 ID 作为推送的类型,因此需要在变量列表中配置通知时需要上传的参数列表,如 **我是内容** 这段文字对应的 markdown 信息,就需要传入 **content** 变量,基于这种配置方式,我们在搭建好通知后台后,可以随意修改卡片的样式等信息 ## 访问凭证 [获取访问凭证文档](https://open.feishu.cn/document/server-docs/api-call-guide/calling-process/get-access-token) 飞书的官方文档还是非常不错的,我们这里使用的是第一种 **tenant_access_token**,这里主要讲一下如何将请求的返回结果取出我们要的字段 ```shell curl -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \ -H 'Content-Type: application/json' \ -d '{ "app_id": "xxx", "app_secret": "xxx" }' ``` 在执行这段代码后,飞书会返回如下内容 ```json { "code": 0, "expire": 3096, "msg": "ok", "tenant_access_token": "t-xxx" } ``` 我们需要的是最后一段 **tenant_access_token** 对应的字符串,这里需要借助 **jq** 指令的辅助,我们只需要在请求的最后加入 **| jq -r '.tenant_access_token'** 即可 ```shell token=$(curl -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \ -H 'Content-Type: application/json' \ -d '{ "app_id": "xxx", "app_secret": "xxx" }' | jq -r '.tenant_access_token') echo $token ``` ## 群 ID - [群 ID 说明](https://open.feishu.cn/document/server-docs/group/chat/chat-id-description) - [API 调试](https://open.feishu.cn/document/server-docs/group/chat/list) 在我们调用最后的发送 API 之前,需要明确这条消息到底发给谁,我这里的需求是发送到专门的通知群中,因此需要透过飞书的 API 获取正确的群 ID 在 API 调试界面,手动获取 token 后,飞书会直接返回给你当前机器人所在的所有群的基本信息,具体返回参考如下 ```json { "code": 0, "data": { "has_more": false, "items": [ { "avatar": "xxx", "chat_id": "xxx", "description": "", "external": false, "name": "xxx", "owner_id": "xxx", "owner_id_type": "open_id", "tenant_key": "xxx" } ], "page_token": "" }, "msg": "success" } ``` 这里的 **chat_id** 对应的值就是我们所需要的 ## 发送消息 [发送消息文档](https://open.feishu.cn/document/server-docs/im-v1/message/create) 这个部分我们主要做的是对 send 行为进行封装,并处理好字符串的转换。在发送之前,我们需要准备好如下参数 - **receive_id_type** 这里是 **chat_id** - **tenant_access_token** - **receive_id** 对应群的 **chat_id** - **template_id** 对应 card 模板 ID - **template_variable** 对应 card 模板中的变量 - **app_id** 机器人应用 ID - **app_secret** 机器人的 sign ```shell #!/bin/bash raw_content=' { "type":"template", "data": { "template_id":"xxx", # 填入你的模板ID "template_variable": { "title":"我是标题", # 这里可以封装为函数,使用 $1 等参数进行接收 "content":"我是内容", "btn_name":"我是按钮", "btn_url":"https://www.baidu.com" } } } ' # 飞书对于 content 的定义为 string,因此这里必须是一个转义后的 json # 比如 "type":"template" 就必须是 \"type\":\"template\" # 借助 jq 的 tostring 方法,可以保证上面模板 json 的书写体验 content=$(echo $raw_content | jq -c '.|tostring') card=' { "msg_type": "interactive", "receive_id": "xxx", # 群的 chat_id "content":'$content' } ' token=$(curl -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \ -H 'Content-Type: application/json' \ -d '{ "app_id": "xxx", # 企业应用的 app_id "app_secret": "xxx" # 企业应用的 sign }' | jq -r '.tenant_access_token') curl -i -X POST 'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer '$token'' \ -d "$card" ``` ## 一些恶趣味 在我使用过程中发现,card 后台也可以动态配置图片,而且飞书也支持 gif 格式,这就有意思了,搭建工具可以手动上传你需要的图片,记录下来这张图片的 key,然后在 shell 脚本中根据情况选择不同的 key,这样就可以有不同的通知效果 > 虽然飞书也支持 api upload 图片,但是我懒的写了~ ![](https://blog.liuocean.synology.me:9001/blog/old/17032145777517.jpg) 我把通知的三种类型,对应了三个不同 魔性八哥 的表情包 - 开始打包 - 打包成功 - 打包失败 哈哈哈哈哈,这个通知非常欢乐,你都不用看文字,就知道结果 ## 最后 这次了解了一下飞书的通知,对比了一下钉钉的 webhook,差距非常明显