跳转至

那些年写过的企微机器人

1. 机器人

1.1. tip-tool

功能有

  1. 发起MR(已废弃)
  2. 远程发布(已废弃)
  3. 查看007性能数据
  4. 定时提醒
  5. 查询分支
  6. 查询单元测试/自动化测试/CodeCC报告
  7. 查看项目列表
  8. 查看当前会话id
  9. 查看后台协议地址
  10. 查看某次提交信息
  11. 创建赛事子活动
  12. 对比仓库两次commit的差异

1.2. 开源治理报表

爬虫抓取小组内的开源治理报表,每天早上9点半发送。

1.3. 七彩石助手

将七彩石配置同步到腾讯云,七彩石配置发生变化时会通知到群里

1.4. TAM日报

用API获取多个项目的TAM性能数据、首页数据,处理并制成图片发送到群里。

1.5. 深圳天气预警播报

爬虫获取当前正在生效的天气预警信息,一旦发生变化就把预警信息发送到群里。

制作背景是有一段时间有暴雨预警,如果持续红色,就居家办公,所以需要知道当前预警级别是不是红色。

1.6. 007日报

007上性能数据日报

2. 数据处理总结

前端常做的两件事:处理数据、展示。

对于数据处理,比如上面的日报数据,总结了一下:

总体流程:

  1. 获取昨天数据
  2. 获取前天数据
  3. 处理两个数据
  4. 拉平前天数据
  5. 获取相较前天的比例
  6. 获取最大最小index
  7. 获取表格headers

其中4、5、6、7都可以提取公共方法,因为第3步数据处理后,会统一成一样的格式。

处理数据的具体步骤:

  • 根据某key过滤(一般是主键)
  • 根据某key排序
  • 对每一项处理
  • 生成 key: { name: name,value: value }形式
  • 其中会格式化value
  • 再次过滤内部key
  • 添加其他内部key
  • 排序内部key
  • 再次处理某key(之所以不提前处理,是因为某些操作会造成key重复,比如截断)

处理数据示例代码:

parsedData.sort((a, b) => b.Request - a.Request)
  .map((item) => {
    const temp = {};

    const list = Object.keys(item).map((iKey) => {
      let value = item[iKey];

      if (iKey === 'Project') {
        value = ABBR_PROJECT_MAP[value] || value;
      } else {
        value = global.utils.formatNum(value);
      }

      return {
        name: iKey,
        value,
      };
    })
      .filter(item => SORT_KEY_LIST.includes(item.name))
      .sort((a, b) => SORT_KEY_LIST.indexOf(a.name) - SORT_KEY_LIST.indexOf(b.name));
    list.forEach((item) => {
      temp[item.name] = item;
    });

    return temp;
  })
  .filter(item => !FILTER_PROJECT_ID_LIST.includes(item.Project.value))
  .filter(item => item.Request.value > 10);

3. 企业微信消息类型

MsgType 类型有:

  • text
  • image
  • attachment
  • mixed 图文混排消息

MsgTypeevent 时,EventType 事件类型可能是:

  • add_to_chat 表示被添加进会话
  • delete_from_chat 表示被移出会话
  • enter_chat 表示用户进入机器人单聊

ChatType 类型有:

  • single
  • group

顺便贴下 ctx 打印内容:

img

ctx.query:

img

4. Koa

借助 Koa 的中间件机制,可以很方便的将不同类型的处理方法隔离开来,抽取公共的逻辑。

下面是一个例子:

router.post(
  '/',
  auth,
  parseMessage,
  handleTextMsg({
    cb: sendTextMsg,
    help: getHelpContent(),
    chatId: true,
  }),
  handleEventEnterChat(enterChatCb),
  handleAttachmentMsg(handleAttachmentCb),
);

下面是处理 add_to_chat 事件的中间件函数:

1
2
3
4
5
6
7
8
function handleEventAddToChat(cb) {
  return async function (ctx, next) {
    if (ctx.msgType === 'event' && ctx.eventType === 'add_to_chat') {
      await cb(ctx, next);
    }
    await next();
  };
}

回调内容举例:

1
2
3
4
5
6
7
8
async function sendTextMsg(ctx) {
  const contentList = ctx.content.split(/\s+/);
  const respContent = await getBranchLink({
    module: contentList[0],
    branch: contentList[1],
  });
  await sendMessageHelper(ctx, respContent);
}

参考:https://developer.work.weixin.qq.com/document/path/91881