当前位置: 首页 > news >正文

go语言实现gogs代码推送到飞书群聊

1. 分析参数

gogs推送入参如下

{"ref": "refs/heads/develop","before": "28e1879d029cb852e4844d9c718537df08844e03","after": "bffeb74224043ba2feb48d137756c8a9331c449a","compare_url": "http://localhost:3000/unknwon/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a","commits": [{"id": "bffeb74224043ba2feb48d137756c8a9331c449a","message": "!@#0^%\u003e\u003e\u003e\u003e\u003c\u003c\u003c\u003c\u003e\u003e\u003e\u003e\n","url": "http://localhost:3000/unknwon/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a","author": {"name": "Unknwon","email": "u@gogs.io","username": "unknwon"},"committer": {"name": "Unknwon","email": "u@gogs.io","username": "unknwon"},"timestamp": "2017-03-13T13:52:11-04:00"}],"repository": {"id": 140,"owner": {"id": 1,"login": "unknwon","full_name": "Unknwon","email": "u@gogs.io","avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96","username": "unknwon"},"name": "webhooks","full_name": "unknwon/webhooks","description": "","private": false,"fork": false,"html_url": "http://localhost:3000/unknwon/webhooks","ssh_url": "ssh://unknwon@localhost:2222/unknwon/webhooks.git","clone_url": "http://localhost:3000/unknwon/webhooks.git","website": "","stars_count": 0,"forks_count": 1,"watchers_count": 1,"open_issues_count": 7,"default_branch": "master","created_at": "2017-02-26T04:29:06-05:00","updated_at": "2017-03-13T13:51:58-04:00"},"pusher": {"id": 1,"login": "unknwon","full_name": "Unknwon","email": "u@gogs.io","avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96","username": "unknwon"},"sender": {"id": 1,"login": "unknwon","full_name": "Unknwon","email": "u@gogs.io","avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96","username": "unknwon"}
}

对我们而言,有需要通知的就:谁推送了代码到哪个分支,什么时间,仓库地址和代码详情,还有就是变更的代码明细。

2. 开发接口

使用go中gin框架作为基础,将需要处理的参数声明成结构体

type Commit struct {ID        string    `json:"id"`Message   string    `json:"message"`URL       string    `json:"url"`Author    Author    `json:"author"`Committer Committer `json:"committer"`Modified  []string  `json:"modified"`Timestamp string    `json:"timestamp"`
}type Author struct {Name     string `json:"name"`Email    string `json:"email"`Username string `json:"username"`
}type Committer struct {Name     string `json:"name"`Email    string `json:"email"`Username string `json:"username"`
}type Repository struct {HTMLURL string `json:"html_url"`
}type PushEvent struct {Ref        string     `json:"ref"`Commits    []Commit   `json:"commits"`Repository Repository `json:"repository"`
}

处理请求参数

func GetMessage(c *gin.Context) {body, err := io.ReadAll(c.Request.Body)if err != nil {c.JSON(500, gin.H{"error": "无法读取请求体"})return}var pushEvent PushEventerr = json.Unmarshal(body, &pushEvent)if err != nil {c.JSON(400, gin.H{"error": "JSON 解析错误"})return}var times stringvar info stringvar author stringvar link stringvar timestamp int64var sign stringnow := time.Now()// 获取时间戳(秒)timestamp = now.Unix()for _, commit := range pushEvent.Commits {// 将时间字符串解析为时间对象timeObj, err := time.Parse(time.RFC3339, commit.Timestamp)if err != nil {fmt.Println("时间解析错误:", err)continue}// 格式化时间为 "2024/01/15"formattedTime := timeObj.Format("2006/01/02")times = formattedTimeinfo = commit.Messagelink = commit.URLauthor = commit.Author.Name}

将入参读取,序列化成json,然后把json数据装回结构体,然后取出参数
并赋值
代码解耦再单独写一个推送飞书的方法,新建结构体

type MessageData struct {Timestamp int64Sign      stringAuthor    stringStash     stringBranch    stringTime      stringInfo      stringLink      string
}

func pushFeiShu(data MessageData) {
url := “https://open.feishu.cn/open-apis/bot/v2/hook/你的机器人hookid”

// 构建飞书消息体
msg := map[string]interface{}{"timestamp": data.Timestamp,"sign":      data.Sign, // 得到的签名字符串。"msg_type":  "interactive","card": map[string]interface{}{"config": map[string]interface{}{"wide_screen_mode": true,},"header": map[string]interface{}{"template": "green","title": map[string]interface{}{"tag":     "plain_text","content": fmt.Sprintf("🟢 %s推送了代码", data.Author),},},"elements": []map[string]interface{}{{"fields": []map[string]interface{}{{"is_short": false,"text": map[string]interface{}{"content": fmt.Sprintf("⚙ 目标仓库: %s", data.Stash),"tag":     "lark_md",},},{"is_short": false,"text": map[string]interface{}{"content": fmt.Sprintf("🔀 目标分支: %s", data.Branch),"tag":     "lark_md",},},{"is_short": false,"text": map[string]interface{}{"content": fmt.Sprintf("📅 推送时间: %s", data.Time),"tag":     "lark_md",},},{"is_short": false,"text": map[string]interface{}{"content": fmt.Sprintf("📝 最新提交:%s", data.Info),"tag":     "lark_md",},},},"tag": "div",},{"tag": "action","actions": []map[string]interface{}{{"tag": "button","text": map[string]interface{}{"tag":     "plain_text","content": "查看代码",},"type": "primary","multi_url": map[string]interface{}{"url": data.Link,},},},},},},
}// 将消息体转换为 JSON 字节数组
payload, err := json.Marshal(msg)
if err != nil {fmt.Println("消息体转换失败:", err)return
}// 创建一个 HTTP 请求
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload))
if err != nil {fmt.Println("创建请求失败:", err)return
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {fmt.Println("请求发送失败:", err)return
}
defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)
if err != nil {fmt.Println("读取响应失败:", err)return
}
fmt.Println("响应:", string(body))

}

push方法调用

	data := MessageData{Author:    author,Timestamp: timestamp,Sign:      sign,Stash:     pushEvent.Repository.HTMLURL,Branch:    pushEvent.Ref,Time:      times,Info:      info,Link:      link,}pushFeiShu(data)c.JSON(200, gin.H{"message": "处理成功"})

注意:
如果飞书机器人配置了验证签名则需要单独处理添加签名,代码如下

package utilsimport ("crypto/hmac""crypto/sha256""encoding/base64""fmt"
)func GenSign(secret string, timestamp int64) (string, error) {//timestamp + key 做sha256, 再进行base64 encodestringToSign := fmt.Sprintf("%v", timestamp) + "\n" + secretvar data []byteh := hmac.New(sha256.New, []byte(stringToSign))_, err := h.Write(data)if err != nil {return "", err}signature := base64.StdEncoding.EncodeToString(h.Sum(nil))return signature, nil
}

3. 配置gogs

在这里插入图片描述

添加接口地址
测试推送
在这里插入图片描述

在这里插入图片描述

相关文章:

  • 数据结构中的一棵树
  • 【b站咸虾米】chapter4_vue组件_新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握
  • 设计模式—行为型模式之观察者模式
  • 每日一题——LeetCode1304.和为零的N个不同整数
  • 本地部署轻量级web开发框架Flask并实现无公网ip远程访问开发界面
  • 一个golang小白使用vscode搭建Ununtu20.04下的go开发环境
  • HCIA vlan练习
  • Maven排除依赖 exclusions
  • 带大家做一个,易上手的家常葱爆牛肉
  • MacOS受欢迎的数据库开发工具 Navicat Premium 15 中文版
  • 二进制部署高可用k8s集群V1.20.11版本
  • nginx 搭建docker 似有hub仓库
  • SqlAlchemy使用教程(五) ORM API 编程入门
  • MetaGPT-打卡-day2,MetaGPT框架组件学习
  • 网络安全概述
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 2017 前端面试准备 - 收藏集 - 掘金
  • Angular 2 DI - IoC DI - 1
  • Centos6.8 使用rpm安装mysql5.7
  • CentOS从零开始部署Nodejs项目
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • ECMAScript入门(七)--Module语法
  • JS基础之数据类型、对象、原型、原型链、继承
  • js写一个简单的选项卡
  • Map集合、散列表、红黑树介绍
  • Markdown 语法简单说明
  • MD5加密原理解析及OC版原理实现
  • Rancher-k8s加速安装文档
  • React-redux的原理以及使用
  • spark本地环境的搭建到运行第一个spark程序
  • Vue2 SSR 的优化之旅
  • 汉诺塔算法
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 计算机常识 - 收藏集 - 掘金
  • 前端技术周刊 2019-02-11 Serverless
  • 我从编程教室毕业
  • 我的面试准备过程--容器(更新中)
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • scrapy中间件源码分析及常用中间件大全
  • #1014 : Trie树
  • #图像处理
  • $(function(){})与(function($){....})(jQuery)的区别
  • $.proxy和$.extend
  • (30)数组元素和与数字和的绝对差
  • (定时器/计数器)中断系统(详解与使用)
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (一)80c52学习之旅-起始篇
  • (转)Android学习笔记 --- android任务栈和启动模式
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .equals()到底是什么意思?
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .Net6 Api Swagger配置