IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 给Flutter包私有仓库pub_server增加企业微信机器人消息 -> 正文阅读

[移动开发]给Flutter包私有仓库pub_server增加企业微信机器人消息

给Flutter包私有仓库pub_server增加企业微信机器人消息

本文相关代码地址:github

效果:
在这里插入图片描述

功能说明

默认的私有仓库pub_server服务程序在package上传成功后只是在命令行中输出了一行成功日志,缺少必要的消息通知,包发布成功了开发人员也不知道。
因为工作中企业微信使用较多,而且其中的群机器人可以方便的在工作群中推送消息,因此想着将上传成功的消息通过群机器人推送到群中。

企业微信群机器人的接入方法参看:群机器人配置说明

代码分析

相关类

修改代码前还是先完整看了一下pub_server的实现代码。

shelf_pubserver.dart文件ShelfPubServer类,该类负责服务端各接口的具体处理逻辑。在requestHandler方法中就可以得到每个接口的请求和反馈报文。其中package包上传功能涉及到/api/packages/versions/newUpload/api/packages/versions/newUploadFinish两个接口,第一个接口的职责说具体的上传逻辑,第二个接口只是完成上传操作。第一个接口处理成功后会返回一个302请求,让客户端直接请求第二个接口。

cow_repository.dart文件CopyAndWriteRepository类,该类是整个服务的核心,ShelfPubServer类所有的处理操作最终都是交给本类处理。其中,该类持有了file_repository.dart文件的FileRepository类负责实际的上传操作。

理论上,在ShelfPubServer类、CopyAndWriteRepository类、FileRepository类这三个类的相关代码中我们都可以监控到package上传成功的消息,可以在相关的代码位置向企业微信的群机器人发送消息请求。

初始方案

我原本是计划在ShelfPubServer类的_finishUploadSimple方法中,/api/packages/versions/newUploadFinish接口返回Successfully uploaded package.信息时直接发送机器人消息。
但是后面发现两个问题:第一,在/api/packages/versions/newUploadFinish接口的请求参数中并未携带上传的package包的信息,所以没办法发送相关的通知文本;第二,在ShelfPubServer类的代码中塞入给群机器人发送消息的代码就污染了原本逻辑代码,造成了不必要的代码耦合,如果我们后面需要增加邮件通知、钉钉通知,那是不是还要新增代码?

其中第一个问题可以通过修改/api/packages/versions/newUpload接口返回报文的方法实现,不过算是对原逻辑代码的改动,暂时不采用;思考第二个问题时,准备自己实现一个请求处理拦截器进行代码解耦,然后发现了一段代码:

  // 启动一个http服务
  return shelf_io.serve(
      const Pipeline()
          .addMiddleware(logRequests()) // 日志中间件
          .addHandler(server.requestHandler), // 请求处理器
      host,
      port);

这是基于shelf框架启动http服务的代码,其中addMiddleware(logRequests())是给接口请求和反馈增加日志输出的中间件。
我没有写过后端接口,看了下Pipeline的代码后觉得,正好可以使用中间件的方式来实现这个功能。

实现

添加一个通用的拦截器中间件

新增拦截器中间件interceptor_middleware.dart

Middleware interceptorMiddleware({Function beforeHandler, Function successHandler, Function errorHandler})

该中间件支持业务代码在每个请求处理前,处理成功后,处理失败后分别执行自己的逻辑。

添加企业微信群机器人中间件

新增机器人中间件qywx_robot_middleware.dart

Middleware qywxRobotMiddleware(String qywxkey, {MsgBuilder msgBuilder})

该中间件封装了[interceptorMiddleware],其中qywxkey是企业微信开放平台的key,msgBuilder是群机器人发送消息的消息体构造器,具体参看群机器人配置说明消息类型及数据格式

中间件的实现代码中拦截了/api/packages/versions/newUpload接口请求,当接口处理成功,且statusCode为302时,则调用相关API发送群机器人消息。

本中间件提供了一个默认的消息体构造器:

Map defaultMsgBuilder(PackageVersion packageVersion) {
  return {
    'msgtype': 'text',
    'text': {
      'content': 'OMG~我的天呐!Flutter Package ${packageVersion.packageName}的新品v${packageVersion.versionString}也太好看了吧!用它!用它!用它!',
      'mentioned_list': ['@all'],
    }
  };
}

可选择添加企业微信群机器人中间件

  var pipeline = Pipeline();
  if (qywxkey!=null && qywxkey.isNotEmpty) {
    pipeline = pipeline.addMiddleware(qywxRobotMiddleware(qywxkey)); // 企业微信机器人中间件  
  }
  pipeline = pipeline.addMiddleware(logRequests()); // 日志中间件
  // 启动一个http服务
  return shelf_io.serve(
      pipeline.addHandler(server.requestHandler), // 请求处理器
      host,
      port);

在启动HTTP服务时,当qywxkey存在时,则加载机器人中间件,否则不加载。
其中qywxkey通过命令行参数的形式传入:

ArgParser argsParser() {
  var parser = ArgParser();

  // 给参数解析器设置可支持的参数以及默认值
  parser.addOption('directory',
      abbr: 'd', defaultsTo: 'pub_server-repository-data');

  parser.addOption('host', abbr: 'h', defaultsTo: 'localhost');

  parser.addOption('port', abbr: 'p', defaultsTo: '8080');
  parser.addOption('qywxkey', abbr: 'q', defaultsTo: '');
  parser.addFlag('standalone', abbr: 's', defaultsTo: false);
  return parser;
}

完整代码地址

github

使用方法

cd ~/pub_server
dart example/example.dart -d ~/package-db -h 192.168.1.2 -p 8090 -q xxxx-xxxx-qywxkey

在启动服务时,在传入IP地址和接口外,额外传入qywxkey即可。

最终效果:
在这里插入图片描述

待优化细节

  • qywxRobotMiddleware中间件代码中拦截的是/api/packages/versions/newUpload接口,该接口只是上传操作,并没有上传成功,所以理论上还是要拦截/api/packages/versions/newUploadFinish接口;
  • /api/packages/versions/newUpload接口只返回了package的名称和版本号,没有该版本的修改内容;但是Package的官方指南中,更新说明是存在CHANGELOG.md文件中,所以想要读取版本更新说明,后面还需要解析MarkDown文件;
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:45:30  更:2021-07-31 16:45:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 18:54:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码