发送webhook到飞书机器人

发布于:2024-12-21 ⋅ 阅读:(14) ⋅ 点赞:(0)

发送webhook到飞书机器人

参考链接 自定义机器人使用指南

创建自定义机器人

  1. 邀请自定义机器人进群。

    • 进入目标群组,在群组右上角点击更多按钮,并点击 设置。
      在这里插入图片描述

    • 在右侧 设置 界面,点击 群机器人。
      在这里插入图片描述

    • 在 群机器人 界面点击 添加机器人。

      在 添加机器人 对话框,找到并点击 自定义机器人。
      在这里插入图片描述

    • 设置自定义机器人的头像、名称与描述,并点击 添加。
      在这里插入图片描述

  2. 获取自定义机器人的 webhook 地址
    机器人对应的 webhook 地址 格式如下:
    https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx
    请妥善保存好此 webhook 地址,不要公布在 Gitlab、博客等可公开查阅的网站上,避免地址泄露后被恶意调用发送垃圾消息。
    在这里插入图片描述

  3. 获取签名校验
    在 安全设置 区域,选择 签名校验。

选择签名校验后,系统已默认提供了一个秘钥。你也可以点击 重置,更换秘钥。
在这里插入图片描述

使用java发送http post到自定义机器人

  1. 计算签名校验,参考官方文档的SignDemo.java,自定义一个签名函数
    private static String genSign(String secret, long timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
        //把timestamp+"\n"+密钥当做签名字符串
        String stringToSign = timestamp + "\n" + secret;
        //使用HmacSHA256算法计算签名
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(new byte[]{});
        return new String(Base64.encodeBase64(signData));
    }

  1. 计算时间戳
    需要注意的是,时间戳是以秒为单位的,并且要配置时区,不可直接使用System.currentTimeMillis()/1000来计算秒值
long seconds = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
  1. 创建富文本消息
    参考官方文档 发送富文本消息
    • 创建一个content对象
    private static JSONObject createOuterContent(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("post", createPostJsonObject(title, message, detail, startTime, endTime));
        return result;
    }

    private static JSONObject createPostJsonObject(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("zh_cn", createZhCNJsonObject(title, message, detail, startTime, endTime));
        return result;
    }

    private static JSONObject createZhCNJsonObject(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("title", title);
        result.put("content", createContentList(message, detail, startTime, endTime));
        return result;
    }

    private static JSONArray createContentList(String message, String detail, String startTime, String endTime) {
        JSONArray result = new JSONArray();
        JSONArray item1 = new JSONArray();
        item1.add(createInnerHeadContent("message"));
        item1.add(createInnerTextContent(message));
        result.add(item1);

        JSONArray item2 = new JSONArray();
        item2.add(createInnerHeadContent("detail"));
        item2.add(createInnerTextContent(detail));
        result.add(item2);

        JSONArray item3 = new JSONArray();
        item3.add(createInnerHeadContent("startTime"));
        item3.add(createInnerTextContent(startTime));
        result.add(item3);

        JSONArray item4 = new JSONArray();
        item4.add(createInnerHeadContent("endTime"));
        item4.add(createInnerTextContent(endTime));
        result.add(item4);
        return result;
    }

    private static JSONObject createInnerHeadContent(String tag) {
        JSONObject result = new JSONObject();
        result.put("tag", "text");
        result.put("text", tag+": ");
        return result;
    }

    private static JSONObject createInnerTextContent(String text) {
        JSONObject result = new JSONObject();
        result.put("tag", "text");
        result.put("text", text);
        return result;
    }

  • 再创建完整的json对象

完整代码如下

java版本

public class FeishuWebhook {
    private static final Logger logger = LoggerFactory.getLogger(FeishuWebhook.class);

    public static final String DEFAULT_DATETIME_FORMATTER_STR = "yyyy-MM-dd HH:mm:ss";
    public static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER =
            DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMATTER_STR);

    public static void send(String url, String secret, AlertDO alertDO) {
        logger.info("FeishuWebhook.send, url:{}, alertDO={}", url, alertDO);
        JSONObject requestBody = createRequestBody(secret, alertDO);
        logger.info("requestBody:{}", requestBody);
        JSONObject result = HttpUtils.postForJsonObject(url, null, null, requestBody);
        logger.info("result:{}", result);
    }

    private static String genSign(String secret, long timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
        //把timestamp+"\n"+密钥当做签名字符串
        String stringToSign = timestamp + "\n" + secret;
        //使用HmacSHA256算法计算签名
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(new byte[]{});
        return new String(Base64.encodeBase64(signData));
    }

    private static JSONObject createRequestBody(String secret, AlertDO alertDO) {
        JSONObject requestBody = new JSONObject();
        long seconds = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
        logger.info("seconds:{}", seconds);
//        int seconds = 1734515343;
        try {
            String sign = genSign(secret, seconds);
            requestBody.put("timestamp", seconds);
            requestBody.put("sign", sign);
            requestBody.put("msg_type", "post");

            String title = "通知";

            String message = alertDO.getMessage();
            String detail = alertDO.getDetail();
            String startTime = DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.ofInstant(alertDO.getStartTime().toInstant(), ZoneId.systemDefault()));
            String endTime = DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.ofInstant(alertDO.getEndTime().toInstant(), ZoneId.systemDefault()));
            requestBody.put("content", createOuterContent(title, message, detail, startTime, endTime));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return requestBody;
    }

    private static JSONObject createOuterContent(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("post", createPostJsonObject(title, message, detail, startTime, endTime));
        return result;
    }

    private static JSONObject createPostJsonObject(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("zh_cn", createZhCNJsonObject(title, message, detail, startTime, endTime));
        return result;
    }

    private static JSONObject createZhCNJsonObject(String title, String message, String detail, String startTime, String endTime) {
        JSONObject result = new JSONObject();
        result.put("title", title);
        result.put("content", createContentList(message, detail, startTime, endTime));
        return result;
    }

    private static JSONArray createContentList(String message, String detail, String startTime, String endTime) {
        JSONArray result = new JSONArray();
        JSONArray item1 = new JSONArray();
        item1.add(createInnerHeadContent("message"));
        item1.add(createInnerTextContent(message));
        result.add(item1);

        JSONArray item2 = new JSONArray();
        item2.add(createInnerHeadContent("detail"));
        item2.add(createInnerTextContent(detail));
        result.add(item2);

        JSONArray item3 = new JSONArray();
        item3.add(createInnerHeadContent("startTime"));
        item3.add(createInnerTextContent(startTime));
        result.add(item3);

        JSONArray item4 = new JSONArray();
        item4.add(createInnerHeadContent("endTime"));
        item4.add(createInnerTextContent(endTime));
        result.add(item4);
        return result;
    }

    private static JSONObject createInnerHeadContent(String tag) {
        JSONObject result = new JSONObject();
        result.put("tag", "text");
        result.put("text", tag+": ");
        return result;
    }

    private static JSONObject createInnerTextContent(String text) {
        JSONObject result = new JSONObject();
        result.put("tag", "text");
        result.put("text", text);
        return result;
    }

}

python版本
FeishuBotHypertextWithSecret.py

import base64
import hashlib
import hmac
from datetime import datetime

import requests

WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/xx"
WEBHOOK_SECRET = "ssssssss"


class LarkBot:
    def __init__(self, secret: str) -> None:
        if not secret:
            raise ValueError("invalid secret key")
        self.secret = secret

    def gen_sign(self, timestamp: int) -> str:
        string_to_sign = '{}\n{}'.format(timestamp, self.secret)
        hmac_code = hmac.new(
            string_to_sign.encode("utf-8"), digestmod=hashlib.sha256
        ).digest()
        sign = base64.b64encode(hmac_code).decode('utf-8')

        return sign

    def send(self) -> None:
        timestamp = int(datetime.now().timestamp())
        sign = self.gen_sign(timestamp)

        params = {
            "timestamp": timestamp,
            "sign": sign,
            "msg_type": "post",
            "content": {
                "post": {
                    "zh_cn": {
                        "title": "项目更新通知",
                        "content": [
                            [{
                                "tag": "text",
                                "text": "项目有更新: "
                            }, {
                                "tag": "a",
                                "text": "请查看",
                                "href": "http://www.example.com/"
                            }, {
                                "tag": "at",
                                "user_id": "ou_18eac8********17ad4f02e8bbbb"
                            }]
                        ]
                    }
                }
            }
        }
        resp = requests.post(url=WEBHOOK_URL, json=params)
        resp.raise_for_status()
        result = resp.json()
        if result.get("code") and result["code"] != 0:
            print(result["msg"])
            return
        print("消息发送成功")


def main():
    bot = LarkBot(secret=WEBHOOK_SECRET)
    bot.send()


if __name__ == '__main__':
    main()

LarkBotWithoutSecret.py

from datetime import datetime

import requests

WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/sss"


class LarkBot:
    def send(self, content: str) -> None:
        timestamp = int(datetime.now().timestamp())

        params = {
            "timestamp": timestamp,
            "msg_type": "text",
            "content": {"text": content},
        }
        resp = requests.post(url=WEBHOOK_URL, json=params)
        resp.raise_for_status()
        result = resp.json()
        if result.get("code") and result["code"] != 0:
            print(result["msg"])
            return
        print("消息发送成功")


def main():
    bot = LarkBot()
    bot.send(content="我是一只高级鸽子!")


if __name__ == '__main__':
    main()