拉仇恨!webhook + 企业微信 给同事做了个代码提交监听工具

这是「进击的Coder」的第 440 篇技术分享

作者:小富

来源:程序员内点事

最近接个任务,用webhook做了个代码提交监听功能,就是有人向远程仓库提交代码后,会在企业微信群内发送一条消息,类似 @XXX 在XXX时间,向XXX项目提交 XXXX 代码 这样的文案。

至于为啥要做这么个工具,没办法官大一级压死人,其实我内心是拒绝的,总像是被监视一样感觉怪怪的。难不成是发现了我平时偷偷提代码,悄无声息的修 Bug?

webhook

webhook也就是我们经常说的钩子,如果对钩子不熟悉,没关系那我们换一个概念,回调URL应该听说过吧,例如:微信支付这类的三方平台都支持配置回调URL,通知支付状态。

当一些事件触发,例如:"push代码到远程仓库",或者"提一个issue"等,源网站可以发起一个HTTP请求到webhook配置的URL。

下图是这个工具的工作流程,开发者向GitHub项目提交代码,会触发GitHub的pull event,紧接着向GitHub webhook中配置的三方URL发送一个POST请求,这个三方平台可以是钉钉、飞书、企业微信这类平台。

下面我们以 GitHub + 企业微信 来实现代码提交监听,自动向企业微信群组推送消息。

配置GitHub webhook

首先进入GitHub对应项目的 Settings,做webhook的基础配置。

主要配置四部分:

Payload URL 回调服务的地址;

Content type 回调请求头,建议JSON格式;

Secret 为了做安全校验,设置后会在请求 header 中增加如下两个属性,用来区分请求的来源,避免暴露的请求被恶意访问;

X-Hub-Signature: sha1=2478e400758f6114aa18abc4380ef8fad0b16fb9
X-Hub-Signature-256: sha256=68bde5bee18bc36fd95c9b71b4a89f238cb01ab3bf92fd67de3a1de12b4f5c72

最后我们选择由哪些事件来触发webhook回调,push event(代码推送事件)、everything(所有事件)、某些特定事件三种。

我们可以在 Recent Deliveries 查看webhook回调记录,以及完整的请求和参数数据,还可以redelivery模拟发送请求。

配置企业微信

企业微信的配置其实更简单,我们先创建一个群组,在群组右键有个添加机器人选项,添加成功后会生成webhook地址。我们只要向这个地址发送POST请求,群组内就会收到推送消息。

消息内容支持文本(text)、markdown(markdown)、图片(image)、图文(news)四种消息类型,而且还支持在群内 @ 群成员,下边以文本格式做示范。

   curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=145a516a-dd15-421f-97a3-ba3bf1479369' \
   -H 'Content-Type: application/json' \
   -d '
   {
        "msgtype": "text",
        "text": {
            "content": "你好,我是程序员内点事"
        }
   }'

直接请求 url 发现消息推送成功,说明配置的没问题。

但是到这大家发现一个问题没,GitHub企业微信一个只管往出发请求,一个只管接受固定数据格式的请求,两个接口的数据根本无法兼容啊?

请求转发

既然他们之间不兼容,没办法,那就只能我们自己在中间做一层适配,谁让两边都惹不起呢!

转发的逻辑也比较简单,只需接受GitHub回调过来的请求数据,稍加修改组装成企业微信要求的数据格式,直接发送就可以了。

GitHub推送过来的数据包括,仓库、作者、提交者、提交内容等信息,基本上够用。

代码实现比较粗糙,将就看下吧

@Slf4j
@RestController
public class WebhookController {

    private static String WECHAT_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=145a516a-dd15-421f-97a3-ba3bf1479369";

    private static String GITHUB_API = "https://api.github.com/users/";

    /**
     * @param webhook webhook
     * @author 程序员内点事
     * @Description: github 回调
     * @date 2021/05/19
     */
    @PostMapping("/webhook")
    public String webhookGithub(@RequestBody GithubWebhookPullVo webhook) {

        log.info("webhook 入参接收 weChatWebhook {}", JSON.toJSONString(webhook));
        // 仓库名
        String name = webhook.getRepository().getName();
        SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String now = simpleFormatter.format(new Date());
        String content = null;
        if (webhook.getCommits().size() > 0) {
            GithubWebhookPullVo.CommitsDTO commitsDTO = webhook.getCommits().get(0);

            content = "[" + commitsDTO.getCommitter().getName() + "]" +
                    "于:" + now + "," +
                    "向作者:[" + commitsDTO.getAuthor().getName() + "]的,远程仓库" + name + "推送代码" +
                    "详情:";

            List<String> addeds = commitsDTO.getAdded();
            if (addeds.size() > 0) {
                content += "添加文件:";
                for (int i = 0; i < addeds.size(); i++) {
                    content = (i + 1) + content + addeds.get(i);
                }
            }
            List<String> modifieds = commitsDTO.getModified();
            if (modifieds.size() > 0) {
                content += "修改文件:";
                for (int i = 0; i < modifieds.size(); i++) {
                    content = (i + 1) + content + modifieds.get(i);
                }
            }
            List<String> removeds = commitsDTO.getRemoved();
            if (removeds.size() > 0) {
                content += "删除文件:";
                for (int i = 0; i < removeds.size(); i++) {
                    content = (i + 1) + content + removeds.get(i);
                }
            }
        }
        log.info(content);

        WeChatWebhook weChatWebhook = new WeChatWebhook();
        weChatWebhook.setMsgtype("text");
        WeChatWebhook.TextDTO textDTO = new WeChatWebhook.TextDTO();
        textDTO.setContent(content);
        textDTO.setMentionedList(Arrays.asList("@all"));
        textDTO.setMentionedMobileList(Arrays.asList("@all"));
        weChatWebhook.setText(textDTO);

        /**
         * 组装参数后向企业微信发送webhook请求
         */
        log.info("企业微信发送参数 {}", JSON.toJSONString(weChatWebhook));
        String post = HttpUtil.sendPostJsonBody(WECHAT_URL, JSON.toJSONString(weChatWebhook));
        log.info("企业微信发送结果 post {}", post);
        return JSON.toJSONString(post);
    }
}

这里要提醒一下,GitHub webhook 回调过来的数据有些并不能直接拿来用,某些场景还是要调用GitHub API来换取一些数据的。

文档地址:https://docs.github.com/en/rest/reference

上边的配置工作完成,再将转发的代码部署到服务器,测试下整个链路看看效果,故意修改pom.xml文件提交,发现提交代码后成功向企业微信发送了消息,和我们预期的效果一致。

源码地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-webhook-wechat

这个工程包含我过往文章里所有的案例,比如:抖音去水印工具源码人脸识别项目源码、以及redisSeataMQ等中间件的各种问题解决案例,感兴趣的同学可以Star个,实际开发一定会用得到。

End

「进击的Coder」专属学习群已正式成立,搜索「CQCcqc4」添加崔庆才的个人微信或者扫描下方二维码拉您入群交流学习。

看完记得关注@进击的Coder

及时收看更多好文

↓↓↓

你的每个赞和在看,我都喜欢!

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
环境要求 PHP >= 7.0 PHP fileinfo 拓展 储存文件需要用到 PHP gd 拓展 控制台显示二维码 PHP posix 拓展 控制台显示二维码(linux) PHP 系统命令 拓展 执行clear命令 PHP SimpleXML 拓展 解析XML 安装 请确保已经会使用composer! 运行微信账号的语言设置务必设置为简体中文!!否则可能出现未知的错误! 1、git git clone https://github.com/HanSon/vbot.git cd vbot composer install 2、composer composer require hanson/vbot 运行 正常运行 php example/index.php 带session运行 php example/index.php --session yoursession 关于session : 带session运行会自动寻找设定session指定的cookies,如不存在则新建一个文件夹位于 /tmp/session 中,当下次修改代码时再执行就会免扫码自动登录。 如果不设置,vbot会自动设置一个6位的字符的session值,下次登录也可以直接设定此值进行面扫码登录。 PS:运行后二维码将保存于设置的缓存目录,命名为qr.png,控制台也会显示二维码,扫描即可(linux用户请确保已经打开ANSI COLOR) 警告!执行前请先查看index.php的代码,注释掉你认为不需要的代码,避免对其他人好友造成困扰 请在terminal运行!请在terminal运行!请在terminal运行! 目录结构 vbot demo (vbot 当前在运行的代码,也欢迎大家提供自己的一些实战例子) example (较为初级的实例) src (源码) tmp (假设缓存目录设置在此) session hanson (设定值 php index.php --session hanson) 523eb1 (随机值) users 23534234345 (微信账号的UIN值) file (文件) gif (表情) jpg (图片) mp3 (语音) mp4 (视频) contact.json (联系人 debug模式下存在) group.json (群组 debug模式下存在) member.json (所有群的所有成员 debug模式下存在) official.json (公众号 debug模式下存在) special.json (特殊账号 debug模式下存在) message.json (消息) 体验 扫码后,验证输入“echo”即可自动加为好友并且入vbot群。 vbot并非24小时执行,有时会因为开发调试等原因暂停功能。如果碰巧遇到关闭情况,可加Q群 492548647 了解开放时间。执行后发送“我”即可自动邀请进群。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值