diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5480842 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "kiroAgent.configureMCP": "Disabled" +} \ No newline at end of file diff --git a/README.md b/README.md index d042b5f..06abd96 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Message Nest 是一个灵活而强大的消息推送整合平台,旨在简化 如果你有很多消息推送方式,每次都需要调用各种接口去发送消息到各个渠道,或者不同的项目你都需要复制同样的发消息代码,这个项目可以帮你管理各种消息方式,并提供统一的发送api接入。你可以自由组合各种消息渠道,一个api推送到各种渠道,帮你省去接入的繁琐步骤。 -这个项目适合推送固定接受人(或者固定多个接收渠道)的场景,不适合批量群发场景。虽然也能支持群发,但是群发本身也有一定风险,不是维护的主要场景,群发的反馈不会处理。 - 演示站点(演示站点的服务器比较烂,见谅) [demo](https://message-nest-demo-site.qwapi.eu.org/) [![Hits](https://hits.sh/github.com/engigu/Message-Push-Nest.svg?view=today-total)](https://hits.sh/github.com/engigu/Message-Push-Nest/) @@ -17,6 +15,7 @@ Message Nest 是一个灵活而强大的消息推送整合平台,旨在简化 - 🔄 **整合性:** 提供了多种消息推送方式,包括邮件、钉钉、企业微信等,方便你集中管理和定制通知。 - 🎨 **自定义性:** 可以根据需求定制消息推送策略,满足不同场景的个性化需求。 - 📝 **模板化(⭐推荐):** 支持消息模板功能,通过占位符实现动态内容替换,一次定义多处复用,大幅提高开发效率和维护便利性。 +- 📧 **群发模式(🆕):** 支持动态接收者功能,可在 API 调用时指定多个接收账号,实现邮 - 🛠 **开放性:** 易于扩展和集成新的消息通知服务,以适应未来的变化。 ## 进度 🔨 diff --git a/docs/api/v1.md b/docs/api/v1.md index 438fa71..b113e13 100644 --- a/docs/api/v1.md +++ b/docs/api/v1.md @@ -51,6 +51,33 @@ POST /api/v1/message/send @提醒功能仅在支持的渠道(钉钉、企业微信)中生效。 ::: +### 动态接收者参数(可选)🆕 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| recipients | array | 否 | 动态接收者列表,如 `["user1@example.com", "user2@example.com"]` | + +::: tip 群发模式 +动态接收者功能允许在 API 调用时指定接收者列表,实现群发功能。 + +**支持的渠道:** +- ✅ **邮件** - 支持多个收件人,实现邮件群发 +- ✅ **微信公众号** - 支持多个 OpenID,实现公众号群发 + +**使用条件:** +1. 任务实例必须配置为"动态接收者模式" +2. 一个任务只能配置一个动态接收实例 +3. 动态接收实例不能与固定接收实例混合使用 + +**配置方式:** +在任务编辑页面,添加实例时勾选"动态接收者模式",此时无需配置固定接收者。 + +**注意事项:** +- 如果任务配置了动态接收实例,`recipients` 参数为必填 +- 不支持动态接收的渠道会忽略此参数 +- 建议控制接收者数量,避免触发渠道限流 +::: + ## 请求示例 ### 基本示例(纯文本) @@ -88,6 +115,22 @@ POST /api/v1/message/send } ``` +### 动态接收者示例(群发)🆕 + +```json +{ + "token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e", + "title": "系统维护通知", + "text": "系统将于今晚22:00进行维护,预计持续2小时。", + "html": "

系统维护通知

系统将于今晚22:00进行维护,预计持续2小时

", + "recipients": [ + "user1@example.com", + "user2@example.com", + "user3@example.com" + ] +} +``` + ### cURL 示例 ```bash @@ -258,14 +301,14 @@ V1 API 支持三种消息格式,系统会根据任务实例配置的格式类 ## 支持的推送渠道 -| 渠道 | 支持格式 | @提醒 | 说明 | -|------|---------|------|------| -| **邮件** | Text, HTML | ❌ | SMTP邮件发送,推荐使用 HTML 格式 | -| **钉钉** | Text, Markdown | ✅ | 钉钉机器人,支持 Markdown 富文本 | -| **企业微信** | Text, Markdown | ✅ | 企业微信机器人,支持 Markdown | -| **微信公众号** | Text | ❌ | 微信测试公众号模板消息 | -| **自定义Webhook** | Text, HTML, Markdown | ❌ | 自定义HTTP请求,格式取决于配置 | -| **自托管消息** | Text, HTML, Markdown | ❌ | 站内消息,支持多种格式 | +| 渠道 | 支持格式 | @提醒 | 动态接收者 | 说明 | +|------|---------|------|-----------|------| +| **邮件** | Text, HTML | ❌ | ✅ | SMTP邮件发送,支持群发多个收件人 | +| **钉钉** | Text, Markdown | ✅ | ❌ | 钉钉机器人,支持 Markdown 富文本 | +| **企业微信** | Text, Markdown | ✅ | ❌ | 企业微信机器人,支持 Markdown | +| **微信公众号** | Text | ❌ | ✅ | 微信测试公众号,支持多个 OpenID 群发 | +| **自定义Webhook** | Text, HTML, Markdown | ❌ | ❌ | 自定义HTTP请求,格式取决于配置 | +| **自托管消息** | Text, HTML, Markdown | ❌ | ❌ | 站内消息,支持多种格式 | ## 使用流程 diff --git a/docs/api/v2.md b/docs/api/v2.md index ac1ab3c..2e945ae 100644 --- a/docs/api/v2.md +++ b/docs/api/v2.md @@ -38,6 +38,7 @@ POST /api/v2/message/send | token | string | 是 | 加密的模板 Token | | title | string | 是 | 消息标题 | | placeholders | object | 否 | 占位符键值对 | +| recipients | array | 条件必填 | 动态接收者列表(群发模式)🆕 | ### 参数说明 @@ -59,6 +60,19 @@ POST /api/v2/message/send - 如果模板中定义了占位符但未传递,将使用默认值 - 如果既未传递也无默认值,占位符将保持原样 +#### recipients 🆕 + +- 动态接收者列表,用于群发场景 +- 格式为字符串数组:`["user1@example.com", "user2@example.com"]` +- **条件必填**:如果模板配置了动态接收实例,此参数为必填 +- **支持的渠道**: + - ✅ 邮件 - 多个收件人邮箱地址 + - ✅ 微信公众号 - 多个用户 OpenID +- **使用限制**: + - 一个模板只能配置一个动态接收实例 + - 动态接收实例不能与固定接收实例混合使用 + - 建议控制接收者数量,避免触发渠道限流 + ## 请求示例 ### 基本示例 @@ -165,6 +179,38 @@ axios.post(url, data) }); ``` +### 动态接收者示例(群发)🆕 + +```javascript +const axios = require('axios'); + +const url = 'http://your-domain/api/v2/message/send'; + +const data = { + token: 'a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b', + title: '活动通知', + placeholders: { + activity_name: '双十二大促', + start_time: '2024-12-12 00:00:00', + discount: '全场8折' + }, + recipients: [ + 'user1@example.com', + 'user2@example.com', + 'user3@example.com' + ] +}; + +axios.post(url, data) + .then(response => { + console.log(response.data); + console.log(`成功发送给 ${response.data.data.count} 个接收者`); + }) + .catch(error => { + console.error('Error:', error); + }); +``` + ### Java 示例 ```java diff --git a/docs/guide/tasks.md b/docs/guide/tasks.md index cc176a0..236d24f 100644 --- a/docs/guide/tasks.md +++ b/docs/guide/tasks.md @@ -53,14 +53,30 @@ #### 邮件渠道 -- **收件人邮箱** - 接收邮件的邮箱地址 -- **消息格式** - Text 或 HTML +- **固定模式**: + - 收件人邮箱 - 接收邮件的邮箱地址 + - 消息格式 - Text 或 HTML +- **动态接收者模式(群发)** 🆕: + - 勾选"动态接收者模式" + - 无需配置固定收件人 + - 发送时通过 API 的 `recipients` 参数指定多个收件人 + - 适用于邮件群发场景 #### 钉钉/企业微信 - **消息格式** - Text 或 Markdown - **@提醒** - 可选配置@手机号或@所有人 +#### 微信公众号 + +- **固定模式**: + - 用户 OpenID - 接收消息的用户标识 +- **动态接收者模式(群发)** 🆕: + - 勾选"动态接收者模式" + - 无需配置固定 OpenID + - 发送时通过 API 的 `recipients` 参数指定多个 OpenID + - 适用于公众号群发场景 + #### 自定义 Webhook - 根据 Webhook 要求配置相应参数 @@ -70,6 +86,13 @@ - 无需额外配置 - **消息格式** - Text、HTML 或 Markdown +::: warning 动态接收者模式限制 +1. 一个任务只能配置一个动态接收实例 +2. 动态接收实例不能与固定接收实例混合使用 +3. 如果配置了动态接收实例,API 调用时 `recipients` 参数为必填 +4. 建议控制接收者数量,避免触发渠道限流 +::: + ## 管理任务 ### 查看任务列表 @@ -190,6 +213,35 @@ curl -X POST http://your-domain/api/v1/message/send \ } ``` +### 动态接收者功能(群发)🆕 + +对于支持的渠道(邮件、微信公众号),可以使用动态接收者实现群发: + +```json +{ + "token": "your_task_token", + "title": "系统维护通知", + "text": "系统将于今晚22:00进行维护", + "html": "

系统维护通知

系统将于今晚22:00进行维护

", + "recipients": [ + "user1@example.com", + "user2@example.com", + "user3@example.com" + ] +} +``` + +**使用场景:** +- 邮件群发通知 +- 微信公众号批量推送 +- 营销活动通知 +- 系统公告发布 + +**注意事项:** +- 任务必须配置为动态接收者模式 +- 一个任务只能有一个动态接收实例 +- 建议控制接收者数量,避免触发限流 + ## 工作流程 ```mermaid diff --git a/docs/guide/template.md b/docs/guide/template.md index 89abdc4..1b34f4e 100644 --- a/docs/guide/template.md +++ b/docs/guide/template.md @@ -169,15 +169,36 @@ Markdown 格式,适用于钉钉、企业微信等支持 Markdown 的渠道: 不同渠道需要配置不同的参数: **邮件渠道:** -- 收件人邮箱地址 -- 消息格式:Text 或 HTML +- **固定模式**: + - 收件人邮箱地址 + - 消息格式:Text 或 HTML +- **动态接收者模式(群发)** 🆕: + - 勾选"动态接收者模式" + - 无需配置固定收件人 + - 发送时通过 API 的 `recipients` 参数指定多个收件人 + - 适用于邮件群发场景 **钉钉/企业微信:** - 消息格式:Text 或 Markdown +**微信公众号:** +- **固定模式**: + - 用户 OpenID +- **动态接收者模式(群发)** 🆕: + - 勾选"动态接收者模式" + - 无需配置固定 OpenID + - 发送时通过 API 的 `recipients` 参数指定多个 OpenID + **自定义 Webhook:** - 根据 Webhook 要求配置 +::: warning 动态接收者模式限制 +1. 一个模板只能配置一个动态接收实例 +2. 动态接收实例不能与固定接收实例混合使用 +3. 如果配置了动态接收实例,API 调用时 `recipients` 参数为必填 +4. 建议控制接收者数量,避免触发渠道限流 +::: + ### 3. 管理实例 - **启用/禁用** - 控制实例是否参与发送 @@ -220,6 +241,26 @@ curl -X POST http://your-domain/api/v2/message/send \ }' ``` +**动态接收者示例(群发)** 🆕: + +```bash +curl -X POST http://your-domain/api/v2/message/send \ + -H "Content-Type: application/json" \ + -d '{ + "token": "encrypted_template_token", + "title": "活动通知", + "placeholders": { + "activity_name": "双十二大促", + "discount": "全场8折" + }, + "recipients": [ + "user1@example.com", + "user2@example.com", + "user3@example.com" + ] + }' +``` + ## 最佳实践 ### 1. 占位符命名 diff --git a/go.mod b/go.mod index 3d3a63c..cfa85fc 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,10 @@ module message-nest go 1.20 require ( + github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 + github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0 + github.com/alibabacloud-go/tea v1.2.2 + github.com/alibabacloud-go/tea-utils/v2 v2.0.6 github.com/engigu/logrus-prefixed-formatter v0.5.3-0.20240113025353-498bcddfa6b5 github.com/gin-gonic/gin v1.9.1 github.com/glebarez/sqlite v1.11.0 @@ -22,11 +26,19 @@ require ( ) require ( + github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect + github.com/alibabacloud-go/debug v1.0.1 // indirect + github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect + github.com/alibabacloud-go/openapi-util v0.1.0 // indirect + github.com/alibabacloud-go/tea-utils v1.3.1 // indirect + github.com/alibabacloud-go/tea-xml v1.1.3 // indirect + github.com/aliyun/credentials-go v1.3.10 // indirect github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect github.com/bytedance/sonic v1.10.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/clbanning/mxj/v2 v2.5.5 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/structs v1.1.0 // indirect @@ -42,7 +54,6 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -55,11 +66,11 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/tidwall/gjson v1.14.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect @@ -74,8 +85,7 @@ require ( golang.org/x/text v0.21.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/ini.v1 v1.47.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect modernc.org/mathutil v1.5.0 // indirect diff --git a/go.sum b/go.sum index 4487a0d..bc16d6a 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,63 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA= +github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g= +github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= +github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8= +github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc= +github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg= +github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ= +github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= +github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= +github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= +github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg= +github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0 h1:DRd/m0TAVzmVoacUv4+C32HrpoehAPxe7Yi8jBwW5HY= +github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0/go.mod h1:XA0GIZV/FIFTuasWP6WlGolkSfH/t8J5eqxT2dHAFbE= +github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q= +github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= +github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY= +github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= +github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg= +github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU= +github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= +github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I= +github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= +github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4= +github.com/alibabacloud-go/tea-utils/v2 v2.0.6 h1:ZkmUlhlQbaDC+Eba/GARMPy6hKdCLiSke5RsN5LcyQ0= +github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= +github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= +github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.30.0 h1:uA3uhDbCxfO9+DI/DuGeAMr9qI+noVWwGPNTFuKID5M= github.com/alicebob/miniredis/v2 v2.30.0/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q= +github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= +github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= +github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= +github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA= +github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= @@ -20,6 +70,10 @@ github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E= +github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,6 +83,9 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/engigu/logrus-prefixed-formatter v0.5.3-0.20240113025353-498bcddfa6b5 h1:XRkGO/dTf/3p1SDYr/BNtDmqwLtI+jssymsCgzvqf5c= github.com/engigu/logrus-prefixed-formatter v0.5.3-0.20240113025353-498bcddfa6b5/go.mod h1:wpl/H0ZIheoONzhaJIPU5Qe+lmLxPXEdY1PNWjla63E= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -64,7 +121,11 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -73,6 +134,7 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -85,8 +147,9 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -95,6 +158,7 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -104,8 +168,6 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -123,9 +185,13 @@ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyex github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -147,6 +213,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -163,14 +230,16 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0= +github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -189,6 +258,9 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -201,7 +273,10 @@ github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= @@ -211,24 +286,60 @@ golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -239,6 +350,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -246,30 +358,64 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -283,19 +429,21 @@ google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= -gopkg.in/ini.v1 v1.47.0 h1:XAVsOWcIxjm6JVEbCbSZgSBZIF0BrCzXs4orAQr6uc8= -gopkg.in/ini.v1 v1.47.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -306,6 +454,8 @@ gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkD gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= diff --git a/models/send_ins.go b/models/send_ins.go index 1325d39..84be220 100644 --- a/models/send_ins.go +++ b/models/send_ins.go @@ -41,6 +41,12 @@ type InsCustomConfig struct { type InsMessageNestConfig struct { } +// InsAliyunSMSConfig 实例里面的阿里云短信config +type InsAliyunSMSConfig struct { + PhoneNumber string `json:"phone_number" validate:"required" label:"手机号码"` + TemplateCode string `json:"template_code" validate:"required" label:"短信模板CODE"` +} + // ManyAddTaskIns 批量添加实例 func ManyAddTaskIns(taskIns []SendTasksIns) error { tx := db.Begin() diff --git a/routers/api/v1/send_message.go b/routers/api/v1/send_message.go index d78e3a3..5f5d964 100644 --- a/routers/api/v1/send_message.go +++ b/routers/api/v1/send_message.go @@ -28,6 +28,9 @@ type SendMessageReq struct { AtMobiles []string `json:"at_mobiles" label:"@的手机号列表"` AtUserIds []string `json:"at_user_ids" label:"@的用户ID列表"` AtAll bool `json:"at_all" label:"是否@所有人"` + + // 动态接收者(用于邮箱、微信公众号等支持群发的渠道) + Recipients []string `json:"recipients" label:"接收者列表"` } // DoSendMassage 外部调用发信接口 @@ -61,17 +64,18 @@ func DoSendMassage(c *gin.Context) { } msgService := send_message_service.SendMessageService{ - SendMode: send_message_service.SendModeTask, // 明确标记为任务模式 - TaskID: taskID, - Title: req.Title, - Text: req.Text, - HTML: req.HTML, - URL: req.URL, - MarkDown: req.MarkDown, - CallerIp: c.ClientIP(), - AtMobiles: req.AtMobiles, - AtUserIds: req.AtUserIds, - AtAll: req.AtAll, + SendMode: send_message_service.SendModeTask, // 明确标记为任务模式 + TaskID: taskID, + Title: req.Title, + Text: req.Text, + HTML: req.HTML, + URL: req.URL, + MarkDown: req.MarkDown, + CallerIp: c.ClientIP(), + AtMobiles: req.AtMobiles, + AtUserIds: req.AtUserIds, + AtAll: req.AtAll, + Recipients: req.Recipients, DefaultLogger: logrus.WithFields(logrus.Fields{ "prefix": "[Send Instance]", }), diff --git a/service/send_ins_service/send_ins.go b/service/send_ins_service/send_ins.go index 0973fe9..c34d3ce 100644 --- a/service/send_ins_service/send_ins.go +++ b/service/send_ins_service/send_ins.go @@ -28,6 +28,20 @@ func (sw *SendTaskInsService) ValidateDiffIns(ins models.SendTasksIns) (string, if err != nil { return "邮箱auth反序列化失败!", empty } + + // 检查是否为动态接收者模式 + var configMap map[string]interface{} + json.Unmarshal([]byte(ins.Config), &configMap) + allowMultiRecip, exists := configMap["allowMultiRecip"].(bool) + + // allowMultiRecip=true为动态模式,to_account可以为空 + // 历史数据(不存在allowMultiRecip字段)默认为固定模式 + if exists && allowMultiRecip && emailConfig.ToAccount == "" { + // 动态模式,不验证to_account + return "", emailConfig + } + + // 固定模式或有to_account时,进行常规验证 _, Msg := app.CommonPlaygroundValid(emailConfig) return Msg, emailConfig } @@ -58,6 +72,29 @@ func (sw *SendTaskInsService) ValidateDiffIns(ins models.SendTasksIns) (string, if err != nil { return "微信公众号发送配置反序列化失败!", empty } + + // 检查是否为动态接收者模式 + var configMap map[string]interface{} + json.Unmarshal([]byte(ins.Config), &configMap) + allowMultiRecip, exists := configMap["allowMultiRecip"].(bool) + + // allowMultiRecip=true为动态模式,to_account可以为空 + // 历史数据(不存在allowMultiRecip字段)默认为固定模式 + if exists && allowMultiRecip && Config.ToAccount == "" { + // 动态模式,不验证to_account + return "", Config + } + + // 固定模式或有to_account时,进行常规验证 + _, Msg := app.CommonPlaygroundValid(Config) + return Msg, Config + } + if ins.WayType == "AliyunSMS" { + var Config models.InsAliyunSMSConfig + err := json.Unmarshal([]byte(ins.Config), &Config) + if err != nil { + return "阿里云短信配置反序列化失败!", empty + } _, Msg := app.CommonPlaygroundValid(Config) return Msg, Config } diff --git a/service/send_message_service/send_message.go b/service/send_message_service/send_message.go index a250af6..3baac5a 100644 --- a/service/send_message_service/send_message.go +++ b/service/send_message_service/send_message.go @@ -1,6 +1,7 @@ package send_message_service import ( + "encoding/json" "errors" "fmt" "message-nest/models" @@ -48,6 +49,9 @@ type SendMessageService struct { AtUserIds []string AtAll bool + // 动态接收者(用于邮箱、微信公众号等支持群发的渠道) + Recipients []string + Status int LogOutput []string @@ -253,12 +257,35 @@ func (sm *SendMessageService) Send(task models.TaskIns) (string, error) { } } - // 使用 SendUnified 方法(自动格式转换和@功能支持) - res, errMsg := channel.SendUnified(msgObj, ins.SendTasksIns, unifiedContent) - if res != "" { - sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s\n", res), sm.Status) + // 处理动态接收者(邮箱、微信公众号等支持群发的渠道) + isDynamicMode := sm.isDynamicRecipientMode(ins.SendTasksIns) + + if isDynamicMode && sm.supportsDynamicRecipient(way.Type) && len(sm.Recipients) > 0 { + // 动态接收模式:使用API传入的Recipients列表(群发) + sm.LogsAndStatusMark(fmt.Sprintf("动态接收模式,共 %d 个接收者", len(sm.Recipients)), sm.Status) + for recipientIdx, recipient := range sm.Recipients { + sm.LogsAndStatusMark(fmt.Sprintf(">>> 接收者 %d/%d: %s", recipientIdx+1, len(sm.Recipients), recipient), sm.Status) + + // 临时修改实例配置中的接收者 + modifiedIns := sm.modifyInsRecipient(ins.SendTasksIns, recipient, way.Type) + + // 使用 SendUnified 方法发送 + res, errMsg := channel.SendUnified(msgObj, modifiedIns, unifiedContent) + if res != "" { + sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status) + } else { + sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg)) + } + } } else { - sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg)) + // 固定接收模式:使用实例配置的to_account + sm.LogsAndStatusMark("固定接收模式,使用实例配置的接收者", sm.Status) + res, errMsg := channel.SendUnified(msgObj, ins.SendTasksIns, unifiedContent) + if res != "" { + sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s\n", res), sm.Status) + } else { + sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg)) + } } } @@ -366,6 +393,64 @@ func (sm *SendMessageService) BuildTemplateContent(ins models.SendTasksIns) *uni return content } +// supportsDynamicRecipient 判断渠道是否支持动态接收者 +func (sm *SendMessageService) supportsDynamicRecipient(wayType string) bool { + // 支持动态接收者的渠道类型 + supportedTypes := map[string]bool{ + unified.MessageTypeEmail: true, + unified.MessageTypeWeChatOFAccount: true, + // 可以继续添加其他支持动态接收者的渠道 + } + return supportedTypes[wayType] +} + +// isDynamicRecipientMode 判断实例是否配置为动态接收模式 +func (sm *SendMessageService) isDynamicRecipientMode(ins models.SendTasksIns) bool { + // 解析实例配置 + var config map[string]interface{} + if err := json.Unmarshal([]byte(ins.Config), &config); err != nil { + return false + } + + // 检查allowMultiRecip字段 + // allowMultiRecip=true: 动态模式 + // allowMultiRecip=false或不存在: 固定模式 + if allowMultiRecip, ok := config["allowMultiRecip"]; ok { + if allow, ok := allowMultiRecip.(bool); ok { + return allow + } + } + + // 默认为固定模式(兼容历史数据) + return false +} + +// modifyInsRecipient 临时修改实例配置中的接收者 +func (sm *SendMessageService) modifyInsRecipient(ins models.SendTasksIns, recipient string, wayType string) models.SendTasksIns { + // 创建副本 + modifiedIns := ins + + // 根据渠道类型修改配置 + var config map[string]interface{} + if err := json.Unmarshal([]byte(ins.Config), &config); err != nil { + sm.LogsAndStatusMark(fmt.Sprintf("解析实例配置失败: %s", err.Error()), SendFail) + return ins + } + + // 修改接收者字段 + config["to_account"] = recipient + + // 序列化回JSON + modifiedConfigBytes, err := json.Marshal(config) + if err != nil { + sm.LogsAndStatusMark(fmt.Sprintf("序列化实例配置失败: %s", err.Error()), SendFail) + return ins + } + + modifiedIns.Config = string(modifiedConfigBytes) + return modifiedIns +} + // GetSendMsg 获取对应消息内容(任务模式使用) // 先根据实例设置的类型取,取不到或者取到的是空,则使用text发送 func (sm *SendMessageService) GetSendMsg(ins models.SendTasksIns) (string, string) { diff --git a/service/send_message_service/unified/channel_registry.go b/service/send_message_service/unified/channel_registry.go index 5579c87..a41ce8f 100644 --- a/service/send_message_service/unified/channel_registry.go +++ b/service/send_message_service/unified/channel_registry.go @@ -24,6 +24,7 @@ const ( MessageTypeCustom = channels.MessageTypeCustom MessageTypeWeChatOFAccount = channels.MessageTypeWeChatOFAccount MessageTypeMessageNest = channels.MessageTypeMessageNest + MessageTypeAliyunSMS = channels.MessageTypeAliyunSMS ) // ChannelRegistry 渠道注册表 @@ -95,6 +96,7 @@ func GetGlobalChannelRegistry() *ChannelRegistry { globalChannelRegistry.Register(channels.NewCustomChannel()) globalChannelRegistry.Register(channels.NewWeChatOFAccountChannel()) globalChannelRegistry.Register(channels.NewMessageNestChannel()) + globalChannelRegistry.Register(channels.NewAliyunSMSChannel()) }) return globalChannelRegistry } diff --git a/service/send_message_service/unified/channels/aliyun_sms.go b/service/send_message_service/unified/channels/aliyun_sms.go new file mode 100644 index 0000000..5a0b6b8 --- /dev/null +++ b/service/send_message_service/unified/channels/aliyun_sms.go @@ -0,0 +1,106 @@ +package channels + +import ( + "encoding/json" + "fmt" + "message-nest/models" + "message-nest/service/send_ins_service" + "message-nest/service/send_way_service" + + openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" + dysmsapi "github.com/alibabacloud-go/dysmsapi-20170525/v4/client" + util "github.com/alibabacloud-go/tea-utils/v2/service" + "github.com/alibabacloud-go/tea/tea" +) + +type AliyunSMSChannel struct{ *BaseChannel } + +func NewAliyunSMSChannel() *AliyunSMSChannel { + return &AliyunSMSChannel{BaseChannel: NewBaseChannel(MessageTypeAliyunSMS, []string{FormatTypeText})} +} + +func (c *AliyunSMSChannel) SendUnified(msgObj interface{}, ins models.SendTasksIns, content *UnifiedMessageContent) (string, string) { + auth, ok := msgObj.(send_way_service.WayDetailAliyunSMS) + if !ok { + return "", "类型转换失败" + } + + insService := send_ins_service.SendTaskInsService{} + errStr, configInterface := insService.ValidateDiffIns(ins) + if errStr != "" { + return "", errStr + } + + config, ok := configInterface.(models.InsAliyunSMSConfig) + if !ok { + return "", "阿里云短信config校验失败" + } + + // 格式化内容 + _, formattedContent, err := c.FormatContent(content) + if err != nil { + return "", err.Error() + } + + // 创建阿里云短信客户端 + client, err := c.createClient(auth.AccessKeyId, auth.AccessKeySecret) + if err != nil { + return "", fmt.Sprintf("创建阿里云短信客户端失败: %s", err.Error()) + } + + // 准备模板参数 + templateParam := map[string]interface{}{ + "content": formattedContent, + } + if content.Extra != nil { + for k, v := range content.Extra { + templateParam[k] = v + } + } + + templateParamJSON, _ := json.Marshal(templateParam) + + // 发送短信 + sendSmsRequest := &dysmsapi.SendSmsRequest{ + PhoneNumbers: tea.String(config.PhoneNumber), + SignName: tea.String(auth.SignName), + TemplateCode: tea.String(config.TemplateCode), + TemplateParam: tea.String(string(templateParamJSON)), + } + + runtime := &util.RuntimeOptions{} + tryErr := func() error { + defer func() { + if r := tea.Recover(recover()); r != nil { + // 处理panic + } + }() + + response, _err := client.SendSmsWithOptions(sendSmsRequest, runtime) + if _err != nil { + return _err + } + + if response.Body.Code != nil && *response.Body.Code != "OK" { + return fmt.Errorf("发送失败: %s - %s", tea.StringValue(response.Body.Code), tea.StringValue(response.Body.Message)) + } + + return nil + }() + + if tryErr != nil { + return "", tryErr.Error() + } + + return "", "" +} + +// createClient 创建阿里云短信客户端 +func (c *AliyunSMSChannel) createClient(accessKeyId, accessKeySecret string) (*dysmsapi.Client, error) { + config := &openapi.Config{ + AccessKeyId: tea.String(accessKeyId), + AccessKeySecret: tea.String(accessKeySecret), + Endpoint: tea.String("dysmsapi.aliyuncs.com"), + } + return dysmsapi.NewClient(config) +} diff --git a/service/send_message_service/unified/channels/types.go b/service/send_message_service/unified/channels/types.go index 909b891..e2acd4f 100644 --- a/service/send_message_service/unified/channels/types.go +++ b/service/send_message_service/unified/channels/types.go @@ -15,6 +15,7 @@ const ( MessageTypeCustom = "Custom" MessageTypeWeChatOFAccount = "WeChatOFAccount" MessageTypeMessageNest = "MessageNest" + MessageTypeAliyunSMS = "AliyunSMS" ) // UnifiedMessageContent 统一的消息内容结构 diff --git a/service/send_way_service/send_way.go b/service/send_way_service/send_way.go index 6b0a7b4..1b8ef4a 100644 --- a/service/send_way_service/send_way.go +++ b/service/send_way_service/send_way.go @@ -56,6 +56,13 @@ type WeChatOFAccount struct { TempID string `json:"tempid" validate:"max=2000" label:"模板消息id"` } +// WayDetailAliyunSMS 阿里云短信渠道明细字段 +type WayDetailAliyunSMS struct { + AccessKeyId string `json:"access_key_id" validate:"required,max=100" label:"AccessKeyId"` + AccessKeySecret string `json:"access_key_secret" validate:"required,max=100" label:"AccessKeySecret"` + SignName string `json:"sign_name" validate:"required,max=50" label:"短信签名"` +} + // MessageNest 自托管消息 type MessageNest struct { } @@ -182,6 +189,14 @@ func (sw *SendWay) ValidateDiffWay() (string, interface{}) { } _, Msg := app.CommonPlaygroundValid(wca) return Msg, wca + } else if sw.Type == "AliyunSMS" { + var aliyunSMS WayDetailAliyunSMS + err := json.Unmarshal([]byte(sw.Auth), &aliyunSMS) + if err != nil { + return "阿里云短信auth反序列化失败!", empty + } + _, Msg := app.CommonPlaygroundValid(aliyunSMS) + return Msg, aliyunSMS } return fmt.Sprintf("未知的发信渠道校验: %s", sw.Type), empty } @@ -227,5 +242,9 @@ func (sw *SendWay) TestSendWay(msgObj interface{}) (string, string) { if ok { return "自托管消息不用测试运行,请直接添加", "" } + _, ok = msgObj.(WayDetailAliyunSMS) + if ok { + return "阿里云短信不用测试运行,请直接添加", "" + } return fmt.Sprintf("未知的发信渠道校验: %s", sw.Type), "" } diff --git a/web/src/components/pages/messageTemplate/TemplateApiViewer.vue b/web/src/components/pages/messageTemplate/TemplateApiViewer.vue index 664e230..3bd0dc8 100644 --- a/web/src/components/pages/messageTemplate/TemplateApiViewer.vue +++ b/web/src/components/pages/messageTemplate/TemplateApiViewer.vue @@ -1,12 +1,13 @@