• 使用 Azure 函数应用推送消息到企业微信机器人


    基本原理

    我们有时会希望工作时使用同一个工具接管所有系统的消息。

    比如使用企业微信接管 GitLab、语雀、禅道等系统的 Webhooks。同时由于消息源(GitLab、禅道、……)系统输出的消息格式和监管工具接收的格式可能不一致,所以我们通常需要做消息格式转换。那么转换的工具可以自己构建一个应用发布出去,或者直接使用云服务(腾讯云函数、Azure 函数应用、……)构建。

    本文结合 GitLab Webhooks,Azure 函数和企业微信的群机器人实现上述过程。

    其中:

    1. GitLab 为消息源,也可以是禅道、语雀、Gitee 或者自己构建的任何应用
    2. Azure 函数应用为消息转换转发工具,也可以是腾讯云函数等第三方云服务或者自己构建的任何应用
    3. 企业微信的群机器人为消息的接收方,也可以是钉钉、倍恰或者自己构建的任何应用

    示例步骤

    创建企业微信群机器人

    具体可以参考如何配置群机器人?-帮助中心-企业微信

    创建 Azure 函数应用

    1. 登录 Azure 的 Portal

    2. 添加函数应用

      • 函数应用名称:wechatwork-robot
      • 运行时堆栈:Node.js
    3. 打开函数应用 wechatwork-robot > 开发工具 > 应用服务编辑器(预览版) —— 好像是 VSCode 为 Azure 做的云版本编辑器

      • 因为我们要使用 axios 组件,所以要在 package.json 文件中添加依赖的包 axios。如果没有发现 package.json 文件,需要额外创建 package.json 文件。
      {
          "name": "xxx-gitlab-hook",
          "dependencies": {
              "axios": "^0.19.2"
          }
      }
      
      • 创建 wechatwork.js 文件,这里实现了 Markdown 格式的消息发送到企业微信,其他格式可以参考企业微信文档实现
      const axios = require('axios');
      const wechatWebHookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/";
      
      // https://work.weixin.qq.com/help?doc_id=13376
      // 每个机器人发送的消息不能超过20条/分钟。
      class wechatwork {
          async sendMarkdownMessage(robotId, content, options) {
              const markdownMessageInfo = {
                  "msgtype": "markdown",
                  "markdown": {
                      "content": content
                  }
              };
      
              return await axios.post(`${wechatWebHookUrl}send?key=${robotId}`, markdownMessageInfo)
                  .then((res) => {
                      console.log(`Status: ${res.status}`);
                      console.log('Body: ', res.data);
                  }).catch((err) => {
                      console.error(err);
                  });
          }
      }
      
      module.exports = wechatwork;
      
    4. 在函数应用 wechatwork-robot 中添加各种消息源解析函数,以 GitLab 为例

      • 新建函数

        • 选择 HTTP trigger
          • 新建函数:GitLab-Hook —— 函数的名称
          • Authorization level:Anonymous —— 访问权限,Azure 提供了 Function,Anonymous 和 Admin
      • 编辑函数 GitLab-Hook

        • 代码 + 测试

          • 修改 wechatwork-robotGitLab-Hookindex.js 文件,注意其中 wechatwork.js 是单独的文件,后面会讲如何撰写这个文件
          const wechatwork = require('../wechatwork.js');
          
          function handleDefaultEvent(event) {
              return new Array(`Git: Sorry, event ${event} is not supported.`);
          }
          
          function addZentaoLink(commitMessage) {
              // ...
              // 我们使用了禅道管理迭代 Task 和 Bug,所以对 GitLab 的消息做了些适配处理
              // ...
          
              return newCommitMessage;
          }
          
          function handlePush(context) {
              let {user_name, project:{name:proName, web_url}, commits} = context;
          
              return commits.map(commit => {
                  let commitMessage = addZentaoLink(commit.message);
                  const message = `Git:项目 [${proName}](${web_url}) 接收到来自 ${user_name} 的推送:[${commit.id.substr(0,8)}](${web_url}/-/commit/${commit.id}) ${commitMessage} `;
                  return message;
              });
          }
          
          function handleMergeRequest(context) {
              let {object_kind='', user:{name, avatar_url}, project:{name:proName, web_url}, object_attributes:{title, state, target_branch, source_branch, url}} = context;
              const message = `Git:项目 [${proName}](${web_url}) 由 @${name} ${state} 一个 ${object_kind}:[${title}](${url})。源分支:${source_branch},目标分支:${target_branch}`;
              return new Array(message);
          }
          
          function handleNoteRequest(context) {
              let {
                  object_kind='',
                  user:{name},
                  project:{name:proName, web_url},
                  object_attributes:{note, noteable_type, url}
              } = context;
              const message = `Git:项目 [${proName}](${web_url}) 接收到来自 @${name} 的对 ${noteable_type} 的[评论](${url}):${note}`;
              return new Array(message);
          }
          
          module.exports = async function (context, req) {
              const gitEvent = req.headers["x-gitlab-event"];
              const rebotId = req.query.id;
          
              let messages = [];
              switch(gitEvent) {
                  case "Push Hook":
                      messages = handlePush(req.body);
                      break;
                  case "Merge Request Hook":
                      messages = handleMergeRequest(req.body);
                      break;
                  case "Note Hook":
                      messages = handleNoteRequest(req.body);
                      break;
                  default:
                      messages = handleDefaultEvent(gitEvent);
                      break;
              }
          
              let work = new wechatwork();
              messages.forEach(message => {
                  work.sendMarkdownMessage(rebotId, message);
              });
          
              context.res = {
                  body: "Done"
              };
          }
          
        • Test/Run(可选)
          在上述代码完成后,可以使用内置的测试运行功能可以模拟 GitLab 的 Http 请求进行测试

      • 获取函数 URL,以供后续 GitLab Webhooks 配置使用

    添加 GitLab WebHooks

    1. 登录 GitLab
    2. 定位到 Settings > Webhooks,填写后 Add Webhook
      1. URL: 上面获取到的函数 URL
      2. Trigger
        1. Push events
        2. Comments
    3. 添加成功后,可以在下方的 Project Hooks 点击 Test,查看企业微信群是否能收到消息推送

    参考

  • 相关阅读:
    QEMU KVM Libvirt手册(10):Managing Virtual Machines with libvirt
    Openssl的证书操作
    QEMU KVM Libvirt手册(10): KVM的各种限制
    QEMU KVM Libvirt手册(9): network
    nginx调优(一)
    Apache调优(二)
    Apache调优(一)
    使用Varnish为网站加速
    Linux系统调优——系统整体运行状态排查(六)
    Linux系统调优——内核相关参数(五)
  • 原文地址:https://www.cnblogs.com/nehcdahc/p/13294322.html
Copyright © 2020-2023  润新知