Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d89b7fe8f | ||
|
|
360169ee64 | ||
|
|
59cf99ae22 | ||
|
|
74ff904598 | ||
|
|
0a68d6358d | ||
|
|
df5165d4a3 | ||
|
|
868731c95e | ||
|
|
6990166dfc | ||
|
|
fa07a6f0e4 |
@@ -101,6 +101,20 @@ cd web/frontend && npm run dev
|
|||||||
|
|
||||||
**第一个注册的用户自动成为管理员**。
|
**第一个注册的用户自动成为管理员**。
|
||||||
|
|
||||||
|
### API Key
|
||||||
|
|
||||||
|
每个用户在注册时会自动生成 API Key,可在 WebUI 的“设置”页面查看。调用需要认证的 API 时,在请求头中任选其一:
|
||||||
|
|
||||||
|
```http
|
||||||
|
X-API-Key: gb_<your-api-key>
|
||||||
|
```
|
||||||
|
|
||||||
|
或:
|
||||||
|
|
||||||
|
```http
|
||||||
|
Authorization: Bearer gb_<your-api-key>
|
||||||
|
```
|
||||||
|
|
||||||
## 数据库
|
## 数据库
|
||||||
|
|
||||||
默认 SQLite,可选 PostgreSQL,详见 [docs/database.md](docs/database.md)。
|
默认 SQLite,可选 PostgreSQL,详见 [docs/database.md](docs/database.md)。
|
||||||
|
|||||||
@@ -218,6 +218,18 @@ func HandleDeleteAccount(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查账号是否归属请求用户
|
||||||
|
ownerUID, err := getAccountOwnerUID(accountID)
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "获取账号所属用户失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ownerUID != userInfo.ID {
|
||||||
|
response.Forbidden(c, "无权限操作该账号")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 删除相关规则
|
// 删除相关规则
|
||||||
rules, err := getRulesByAccountID(accountID, userInfo.ID)
|
rules, err := getRulesByAccountID(accountID, userInfo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -59,3 +59,17 @@ func maskAccounts(accounts []model.Account) []model.Account {
|
|||||||
}
|
}
|
||||||
return masked
|
return masked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAccountOwnerUID 获取账号所属用户的 UID
|
||||||
|
func getAccountOwnerUID(accountID uint) (uint, error) {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var account model.Account
|
||||||
|
if err := gormDB.Select("uid").Where("id = ?", accountID).First(&account).Error; err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return account.UID, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package gateway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/ssdomei232/goodBaby/api/response"
|
||||||
|
"github.com/ssdomei232/goodBaby/api/user"
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/runner"
|
||||||
|
"github.com/ssdomei232/goodBaby/internal/retry"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type webhookRequest struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func token() (string, error) {
|
||||||
|
b := make([]byte, 32)
|
||||||
|
if _, err := rand.Read(b); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "gw_" + hex.EncodeToString(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleList(c *gin.Context) {
|
||||||
|
u, err := user.GetUserInfoByGinCtx(c)
|
||||||
|
if err != nil {
|
||||||
|
response.Unauthorized(c, "未登录")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbConn, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "获取网关失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var items []model.MessageGateway
|
||||||
|
if err := dbConn.Where("uid = ?", u.ID).Order("id DESC").Find(&items).Error; err != nil {
|
||||||
|
response.ServerError(c, "获取网关失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.OK(c, items)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleCreate(c *gin.Context) {
|
||||||
|
u, err := user.GetUserInfoByGinCtx(c)
|
||||||
|
if err != nil {
|
||||||
|
response.Unauthorized(c, "未登录")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req model.MessageGatewayRequest
|
||||||
|
if c.ShouldBindJSON(&req) != nil || strings.TrimSpace(req.Name) == "" {
|
||||||
|
response.BadRequest(c, "网关名称和规则不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbConn, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "创建网关失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key, err := token()
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "生成网关 Token 失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item := model.MessageGateway{UID: u.ID, Name: strings.TrimSpace(req.Name), Token: key, CreateAt: time.Now().Unix()}
|
||||||
|
if err := dbConn.Create(&item).Error; err != nil {
|
||||||
|
response.ServerError(c, "创建网关失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.OK(c, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleDelete(c *gin.Context) {
|
||||||
|
u, err := user.GetUserInfoByGinCtx(c)
|
||||||
|
if err != nil {
|
||||||
|
response.Unauthorized(c, "未登录")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dbConn, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "删除网关失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := dbConn.Where("id = ? AND uid = ?", c.Param("gatewayID"), u.ID).Delete(&model.MessageGateway{}).Error; err != nil {
|
||||||
|
response.ServerError(c, "删除网关失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.OK(c, "网关已删除")
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleWebhook(c *gin.Context) {
|
||||||
|
dbConn, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "网关不可用")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var gw model.MessageGateway
|
||||||
|
if err := dbConn.Where("token = ?", c.Param("token")).First(&gw).Error; err != nil {
|
||||||
|
response.Fail(c, http.StatusNotFound, "网关不存在")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req webhookRequest
|
||||||
|
if c.ShouldBindJSON(&req) != nil || strings.TrimSpace(req.Message) == "" {
|
||||||
|
response.BadRequest(c, "message 不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var rules []model.Rule
|
||||||
|
if err := dbConn.Where("uid = ? AND gateway_id = ? AND enabled = ?", gw.UID, gw.ID, true).Find(&rules).Error; err != nil {
|
||||||
|
response.ServerError(c, "读取网关规则失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), retry.TestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
fails := make([]string, 0)
|
||||||
|
for i := range rules {
|
||||||
|
rule := rules[i]
|
||||||
|
cfg, err := overrideMessage(rule.ConfigJson, req.Title, req.Message)
|
||||||
|
if err != nil {
|
||||||
|
fails = append(fails, rule.Name+": 规则不支持消息网关")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rule.ConfigJson = cfg
|
||||||
|
if err := runner.ExecuteRuleWithContext(ctx, &rule, "webhook"); err != nil {
|
||||||
|
fails = append(fails, rule.Name+": "+err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.OK(c, gin.H{"total": len(rules), "failed": fails})
|
||||||
|
}
|
||||||
|
|
||||||
|
func overrideMessage(raw, title, message string) (string, error) {
|
||||||
|
var obj map[string]any
|
||||||
|
if err := json.Unmarshal([]byte(raw), &obj); err != nil {
|
||||||
|
return raw, err
|
||||||
|
}
|
||||||
|
matched := false
|
||||||
|
if _, ok := obj["msg"]; ok {
|
||||||
|
obj["msg"] = message
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
if _, ok := obj["message"]; ok {
|
||||||
|
obj["message"] = message
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
if _, ok := obj["body"]; ok {
|
||||||
|
obj["body"] = message
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
return raw, fmt.Errorf("message field not found")
|
||||||
|
}
|
||||||
|
if title != "" {
|
||||||
|
if _, ok := obj["title"]; ok {
|
||||||
|
obj["title"] = title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(obj)
|
||||||
|
return string(b), err
|
||||||
|
}
|
||||||
@@ -40,6 +40,9 @@ func NotFound(c *gin.Context, msg string) { Fail(c, http.StatusNotFound, msg) }
|
|||||||
// ServerError 服务端错误
|
// ServerError 服务端错误
|
||||||
func ServerError(c *gin.Context, msg string) { Fail(c, http.StatusInternalServerError, msg) }
|
func ServerError(c *gin.Context, msg string) { Fail(c, http.StatusInternalServerError, msg) }
|
||||||
|
|
||||||
|
// Forbidden 无权限
|
||||||
|
func Forbidden(c *gin.Context, msg string) { Fail(c, http.StatusForbidden, msg) }
|
||||||
|
|
||||||
// FromError 按错误类型选择合适的状态码:
|
// FromError 按错误类型选择合适的状态码:
|
||||||
// 参数校验错误返回 400,其余返回 500
|
// 参数校验错误返回 400,其余返回 500
|
||||||
func FromError(c *gin.Context, err error, fallback string) {
|
func FromError(c *gin.Context, err error, fallback string) {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ func HandleCreateRule(c *gin.Context) {
|
|||||||
UID: userInfo.ID,
|
UID: userInfo.ID,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
TimerID: req.TimerID,
|
TimerID: req.TimerID,
|
||||||
|
GatewayID: req.GatewayID,
|
||||||
AccountID: req.AccountID,
|
AccountID: req.AccountID,
|
||||||
Type: req.Type,
|
Type: req.Type,
|
||||||
ConfigJson: req.ConfigJson,
|
ConfigJson: req.ConfigJson,
|
||||||
@@ -123,6 +124,7 @@ func HandleEditRule(c *gin.Context) {
|
|||||||
updated.Name = req.Name
|
updated.Name = req.Name
|
||||||
updated.Type = req.Type
|
updated.Type = req.Type
|
||||||
updated.TimerID = req.TimerID
|
updated.TimerID = req.TimerID
|
||||||
|
updated.GatewayID = req.GatewayID
|
||||||
updated.AccountID = req.AccountID
|
updated.AccountID = req.AccountID
|
||||||
updated.Enabled = boolOr(req.Enabled, existing.Enabled)
|
updated.Enabled = boolOr(req.Enabled, existing.Enabled)
|
||||||
// 前端提交的敏感字段可能是掩码占位符,用旧配置补回
|
// 前端提交的敏感字段可能是掩码占位符,用旧配置补回
|
||||||
@@ -162,6 +164,16 @@ func HandleDeleteRule(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ownerUID, err := getRuleOwnerUID(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
response.ServerError(c, "获取规则所属用户失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ownerUID != userInfo.ID {
|
||||||
|
response.Forbidden(c, "无权限操作该规则")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := DeleteRuleByID(ruleID, userInfo.ID); err != nil {
|
if err := DeleteRuleByID(ruleID, userInfo.ID); err != nil {
|
||||||
response.ServerError(c, "删除规则失败")
|
response.ServerError(c, "删除规则失败")
|
||||||
return
|
return
|
||||||
|
|||||||
+29
-6
@@ -59,12 +59,20 @@ func checkRuleConfigAccountAndTimerExist(rule *model.Rule, requiredAccountType s
|
|||||||
}
|
}
|
||||||
|
|
||||||
var count int64
|
var count int64
|
||||||
if err := gormDB.Model(&model.Timer{}).
|
if rule.TimerID != 0 {
|
||||||
Where("id = ? AND uid = ?", rule.TimerID, rule.UID).Count(&count).Error; err != nil {
|
if err := gormDB.Model(&model.Timer{}).Where("id = ? AND uid = ?", rule.TimerID, rule.UID).Count(&count).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return model.ErrValidation("关联的 Timer 不存在")
|
return model.ErrValidation("关联的 Timer 不存在")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := gormDB.Model(&model.MessageGateway{}).Where("id = ? AND uid = ?", rule.GatewayID, rule.UID).Count(&count).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
return model.ErrValidation("关联的消息网关不存在")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if requiredAccountType == "" {
|
if requiredAccountType == "" {
|
||||||
@@ -103,3 +111,18 @@ func maskRules(rules []model.Rule) []model.Rule {
|
|||||||
}
|
}
|
||||||
return masked
|
return masked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRuleOwnerUID 获取规则所属用户的 UID
|
||||||
|
func getRuleOwnerUID(ruleID uint) (uint, error) {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var rule model.Rule
|
||||||
|
if err := gormDB.Select("uid").Where("id = ?", ruleID).First(&rule).Error; err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rule.UID, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,3 +70,17 @@ func signTimer(timer *model.Timer) error {
|
|||||||
timer.Triggered = false
|
timer.Triggered = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getTimerOwnerUID 获取 Timer 的所属用户 ID
|
||||||
|
func getTimerOwnerUID(timerID uint) (uint, error) {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var timer model.Timer
|
||||||
|
if err := gormDB.Select("uid").Where("id = ?", timerID).First(&timer).Error; err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return timer.UID, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -48,11 +50,44 @@ func createUser(u *model.User) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
u.Password = hashedPassword
|
u.Password = hashedPassword
|
||||||
|
if u.APIKey == "" {
|
||||||
|
u.APIKey, err = generateAPIKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
u.CreateAt = time.Now().Unix()
|
u.CreateAt = time.Now().Unix()
|
||||||
|
|
||||||
return gormDB.Create(u).Error
|
return gormDB.Create(u).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateAPIKey() (string, error) {
|
||||||
|
b := make([]byte, 32)
|
||||||
|
if _, err := rand.Read(b); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "gb_" + hex.EncodeToString(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureAPIKey(user *model.User) error {
|
||||||
|
if user.APIKey != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
key, err := generateAPIKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := gormDB.Model(&model.User{}).Where("id = ? AND (api_key IS NULL OR api_key = '')", user.ID).Update("api_key", key).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
user.APIKey = key
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsUsernameTaken 用户名是否已被占用
|
// IsUsernameTaken 用户名是否已被占用
|
||||||
func IsUsernameTaken(username string) (bool, error) {
|
func IsUsernameTaken(username string) (bool, error) {
|
||||||
gormDB, err := db.GetGormDB()
|
gormDB, err := db.GetGormDB()
|
||||||
@@ -134,6 +169,9 @@ func GetUserByID(id uint) (*model.User, error) {
|
|||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := ensureAPIKey(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,6 +210,27 @@ func HandleUpdateNotifyConfig(c *gin.Context) {
|
|||||||
// AuthMiddleware 认证中间件,同时把当前用户放进 context 供后续 handler 复用
|
// AuthMiddleware 认证中间件,同时把当前用户放进 context 供后续 handler 复用
|
||||||
func AuthMiddleware() gin.HandlerFunc {
|
func AuthMiddleware() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
apiKey := c.GetHeader("X-API-Key")
|
||||||
|
if apiKey == "" {
|
||||||
|
auth := c.GetHeader("Authorization")
|
||||||
|
const prefix = "Bearer "
|
||||||
|
if len(auth) > len(prefix) && auth[:len(prefix)] == prefix {
|
||||||
|
apiKey = auth[len(prefix):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if apiKey != "" {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err == nil {
|
||||||
|
var user model.User
|
||||||
|
if gormDB.Where("api_key = ?", apiKey).First(&user).Error == nil {
|
||||||
|
c.Set(contextKey, &user)
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.AbortWith(c, http.StatusUnauthorized, "API Key 无效")
|
||||||
|
return
|
||||||
|
}
|
||||||
session := sessions.Default(c)
|
session := sessions.Default(c)
|
||||||
uid, ok := session.Get("uid").(uint)
|
uid, ok := session.Get("uid").(uint)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package alidns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/alibabacloud-go/alidns-20150109/v5/client"
|
||||||
|
"github.com/ssdomei232/goodBaby/internal/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AliDNSAccountConfigValidator struct{}
|
||||||
|
|
||||||
|
func (v *AliDNSAccountConfigValidator) GetType() string { return AccountType }
|
||||||
|
|
||||||
|
func (v *AliDNSAccountConfigValidator) Validate(config string) error {
|
||||||
|
cfg, err := parseAccount(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if cfg.AK == "" || cfg.SK == "" {
|
||||||
|
return fmt.Errorf("阿里云账号配置不完整")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseAccount(config string) (*AliDNSAccount, error) {
|
||||||
|
var cfg AliDNSAccount
|
||||||
|
if err := json.Unmarshal([]byte(config), &cfg); err != nil {
|
||||||
|
return nil, fmt.Errorf("解析阿里云账号配置失败: %v", err)
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *AliDNSAccountConfigValidator) Test(config string) error {
|
||||||
|
cfg, err := parseAccount(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
aliDNSClient, err := getAliDNSClient(cfg.AK, cfg.SK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = aliDNSClient.DescribeDnsProductInstances(&client.DescribeDnsProductInstancesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *AliDNSAccountConfigValidator) Meta() meta.AccountMeta {
|
||||||
|
return meta.AccountMeta{
|
||||||
|
Type: AccountType,
|
||||||
|
Label: "阿里云",
|
||||||
|
Description: "阿里云国内站",
|
||||||
|
Fields: []meta.Field{
|
||||||
|
{Key: "ak", Label: "Access Key", Type: meta.FieldPassword, Required: true, Secret: true, Placeholder: "xxxxxxxxx"},
|
||||||
|
{Key: "sk", Label: "Secret Key", Type: meta.FieldPassword, Required: true, Secret: true, Placeholder: "xxxxxxxxx"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package alidns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/alibabacloud-go/alidns-20150109/v5/client"
|
||||||
|
"github.com/ssdomei232/goodBaby/internal/retry"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// deleteAliDNSRecord deletes a DNS record from Alibaba Cloud DNS based on the provided rule.
|
||||||
|
func deleteAliDNSRecord(ctx context.Context, rule *model.Rule) error {
|
||||||
|
aliDNSClient, err := getAliDNSClientFromRule(rule)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
deleteRecordConfig, err := getDeleteRecordConfig(rule)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := retry.Do(ctx, func() error {
|
||||||
|
_, err := aliDNSClient.DeleteDomainRecord(&client.DeleteDomainRecordRequest{
|
||||||
|
RecordId: &deleteRecordConfig.RecordID,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("删除阿里云DNS记录失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package alidns
|
||||||
|
|
||||||
|
const (
|
||||||
|
AccountType = "alidns"
|
||||||
|
RuleTypeDeleteRecord = "alidns-delete-record"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AliDNSAccount struct {
|
||||||
|
AK string `json:"ak"`
|
||||||
|
SK string `json:"sk"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteRecordConfig struct {
|
||||||
|
RecordID string `json:"record_id"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package alidns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/internal/meta"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 阿里云删除记录规则验证器
|
||||||
|
type AliDNSDeleteRecordRuleValidator struct{}
|
||||||
|
|
||||||
|
func (v *AliDNSDeleteRecordRuleValidator) GetType() string {
|
||||||
|
return RuleTypeDeleteRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *AliDNSDeleteRecordRuleValidator) Validate(configJSON string) error {
|
||||||
|
var config DeleteRecordConfig
|
||||||
|
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
|
||||||
|
return fmt.Errorf("解析阿里云删除记录规则配置失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.RecordID == "" {
|
||||||
|
return fmt.Errorf("阿里云删除记录规则配置中 record_id 不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *AliDNSDeleteRecordRuleValidator) Meta() meta.RuleMeta {
|
||||||
|
return meta.RuleMeta{
|
||||||
|
Type: RuleTypeDeleteRecord,
|
||||||
|
Label: "删除阿里云DNS解析记录",
|
||||||
|
Description: "触发时删除阿里云DNS解析记录",
|
||||||
|
AccountType: AccountType,
|
||||||
|
Fields: []meta.Field{
|
||||||
|
{Key: "record_id", Label: "记录ID", Type: meta.FieldString, Required: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package alidns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteAliDNSRecordExecutor 删除阿里云DNS记录执行器
|
||||||
|
type DeleteAliDNSRecordExecutor struct{}
|
||||||
|
|
||||||
|
func (e *DeleteAliDNSRecordExecutor) GetType() string {
|
||||||
|
return RuleTypeDeleteRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DeleteAliDNSRecordExecutor) Execute(ctx context.Context, rule *model.Rule) error {
|
||||||
|
log.Printf("执行删除阿里云DNS记录规则: %s (ID: %d)", rule.Name, rule.ID)
|
||||||
|
|
||||||
|
return deleteAliDNSRecord(ctx, rule)
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package alidns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
alidns "github.com/alibabacloud-go/alidns-20150109/v5/client"
|
||||||
|
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||||
|
"github.com/alibabacloud-go/tea/tea"
|
||||||
|
"github.com/aliyun/credentials-go/credentials"
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getAliDNSClient initializes and returns an Alibaba Cloud DNS client based on the provided rule's account configuration. It retrieves the account configuration from the database, sets up the necessary credentials, and creates a new client instance for interacting with Alibaba Cloud DNS services.
|
||||||
|
func getAliDNSClientFromRule(rule *model.Rule) (client *alidns.Client, err error) {
|
||||||
|
var accountConfig AliDNSAccount
|
||||||
|
|
||||||
|
// get config
|
||||||
|
if err := db.LoadAccountConfig(rule.AccountID, &accountConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAliDNSClient(accountConfig.AK, accountConfig.SK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAliDNSClient(ak string, sk string) (client *alidns.Client, err error) {
|
||||||
|
// init aliyun account config
|
||||||
|
credentialsConfig := new(credentials.Config).
|
||||||
|
SetType("access_key").
|
||||||
|
SetAccessKeyId(ak).
|
||||||
|
SetAccessKeySecret(sk)
|
||||||
|
akCredential, err := credentials.NewCredential(credentialsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config := &openapi.Config{}
|
||||||
|
config.Credential = akCredential
|
||||||
|
config.Endpoint = tea.String("alidns.aliyuncs.com")
|
||||||
|
|
||||||
|
// create aliyun account client
|
||||||
|
client, _ = alidns.NewClient(config)
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDeleteRecordConfig retrieves the configuration for deleting DNS records from the provided rule. It unmarshals the rule's configuration JSON into a DeleteRecordConfig structure and returns it.
|
||||||
|
func getDeleteRecordConfig(rule *model.Rule) (*DeleteRecordConfig, error) {
|
||||||
|
var deleteRecordConfig DeleteRecordConfig
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(rule.ConfigJson), &deleteRecordConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &deleteRecordConfig, nil
|
||||||
|
}
|
||||||
@@ -12,9 +12,7 @@ import (
|
|||||||
// RainyunAccountConfigValidator Rainyun账号配置验证器
|
// RainyunAccountConfigValidator Rainyun账号配置验证器
|
||||||
type RainyunAccountConfigValidator struct{}
|
type RainyunAccountConfigValidator struct{}
|
||||||
|
|
||||||
func (v *RainyunAccountConfigValidator) GetType() string {
|
func (v *RainyunAccountConfigValidator) GetType() string { return AccountType }
|
||||||
return AccountType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *RainyunAccountConfigValidator) Validate(config string) error {
|
func (v *RainyunAccountConfigValidator) Validate(config string) error {
|
||||||
// 解析配置
|
// 解析配置
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package rainyun
|
|||||||
const (
|
const (
|
||||||
// AccountType Rainyun 账号类型标识
|
// AccountType Rainyun 账号类型标识
|
||||||
AccountType = "rainyun"
|
AccountType = "rainyun"
|
||||||
// RuleType 发送 Rainyun 消息的规则类型标识
|
// RuleTypeWorkOrder 发送 Rainyun 工单消息的规则类型标识
|
||||||
RuleType = "rainyun-workorder"
|
RuleTypeWorkOrder = "rainyun-workorder"
|
||||||
|
RuleTypeRunAway = "rainyun-runaway"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RainyunWorkOrderRule struct {
|
type RainyunWorkOrderRule struct {
|
||||||
@@ -15,3 +16,7 @@ type RainyunWorkOrderRule struct {
|
|||||||
type RainyunAccount struct {
|
type RainyunAccount struct {
|
||||||
APIKey string `json:"api_key"`
|
APIKey string `json:"api_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RainyunRunAwayRule struct {
|
||||||
|
IK string `json:"ik"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,13 +2,18 @@ package rainyun
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/internal/retry"
|
||||||
"github.com/ssdomei232/goodBaby/model"
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
rain "github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/common"
|
rain "github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/common"
|
||||||
|
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/rcs"
|
||||||
|
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/rgs"
|
||||||
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/workorder"
|
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/workorder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sendRainyunWorkorderMsg(ctx context.Context, rule *model.Rule) error {
|
func SendRainyunWorkorderMsg(ctx context.Context, rule *model.Rule) error {
|
||||||
rainyunConfig, err := getRainyunConfigFromRule(rule)
|
rainyunConfig, err := getRainyunConfigFromRule(rule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -19,14 +24,26 @@ func sendRainyunWorkorderMsg(ctx context.Context, rule *model.Rule) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = retry.Do(ctx, func() error {
|
||||||
|
return sendRainyunWorkorderMsg(rainyunConfig, rainyunAccount)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendRainyunWorkorderMsg(rainyunRuleConfig *RainyunWorkOrderRule, rainyunAccount *RainyunAccount) error {
|
||||||
client := rain.NewClient(rainyunAccount.APIKey)
|
client := rain.NewClient(rainyunAccount.APIKey)
|
||||||
workorderClient := workorder.Client{Client: client}
|
workorderClient := workorder.Client{Client: client}
|
||||||
|
|
||||||
_, err = workorderClient.CreateWorkOrder(&workorder.CreateWorkerorderRequest{
|
_, err := workorderClient.CreateWorkOrder(&workorder.CreateWorkerorderRequest{
|
||||||
Content: rainyunConfig.Msg,
|
Content: rainyunRuleConfig.Msg,
|
||||||
IsAuthed: false,
|
IsAuthed: false,
|
||||||
IsUrgent: 1,
|
IsUrgent: 1,
|
||||||
Title: rainyunConfig.Title,
|
Title: rainyunRuleConfig.Title,
|
||||||
Type: "reward",
|
Type: "reward",
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -36,3 +53,74 @@ func sendRainyunWorkorderMsg(ctx context.Context, rule *model.Rule) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RainyunRunAway(ctx context.Context, rule *model.Rule) error {
|
||||||
|
rainyunAccount, err := getRainyunAccountFromRule(rule)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client := rain.NewClient(rainyunAccount.APIKey)
|
||||||
|
|
||||||
|
var fails []string
|
||||||
|
total := 0
|
||||||
|
|
||||||
|
// 重装所有RCS
|
||||||
|
rcsClient := rcs.Client{Client: client}
|
||||||
|
options := rain.EncodingStandardQueryParameters(1, 20)
|
||||||
|
rcsList, err := rcsClient.GetRcsList(options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rcsList.Data.TotalRecords == 0 {
|
||||||
|
return nil
|
||||||
|
} else if rcsList.Data.TotalRecords > 20 {
|
||||||
|
rcsTotal := rcsList.Data.TotalRecords
|
||||||
|
options := rain.EncodingStandardQueryParameters(1, rcsTotal)
|
||||||
|
rcsList, err = rcsClient.GetRcsList(options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, rcs := range rcsList.Data.Records {
|
||||||
|
total++
|
||||||
|
err := retry.Do(context.Background(), func() error {
|
||||||
|
return reinstallOneRCS(rcs.ID, &rcsClient)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fails = append(fails, fmt.Sprintf("RCS %d: %v", rcs.ID, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重装所有RGS
|
||||||
|
rgsClient := rgs.Client{Client: client}
|
||||||
|
rgsOptions := rain.EncodingStandardQueryParameters(1, 20)
|
||||||
|
rgsList, err := rgsClient.GetRgsList(rgsOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rgsList.Data.TotalRecords == 0 {
|
||||||
|
return nil
|
||||||
|
} else if rgsList.Data.TotalRecords > 20 {
|
||||||
|
rgsTotal := rgsList.Data.TotalRecords
|
||||||
|
rgsOptions := rain.EncodingStandardQueryParameters(1, rgsTotal)
|
||||||
|
rgsList, err = rgsClient.GetRgsList(rgsOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, rgs := range rgsList.Data.Records {
|
||||||
|
total++
|
||||||
|
err := retry.Do(context.Background(), func() error {
|
||||||
|
return reinstallOneRGS(rgs.ID, &rgsClient)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fails = append(fails, fmt.Sprintf("RGS %d: %v", rgs.ID, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fails) > 0 {
|
||||||
|
return fmt.Errorf("%d/%d 台云服务器重装失败: %s", len(fails), total, strings.Join(fails, "; "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
type RainyunWorkorderRuleValidator struct{}
|
type RainyunWorkorderRuleValidator struct{}
|
||||||
|
|
||||||
func (v *RainyunWorkorderRuleValidator) GetType() string {
|
func (v *RainyunWorkorderRuleValidator) GetType() string {
|
||||||
return RuleType
|
return RuleTypeWorkOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *RainyunWorkorderRuleValidator) Validate(configJSON string) error {
|
func (v *RainyunWorkorderRuleValidator) Validate(configJSON string) error {
|
||||||
@@ -33,9 +33,9 @@ func (v *RainyunWorkorderRuleValidator) Validate(configJSON string) error {
|
|||||||
|
|
||||||
func (v *RainyunWorkorderRuleValidator) Meta() meta.RuleMeta {
|
func (v *RainyunWorkorderRuleValidator) Meta() meta.RuleMeta {
|
||||||
return meta.RuleMeta{
|
return meta.RuleMeta{
|
||||||
Type: RuleType,
|
Type: RuleTypeWorkOrder,
|
||||||
Label: "发送雨云工单",
|
Label: "发送雨云工单",
|
||||||
Description: "触发时通过雨云向指定的工单系统发送工单。",
|
Description: "触发时发送雨云工单",
|
||||||
AccountType: AccountType,
|
AccountType: AccountType,
|
||||||
Fields: []meta.Field{
|
Fields: []meta.Field{
|
||||||
{Key: "title", Label: "工单标题", Type: meta.FieldTextarea, Required: true},
|
{Key: "title", Label: "工单标题", Type: meta.FieldTextarea, Required: true},
|
||||||
@@ -43,3 +43,34 @@ func (v *RainyunWorkorderRuleValidator) Meta() meta.RuleMeta {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RainyunRunAwayRuleValidator struct{}
|
||||||
|
|
||||||
|
func (v *RainyunRunAwayRuleValidator) GetType() string {
|
||||||
|
return RuleTypeRunAway
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *RainyunRunAwayRuleValidator) Validate(configJSON string) error {
|
||||||
|
var config RainyunRunAwayRule
|
||||||
|
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
|
||||||
|
return fmt.Errorf("解析雨云规则配置失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.IK != "我已知晓" {
|
||||||
|
return fmt.Errorf("请输入正确内容")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *RainyunRunAwayRuleValidator) Meta() meta.RuleMeta {
|
||||||
|
return meta.RuleMeta{
|
||||||
|
Type: RuleTypeRunAway,
|
||||||
|
Label: "重置雨云账号中所有云服务器(一键跑路)",
|
||||||
|
Description: "触发时会重装雨云账号下所有云服务器来实现跑路",
|
||||||
|
AccountType: AccountType,
|
||||||
|
Fields: []meta.Field{
|
||||||
|
{Key: "ik", Label: "免责声明", Type: meta.FieldTextarea, Required: true, Placeholder: "该操作引发的损失及法律责任归属账号所有人,本软件一律不承担,请输入\"我已知晓\""},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,11 +11,23 @@ import (
|
|||||||
type RainyunWorkorderExecutor struct{}
|
type RainyunWorkorderExecutor struct{}
|
||||||
|
|
||||||
func (e *RainyunWorkorderExecutor) GetType() string {
|
func (e *RainyunWorkorderExecutor) GetType() string {
|
||||||
return RuleType
|
return RuleTypeWorkOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *RainyunWorkorderExecutor) Execute(ctx context.Context, rule *model.Rule) error {
|
func (e *RainyunWorkorderExecutor) Execute(ctx context.Context, rule *model.Rule) error {
|
||||||
log.Printf("执行雨云工单规则: %s", rule.Name)
|
log.Printf("执行雨云工单规则: %s", rule.Name)
|
||||||
|
|
||||||
return sendRainyunWorkorderMsg(ctx, rule)
|
return SendRainyunWorkorderMsg(ctx, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RainyunRunAwayExecutor 雨云跑路执行器
|
||||||
|
type RainyunRunAwayExecutor struct{}
|
||||||
|
|
||||||
|
func (e *RainyunRunAwayExecutor) GetType() string {
|
||||||
|
return RuleTypeRunAway
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *RainyunRunAwayExecutor) Execute(ctx context.Context, rule *model.Rule) error {
|
||||||
|
log.Printf("执行雨云跑路规则: %s", rule.Name)
|
||||||
|
return RainyunRunAway(ctx, rule)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import (
|
|||||||
|
|
||||||
"github.com/ssdomei232/goodBaby/handler/db"
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
"github.com/ssdomei232/goodBaby/model"
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/public"
|
||||||
|
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/rcs"
|
||||||
|
"github.com/ssdomei232/rainyun-go-sdk/v2/rainyun/rgs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 从 Rule 中获取 RainyunConfig
|
// 从 Rule 中获取 RainyunConfig
|
||||||
@@ -25,3 +28,57 @@ func getRainyunAccountFromRule(rule *model.Rule) (*RainyunAccount, error) {
|
|||||||
}
|
}
|
||||||
return &rainyunAccount, nil
|
return &rainyunAccount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reinstallOneRCS(rcsID int, rcsClient *rcs.Client) error {
|
||||||
|
rcsDetail, err := rcsClient.GetRcsDetails(rcsID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rcsOSList, err := public.GetRcsOSList()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, os := range rcsOSList.Data {
|
||||||
|
if os.Region == rcsDetail.Data.Data.Node.Region && os.OsType == "linux" {
|
||||||
|
rcsReinstallRequest := &rcs.ReinstallRcsRequest{
|
||||||
|
OsID: os.ID,
|
||||||
|
ResetOsd: true,
|
||||||
|
}
|
||||||
|
_, err := rcsClient.ReinstallRcs(rcsID, rcsReinstallRequest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reinstallOneRGS(rgsID int, rgsClient *rgs.Client) error {
|
||||||
|
rgsDetail, err := rgsClient.GetRgsDetails(rgsID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rgsOSList, err := public.GetRgsOSList()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, os := range rgsOSList.Data {
|
||||||
|
if os.Region == rgsDetail.Data.Data.Node.Region && os.OsType == "linux" {
|
||||||
|
rgsReinstallRequest := &rcs.ReinstallRcsRequest{
|
||||||
|
OsID: os.ID,
|
||||||
|
ResetOsd: true,
|
||||||
|
}
|
||||||
|
_, err := rgsClient.Reinstallgs(rgsID, rgsReinstallRequest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ go 1.25.0
|
|||||||
require (
|
require (
|
||||||
github.com/CatchZeng/dingtalk v1.5.0
|
github.com/CatchZeng/dingtalk v1.5.0
|
||||||
github.com/CuteReimu/bilibili/v2 v2.3.5
|
github.com/CuteReimu/bilibili/v2 v2.3.5
|
||||||
|
github.com/alibabacloud-go/alidns-20150109/v5 v5.6.0
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi v0.2.1
|
||||||
|
github.com/alibabacloud-go/tea v1.5.2
|
||||||
|
github.com/aliyun/credentials-go v1.4.5
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3
|
github.com/cenkalti/backoff/v5 v5.0.3
|
||||||
github.com/gin-contrib/sessions v1.0.4
|
github.com/gin-contrib/sessions v1.0.4
|
||||||
github.com/gin-gonic/gin v1.11.0
|
github.com/gin-gonic/gin v1.11.0
|
||||||
@@ -13,7 +17,7 @@ require (
|
|||||||
github.com/google/go-github/v84 v84.0.0
|
github.com/google/go-github/v84 v84.0.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/ssdomei232/napcat-http-go-sdk v1.0.0
|
github.com/ssdomei232/napcat-http-go-sdk v1.0.0
|
||||||
github.com/ssdomei232/rainyun-go-sdk/v2 v2.0.5
|
github.com/ssdomei232/rainyun-go-sdk/v2 v2.0.6
|
||||||
github.com/wneessen/go-mail v0.7.2
|
github.com/wneessen/go-mail v0.7.2
|
||||||
golang.org/x/crypto v0.48.0
|
golang.org/x/crypto v0.48.0
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
@@ -22,8 +26,16 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f // indirect
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f // indirect
|
||||||
|
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi/v2 v2.2.4 // indirect
|
||||||
|
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||||
|
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
|
||||||
|
github.com/alibabacloud-go/tea-utils v1.4.3 // indirect
|
||||||
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.9 // indirect
|
||||||
|
github.com/alibabacloud-go/tea-xml v1.1.2 // indirect
|
||||||
github.com/bytedance/sonic v1.14.0 // indirect
|
github.com/bytedance/sonic v1.14.0 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||||
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||||
@@ -39,6 +51,7 @@ require (
|
|||||||
github.com/gorilla/context v1.1.2 // indirect
|
github.com/gorilla/context v1.1.2 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/gorilla/sessions v1.4.0 // indirect
|
github.com/gorilla/sessions v1.4.0 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
||||||
@@ -59,6 +72,7 @@ require (
|
|||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||||
github.com/spf13/cast v1.9.2 // indirect
|
github.com/spf13/cast v1.9.2 // indirect
|
||||||
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
@@ -70,6 +84,7 @@ require (
|
|||||||
golang.org/x/text v0.34.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
golang.org/x/tools v0.42.0 // indirect
|
golang.org/x/tools v0.42.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.9 // indirect
|
google.golang.org/protobuf v1.36.9 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
modernc.org/libc v1.22.5 // indirect
|
modernc.org/libc v1.22.5 // indirect
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
modernc.org/memory v1.5.0 // indirect
|
modernc.org/memory v1.5.0 // indirect
|
||||||
|
|||||||
@@ -1,24 +1,89 @@
|
|||||||
bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI=
|
bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI=
|
||||||
bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA=
|
bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA=
|
||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII=
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII=
|
||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/CatchZeng/dingtalk v1.5.0 h1:3YNpGIdeZ4pTfjjVyC2G1CCzWocMmYniBY8CXiOY9Ss=
|
github.com/CatchZeng/dingtalk v1.5.0 h1:3YNpGIdeZ4pTfjjVyC2G1CCzWocMmYniBY8CXiOY9Ss=
|
||||||
github.com/CatchZeng/dingtalk v1.5.0/go.mod h1:/CT0Eskr26XfjAybLBLV+DjvPHaznwiFXRBndQp7zZ8=
|
github.com/CatchZeng/dingtalk v1.5.0/go.mod h1:/CT0Eskr26XfjAybLBLV+DjvPHaznwiFXRBndQp7zZ8=
|
||||||
github.com/CuteReimu/bilibili/v2 v2.3.5 h1:0MpBOJL6Q7kP3lFItC7NQ3MLG/I1uIzZBjemXIE0CRM=
|
github.com/CuteReimu/bilibili/v2 v2.3.5 h1:0MpBOJL6Q7kP3lFItC7NQ3MLG/I1uIzZBjemXIE0CRM=
|
||||||
github.com/CuteReimu/bilibili/v2 v2.3.5/go.mod h1:FHKH1cc04M/qpQhF+DaFIBFleLtvgMwYfZCNhHK/kBQ=
|
github.com/CuteReimu/bilibili/v2 v2.3.5/go.mod h1:FHKH1cc04M/qpQhF+DaFIBFleLtvgMwYfZCNhHK/kBQ=
|
||||||
|
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/alidns-20150109/v5 v5.6.0 h1:dfHe5OpLz/vGINeU8ZOB1Y0dANk4+Td023zMaf+8rew=
|
||||||
|
github.com/alibabacloud-go/alidns-20150109/v5 v5.6.0/go.mod h1:1tXuCJoXdeAY9uBxgJ6ZLbv+SOe/4SJhUMSNCz9pOng=
|
||||||
|
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 v0.2.1 h1:WyzxxKvhdVDlwpAMOHgAiCJ+NXa6g5ZWPFEzaK/ewwY=
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi v0.2.1/go.mod h1:zXOqLbpIqq543oioL9IuuZYOQgHQ5B8/n5OPrnko8aY=
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi/v2 v2.2.4 h1:o6veen0IZ/Fe1JawwhwQMZcbw67CVDY1pQwXcNWPyQo=
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi/v2 v2.2.4/go.mod h1:eHjVxrT9g8uVYN/nyAwOFQEfkVA154ChiqRc2XnNKYU=
|
||||||
|
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.0/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
|
||||||
|
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/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.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
|
||||||
|
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.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||||
|
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||||
|
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
|
||||||
|
github.com/alibabacloud-go/tea v1.5.2 h1:DUzV/cRTbJC++rmADfqVu//GuWbaD64ZJ3yW3v2ukNU=
|
||||||
|
github.com/alibabacloud-go/tea v1.5.2/go.mod h1:hgSs82CkOiehSQMoiFN79dL6zsGX7pVGvnn9SIEs8/0=
|
||||||
|
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||||
|
github.com/alibabacloud-go/tea-utils v1.4.3 h1:8SzwmmRrOnQ09Hf5a9GyfJc0d7Sjv6fmsZoF4UDbFjo=
|
||||||
|
github.com/alibabacloud-go/tea-utils v1.4.3/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
|
||||||
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
|
||||||
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.9 h1:y6pUIlhjxbZl9ObDAcmA1H3c21eaAxADHTDQmBnAIgA=
|
||||||
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.9/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||||
|
github.com/alibabacloud-go/tea-xml v1.1.2 h1:oLxa7JUXm2EDFzMg+7oRsYc+kutgCVwm+bZlhhmvW5M=
|
||||||
|
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||||
|
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.4.5 h1:O76WYKgdy1oQYYiJkERjlA2dxGuvLRrzuO2ScrtGWSk=
|
||||||
|
github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||||
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||||
|
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||||
|
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||||
|
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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
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/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||||
@@ -47,8 +112,23 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
|||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
|
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/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
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=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
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=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
@@ -63,12 +143,16 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu
|
|||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
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/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-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
|
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
|
||||||
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
|
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
|
||||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
@@ -81,12 +165,16 @@ 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/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 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
@@ -98,14 +186,18 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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 h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
||||||
@@ -119,52 +211,195 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV
|
|||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
|
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
|
||||||
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||||
github.com/ssdomei232/napcat-http-go-sdk v1.0.0 h1:BY3iqqlZw5letiCwTmfMrhyqsx0a96eL5LpDuinnOSE=
|
github.com/ssdomei232/napcat-http-go-sdk v1.0.0 h1:BY3iqqlZw5letiCwTmfMrhyqsx0a96eL5LpDuinnOSE=
|
||||||
github.com/ssdomei232/napcat-http-go-sdk v1.0.0/go.mod h1:yPsSaMs3OyKMVPXwIs5ZB5G532vRi1GvL/WiWUEwblU=
|
github.com/ssdomei232/napcat-http-go-sdk v1.0.0/go.mod h1:yPsSaMs3OyKMVPXwIs5ZB5G532vRi1GvL/WiWUEwblU=
|
||||||
github.com/ssdomei232/rainyun-go-sdk/v2 v2.0.5 h1:T30N4npW+U10IlZeQ8SooJi9V42uM+f+lrFPRRftHeg=
|
github.com/ssdomei232/rainyun-go-sdk/v2 v2.0.6 h1:tjratVKpPk3lc2bw+oVnIzVZG79mFlvUBez+FbX86pQ=
|
||||||
github.com/ssdomei232/rainyun-go-sdk/v2 v2.0.5/go.mod h1:Wf9X0qEpKQ1/uD4iUGGoPLHydiCxULqCVk+JCoVqdIg=
|
github.com/ssdomei232/rainyun-go-sdk/v2 v2.0.6/go.mod h1:Wf9X0qEpKQ1/uD4iUGGoPLHydiCxULqCVk+JCoVqdIg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
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/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8=
|
github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8=
|
||||||
github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
|
github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
|
||||||
|
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.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
|
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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
|
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.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
|
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
|
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.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/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||||
|
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-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-20201010224723-4f7140c49acb/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-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.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
|
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/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
|
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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/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-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.12.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.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||||
|
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.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
|
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.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
|
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||||
|
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.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.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
|
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||||
|
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=
|
||||||
|
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=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -172,6 +407,8 @@ gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
|||||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||||
|
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 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||||
|
|||||||
@@ -138,5 +138,6 @@ func AutoMigrate(gormDB *gorm.DB) error {
|
|||||||
&model.Rule{},
|
&model.Rule{},
|
||||||
&model.Account{},
|
&model.Account{},
|
||||||
&model.ExecutionLog{},
|
&model.ExecutionLog{},
|
||||||
|
&model.MessageGateway{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,6 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/bilibili"
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/email"
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/fwalert"
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/github"
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/onebot"
|
|
||||||
"github.com/ssdomei232/goodBaby/drivers/rainyun"
|
|
||||||
"github.com/ssdomei232/goodBaby/model"
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,27 +59,6 @@ var (
|
|||||||
globalExecutorRegistry *ExecutorRegistry
|
globalExecutorRegistry *ExecutorRegistry
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitExecutorRegistry 初始化执行器注册表并注册所有执行器
|
|
||||||
func InitExecutorRegistry() *ExecutorRegistry {
|
|
||||||
registryOnce.Do(func() {
|
|
||||||
registry := NewExecutorRegistry()
|
|
||||||
|
|
||||||
// 注册所有规则执行器
|
|
||||||
registry.Register(&bilibili.BilibiliDynamicExecutor{})
|
|
||||||
registry.Register(&bilibili.BilibiliPrivateMessageExecutor{})
|
|
||||||
registry.Register(&email.EmailExecutor{})
|
|
||||||
registry.Register(&github.GithubMakeRepoPublicExecutor{})
|
|
||||||
registry.Register(&onebot.OneBotExecutor{})
|
|
||||||
registry.Register(&dingtalk.DingTalkExecutor{})
|
|
||||||
registry.Register(&fwalert.FwalertExecutor{})
|
|
||||||
registry.Register(&rainyun.RainyunWorkorderExecutor{})
|
|
||||||
// 未来添加新规则类型时,在这里注册即可
|
|
||||||
|
|
||||||
globalExecutorRegistry = registry
|
|
||||||
})
|
|
||||||
return globalExecutorRegistry
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetGlobalExecutorRegistry 获取全局执行器注册表
|
// GetGlobalExecutorRegistry 获取全局执行器注册表
|
||||||
func GetGlobalExecutorRegistry() *ExecutorRegistry {
|
func GetGlobalExecutorRegistry() *ExecutorRegistry {
|
||||||
if globalExecutorRegistry == nil {
|
if globalExecutorRegistry == nil {
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package runner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/alidns"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/bilibili"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/email"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/fwalert"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/github"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/onebot"
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/rainyun"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InitExecutorRegistry 初始化执行器注册表并注册所有执行器
|
||||||
|
func InitExecutorRegistry() *ExecutorRegistry {
|
||||||
|
registryOnce.Do(func() {
|
||||||
|
registry := NewExecutorRegistry()
|
||||||
|
|
||||||
|
// 注册所有规则执行器
|
||||||
|
registry.Register(&bilibili.BilibiliDynamicExecutor{})
|
||||||
|
registry.Register(&bilibili.BilibiliPrivateMessageExecutor{})
|
||||||
|
registry.Register(&email.EmailExecutor{})
|
||||||
|
registry.Register(&github.GithubMakeRepoPublicExecutor{})
|
||||||
|
registry.Register(&onebot.OneBotExecutor{})
|
||||||
|
registry.Register(&dingtalk.DingTalkExecutor{})
|
||||||
|
registry.Register(&fwalert.FwalertExecutor{})
|
||||||
|
registry.Register(&rainyun.RainyunWorkorderExecutor{})
|
||||||
|
registry.Register(&rainyun.RainyunRunAwayExecutor{})
|
||||||
|
registry.Register(&alidns.DeleteAliDNSRecordExecutor{})
|
||||||
|
// 未来添加新规则类型时,在这里注册即可
|
||||||
|
|
||||||
|
globalExecutorRegistry = registry
|
||||||
|
})
|
||||||
|
return globalExecutorRegistry
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package accountConfigChecker
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/alidns"
|
||||||
"github.com/ssdomei232/goodBaby/drivers/bilibili"
|
"github.com/ssdomei232/goodBaby/drivers/bilibili"
|
||||||
"github.com/ssdomei232/goodBaby/drivers/email"
|
"github.com/ssdomei232/goodBaby/drivers/email"
|
||||||
"github.com/ssdomei232/goodBaby/drivers/github"
|
"github.com/ssdomei232/goodBaby/drivers/github"
|
||||||
@@ -26,6 +27,7 @@ func InitValidatorRegistry() *ValidatorRegistry {
|
|||||||
r.Register(&github.GitHubAccountConfigValidator{})
|
r.Register(&github.GitHubAccountConfigValidator{})
|
||||||
r.Register(&onebot.OneBotAccountConfigValidator{})
|
r.Register(&onebot.OneBotAccountConfigValidator{})
|
||||||
r.Register(&rainyun.RainyunAccountConfigValidator{})
|
r.Register(&rainyun.RainyunAccountConfigValidator{})
|
||||||
|
r.Register(&alidns.AliDNSAccountConfigValidator{})
|
||||||
|
|
||||||
registry = r
|
registry = r
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package ruleConfigChecker
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/alidns"
|
||||||
"github.com/ssdomei232/goodBaby/drivers/bilibili"
|
"github.com/ssdomei232/goodBaby/drivers/bilibili"
|
||||||
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
|
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
|
||||||
"github.com/ssdomei232/goodBaby/drivers/email"
|
"github.com/ssdomei232/goodBaby/drivers/email"
|
||||||
@@ -31,6 +32,8 @@ func InitValidatorRegistry() *ValidatorRegistry {
|
|||||||
r.Register(&github.GithubMakeRepositoryPublicRuleValidator{})
|
r.Register(&github.GithubMakeRepositoryPublicRuleValidator{})
|
||||||
r.Register(&fwalert.FwalertRuleValidator{})
|
r.Register(&fwalert.FwalertRuleValidator{})
|
||||||
r.Register(&rainyun.RainyunWorkorderRuleValidator{})
|
r.Register(&rainyun.RainyunWorkorderRuleValidator{})
|
||||||
|
r.Register(&rainyun.RainyunRunAwayRuleValidator{})
|
||||||
|
r.Register(&alidns.AliDNSDeleteRecordRuleValidator{})
|
||||||
|
|
||||||
registry = r
|
registry = r
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/ssdomei232/goodBaby/api/account"
|
"github.com/ssdomei232/goodBaby/api/account"
|
||||||
"github.com/ssdomei232/goodBaby/api/admin"
|
"github.com/ssdomei232/goodBaby/api/admin"
|
||||||
"github.com/ssdomei232/goodBaby/api/dashboard"
|
"github.com/ssdomei232/goodBaby/api/dashboard"
|
||||||
|
"github.com/ssdomei232/goodBaby/api/gateway"
|
||||||
apilog "github.com/ssdomei232/goodBaby/api/log"
|
apilog "github.com/ssdomei232/goodBaby/api/log"
|
||||||
apimeta "github.com/ssdomei232/goodBaby/api/meta"
|
apimeta "github.com/ssdomei232/goodBaby/api/meta"
|
||||||
"github.com/ssdomei232/goodBaby/api/rule"
|
"github.com/ssdomei232/goodBaby/api/rule"
|
||||||
@@ -65,6 +66,7 @@ func main() {
|
|||||||
v1.GET("/site", apimeta.HandleGetSiteInfo)
|
v1.GET("/site", apimeta.HandleGetSiteInfo)
|
||||||
v1.POST("/user/registry", user.HandleRegistry)
|
v1.POST("/user/registry", user.HandleRegistry)
|
||||||
v1.POST("/user/login", user.HandleLogin)
|
v1.POST("/user/login", user.HandleLogin)
|
||||||
|
v1.POST("/gateways/:token/webhook", gateway.HandleWebhook)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 需要认证的路由组
|
// 需要认证的路由组
|
||||||
@@ -114,6 +116,13 @@ func main() {
|
|||||||
accounts.DELETE("/:accountID", account.HandleDeleteAccount)
|
accounts.DELETE("/:accountID", account.HandleDeleteAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gateways := authorized.Group("/gateways")
|
||||||
|
{
|
||||||
|
gateways.GET("/", gateway.HandleList)
|
||||||
|
gateways.POST("/", gateway.HandleCreate)
|
||||||
|
gateways.DELETE("/:gatewayID", gateway.HandleDelete)
|
||||||
|
}
|
||||||
|
|
||||||
logs := authorized.Group("/logs")
|
logs := authorized.Group("/logs")
|
||||||
{
|
{
|
||||||
logs.GET("/", apilog.HandleGetLogs)
|
logs.GET("/", apilog.HandleGetLogs)
|
||||||
@@ -151,7 +160,7 @@ func corsMiddleware(allowedOrigins []string) gin.HandlerFunc {
|
|||||||
c.Header("Access-Control-Allow-Origin", origin)
|
c.Header("Access-Control-Allow-Origin", origin)
|
||||||
c.Header("Access-Control-Allow-Credentials", "true")
|
c.Header("Access-Control-Allow-Credentials", "true")
|
||||||
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||||
c.Header("Access-Control-Allow-Headers", "Content-Type")
|
c.Header("Access-Control-Allow-Headers", "Content-Type, X-API-Key, Authorization")
|
||||||
c.Header("Vary", "Origin")
|
c.Header("Vary", "Origin")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type MessageGateway struct {
|
||||||
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
|
UID uint `gorm:"index" json:"uid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Token string `gorm:"uniqueIndex;size:67" json:"token"`
|
||||||
|
CreateAt int64 `json:"create_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageGatewayRequest struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
+11
-6
@@ -2,10 +2,11 @@ package model
|
|||||||
|
|
||||||
// Rule 描述一个 Timer 到期后要执行的动作
|
// Rule 描述一个 Timer 到期后要执行的动作
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
ID uint `json:"id" gorm:"primaryKey"`
|
ID uint `json:"id" gorm:"primaryKey"`
|
||||||
UID uint `gorm:"index" json:"uid"`
|
UID uint `gorm:"index" json:"uid"`
|
||||||
TimerID uint `gorm:"index" json:"timer_id"`
|
TimerID uint `gorm:"index" json:"timer_id"`
|
||||||
Name string `json:"name"`
|
GatewayID uint `gorm:"index" json:"gateway_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
// 关联账号,部分规则类型(如钉钉)不需要账号,此时为 0
|
// 关联账号,部分规则类型(如钉钉)不需要账号,此时为 0
|
||||||
AccountID uint `json:"account_id"`
|
AccountID uint `json:"account_id"`
|
||||||
// 规则类型,见 internal/ruleConfigChecker 注册表
|
// 规则类型,见 internal/ruleConfigChecker 注册表
|
||||||
@@ -20,6 +21,7 @@ type Rule struct {
|
|||||||
type RuleRequest struct {
|
type RuleRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
TimerID uint `json:"timer_id"`
|
TimerID uint `json:"timer_id"`
|
||||||
|
GatewayID uint `json:"gateway_id"`
|
||||||
AccountID uint `json:"account_id"`
|
AccountID uint `json:"account_id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
ConfigJson string `json:"config_json"`
|
ConfigJson string `json:"config_json"`
|
||||||
@@ -37,8 +39,11 @@ func (r *RuleRequest) Validate() error {
|
|||||||
if r.Type == "" {
|
if r.Type == "" {
|
||||||
return ErrValidation("规则类型不能为空")
|
return ErrValidation("规则类型不能为空")
|
||||||
}
|
}
|
||||||
if r.TimerID == 0 {
|
if r.TimerID == 0 && r.GatewayID == 0 {
|
||||||
return ErrValidation("必须关联一个 Timer")
|
return ErrValidation("必须关联一个定时器或消息网关")
|
||||||
|
}
|
||||||
|
if r.TimerID != 0 && r.GatewayID != 0 {
|
||||||
|
return ErrValidation("定时器和消息网关只能选择一个")
|
||||||
}
|
}
|
||||||
if r.ConfigJson == "" {
|
if r.ConfigJson == "" {
|
||||||
return ErrValidation("规则配置不能为空")
|
return ErrValidation("规则配置不能为空")
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type User struct {
|
|||||||
CreateAt int64 `json:"create_at"`
|
CreateAt int64 `json:"create_at"`
|
||||||
Username string `gorm:"uniqueIndex" json:"username"`
|
Username string `gorm:"uniqueIndex" json:"username"`
|
||||||
Password string `json:"-"`
|
Password string `json:"-"`
|
||||||
|
APIKey string `gorm:"index;size:67" json:"api_key"`
|
||||||
// 管理员可以修改系统配置。第一个注册的用户自动成为管理员。
|
// 管理员可以修改系统配置。第一个注册的用户自动成为管理员。
|
||||||
IsAdmin bool `gorm:"default:false" json:"is_admin"`
|
IsAdmin bool `gorm:"default:false" json:"is_admin"`
|
||||||
// 钉钉机器人配置(JSON 字符串),用于接收提醒
|
// 钉钉机器人配置(JSON 字符串),用于接收提醒
|
||||||
|
|||||||
Generated
+22
-52
@@ -10,7 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.2",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"axios": "^1.18.1",
|
"axios": "^1.18.1",
|
||||||
"element-plus": "^2.14.3",
|
"element-plus": "^2.14.5",
|
||||||
"pinia": "^4.0.2",
|
"pinia": "^4.0.2",
|
||||||
"vue": "^3.5.39",
|
"vue": "^3.5.39",
|
||||||
"vue-router": "^4.6.4"
|
"vue-router": "^4.6.4"
|
||||||
@@ -286,9 +286,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -306,9 +303,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -326,9 +320,6 @@
|
|||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -346,9 +337,6 @@
|
|||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -366,9 +354,6 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -386,9 +371,6 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -513,7 +495,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@types/web-bluetooth": {
|
"node_modules/@types/web-bluetooth": {
|
||||||
"version": "0.0.21",
|
"version": "0.0.21",
|
||||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
|
||||||
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
|
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -727,14 +709,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vueuse/core": {
|
"node_modules/@vueuse/core": {
|
||||||
"version": "14.3.0",
|
"version": "14.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.4.0.tgz",
|
||||||
"integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
|
"integrity": "sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/web-bluetooth": "^0.0.21",
|
"@types/web-bluetooth": "^0.0.21",
|
||||||
"@vueuse/metadata": "14.3.0",
|
"@vueuse/metadata": "14.4.0",
|
||||||
"@vueuse/shared": "14.3.0"
|
"@vueuse/shared": "14.4.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/antfu"
|
"url": "https://github.com/sponsors/antfu"
|
||||||
@@ -744,18 +726,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vueuse/metadata": {
|
"node_modules/@vueuse/metadata": {
|
||||||
"version": "14.3.0",
|
"version": "14.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.4.0.tgz",
|
||||||
"integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==",
|
"integrity": "sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/antfu"
|
"url": "https://github.com/sponsors/antfu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vueuse/shared": {
|
"node_modules/@vueuse/shared": {
|
||||||
"version": "14.3.0",
|
"version": "14.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.4.0.tgz",
|
||||||
"integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
|
"integrity": "sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/antfu"
|
"url": "https://github.com/sponsors/antfu"
|
||||||
@@ -905,18 +887,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/element-plus": {
|
"node_modules/element-plus": {
|
||||||
"version": "2.14.3",
|
"version": "2.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.14.3.tgz",
|
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.5.tgz",
|
||||||
"integrity": "sha512-pJcvxcpZjYruNzuJhAeVwnbYjfNgzBKnWHwSVEhwzM2/kcLI3brzmtIBxtPqd4hQWJfD1PRnjoc1WipLw2eBGg==",
|
"integrity": "sha512-bghYy/S+qg87enHPXELirhEdDqsVAUGcGpbGIeG8dz0kwpIkGz7gYsifulBshXX74iRtHib85XWQj0uSH2A1Yg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ctrl/tinycolor": "^4.2.0",
|
"@ctrl/tinycolor": "^4.2.0",
|
||||||
"@element-plus/icons-vue": "^2.3.2",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@floating-ui/dom": "^1.7.6",
|
"@floating-ui/dom": "^1.8.0",
|
||||||
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
|
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
|
||||||
"@types/lodash": "^4.17.24",
|
"@types/lodash": "^4.17.24",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@vueuse/core": "14.3.0",
|
"@vueuse/core": "14.4.0",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"lodash": "^4.18.1",
|
"lodash": "^4.18.1",
|
||||||
@@ -924,7 +906,7 @@
|
|||||||
"lodash-unified": "^1.0.3",
|
"lodash-unified": "^1.0.3",
|
||||||
"memoize-one": "^6.0.0",
|
"memoize-one": "^6.0.0",
|
||||||
"normalize-wheel-es": "^1.2.0",
|
"normalize-wheel-es": "^1.2.0",
|
||||||
"vue-component-type-helpers": "^3.3.5"
|
"vue-component-type-helpers": "^3.3.9"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vue": "^3.3.7"
|
"vue": "^3.3.7"
|
||||||
@@ -1322,9 +1304,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1346,9 +1325,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1370,9 +1346,6 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1394,9 +1367,6 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1854,9 +1824,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue-component-type-helpers": {
|
"node_modules/vue-component-type-helpers": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.11.tgz",
|
||||||
"integrity": "sha512-troqCMmQodQDqUqn63NQaFi+CDSclSe7sc8VEBFqf5GFLqmGR2Ph3P2WEC7qwpRVyEWsTi/aAr4vyOe/B1hU3g==",
|
"integrity": "sha512-LwcxzeliO9fkQcpJG0PoX8X5kmAhKmH9wkpDLxNabwzkQ9Zeib2YVHwFV4pcWmMLfXVfjr/dSV+DaJ3cIPgSNA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/vue-router": {
|
"node_modules/vue-router": {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.2",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"axios": "^1.18.1",
|
"axios": "^1.18.1",
|
||||||
"element-plus": "^2.14.3",
|
"element-plus": "^2.14.5",
|
||||||
"pinia": "^4.0.2",
|
"pinia": "^4.0.2",
|
||||||
"vue": "^3.5.39",
|
"vue": "^3.5.39",
|
||||||
"vue-router": "^4.6.4"
|
"vue-router": "^4.6.4"
|
||||||
|
|||||||
Generated
+1214
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import type {
|
|||||||
DashboardOverview,
|
DashboardOverview,
|
||||||
ExecutionLog,
|
ExecutionLog,
|
||||||
LogPage,
|
LogPage,
|
||||||
|
MessageGateway,
|
||||||
Providers,
|
Providers,
|
||||||
Rule,
|
Rule,
|
||||||
RuleRequest,
|
RuleRequest,
|
||||||
@@ -81,6 +82,12 @@ export const logApi = {
|
|||||||
clear: () => api.delete<string>('/logs/'),
|
clear: () => api.delete<string>('/logs/'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const gatewayApi = {
|
||||||
|
list: () => api.get<MessageGateway[]>('/gateways/'),
|
||||||
|
create: (name: string) => api.post<MessageGateway>('/gateways/', { name }),
|
||||||
|
remove: (id: number) => api.delete<string>(`/gateways/${id}`),
|
||||||
|
}
|
||||||
|
|
||||||
export const adminApi = {
|
export const adminApi = {
|
||||||
getConfig: () => api.get<AdminConfigResponse>('/admin/config'),
|
getConfig: () => api.get<AdminConfigResponse>('/admin/config'),
|
||||||
updateConfig: (body: AdminConfig) => api.put<AdminConfig>('/admin/config', body),
|
updateConfig: (body: AdminConfig) => api.put<AdminConfig>('/admin/config', body),
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ export interface UserInfo {
|
|||||||
create_at: number
|
create_at: number
|
||||||
username: string
|
username: string
|
||||||
is_admin: boolean
|
is_admin: boolean
|
||||||
dingtalk_config: string | null
|
dingtalk_config: string | null
|
||||||
|
api_key: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Timer {
|
export interface Timer {
|
||||||
@@ -40,6 +41,7 @@ export interface Rule {
|
|||||||
id: number
|
id: number
|
||||||
uid: number
|
uid: number
|
||||||
timer_id: number
|
timer_id: number
|
||||||
|
gateway_id: number
|
||||||
name: string
|
name: string
|
||||||
account_id: number
|
account_id: number
|
||||||
type: string
|
type: string
|
||||||
@@ -48,9 +50,12 @@ export interface Rule {
|
|||||||
create_at: number
|
create_at: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MessageGateway { id: number; uid: number; name: string; token: string; create_at: number }
|
||||||
|
|
||||||
export interface RuleRequest {
|
export interface RuleRequest {
|
||||||
name: string
|
name: string
|
||||||
timer_id: number
|
timer_id: number
|
||||||
|
gateway_id?: number
|
||||||
account_id: number
|
account_id: number
|
||||||
type: string
|
type: string
|
||||||
config_json: string
|
config_json: string
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
Timer as TimerIcon,
|
Timer as TimerIcon,
|
||||||
Operation,
|
Operation,
|
||||||
User,
|
User,
|
||||||
|
Connection,
|
||||||
Document,
|
Document,
|
||||||
Setting,
|
Setting,
|
||||||
SwitchButton,
|
SwitchButton,
|
||||||
@@ -38,6 +39,7 @@ const menus = [
|
|||||||
{ path: '/timers', title: '定时器', icon: TimerIcon },
|
{ path: '/timers', title: '定时器', icon: TimerIcon },
|
||||||
{ path: '/rules', title: '规则', icon: Operation },
|
{ path: '/rules', title: '规则', icon: Operation },
|
||||||
{ path: '/accounts', title: '账号', icon: User },
|
{ path: '/accounts', title: '账号', icon: User },
|
||||||
|
{ path: '/gateways', title: '消息网关', icon: Connection },
|
||||||
{ path: '/logs', title: '执行日志', icon: Document },
|
{ path: '/logs', title: '执行日志', icon: Document },
|
||||||
{ path: '/settings', title: '设置', icon: Setting },
|
{ path: '/settings', title: '设置', icon: Setting },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const router = createRouter({
|
|||||||
component: () => import('@/views/AccountsView.vue'),
|
component: () => import('@/views/AccountsView.vue'),
|
||||||
meta: { title: '账号' },
|
meta: { title: '账号' },
|
||||||
},
|
},
|
||||||
|
{ path: 'gateways', name: 'gateways', component: () => import('@/views/GatewaysView.vue'), meta: { title: '消息网关' } },
|
||||||
{
|
{
|
||||||
path: 'logs',
|
path: 'logs',
|
||||||
name: 'logs',
|
name: 'logs',
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { CopyDocument, Delete, Link, Plus } from '@element-plus/icons-vue'
|
||||||
|
import { gatewayApi, ruleApi } from '@/api'
|
||||||
|
import type { MessageGateway, Rule } from '@/api/types'
|
||||||
|
const gateways = ref<MessageGateway[]>([]), rules = ref<Rule[]>([]), name = ref(''), loading = ref(false), saving = ref(false)
|
||||||
|
const origin = window.location.origin
|
||||||
|
async function refresh() { loading.value = true; try { ;[gateways.value, rules.value] = await Promise.all([gatewayApi.list(), ruleApi.list()]) } catch { ElMessage.error('加载消息网关失败') } finally { loading.value = false } }
|
||||||
|
async function create() { if (!name.value.trim()) { ElMessage.warning('请输入网关名称'); return }; saving.value = true; try { await gatewayApi.create(name.value.trim()); name.value = ''; await refresh(); ElMessage.success('消息网关已创建') } catch (e) { ElMessage.error(e instanceof Error ? e.message : '创建失败') } finally { saving.value = false } }
|
||||||
|
async function remove(item: MessageGateway) { try { await ElMessageBox.confirm(`删除“${item.name}”?关联规则将无法继续通过此网关触发。`, '删除消息网关', { type: 'warning' }); await gatewayApi.remove(item.id); await refresh() } catch {} }
|
||||||
|
async function copy(url: string) { await navigator.clipboard?.writeText(url); ElMessage.success('Webhook 地址已复制') }
|
||||||
|
function endpoint(item: MessageGateway) { return `${origin}/api/v1/gateways/${item.token}/webhook` }
|
||||||
|
function ruleCount(item: MessageGateway) { return rules.value.filter(r => r.gateway_id === item.id).length }
|
||||||
|
onMounted(refresh)
|
||||||
|
</script>
|
||||||
|
<template><div class="gateway-page" v-loading="loading"><div class="page-header"><div><h2>消息网关</h2><div class="muted">创建入口,让外部系统通过 Webhook 触发通知规则</div></div><el-button type="primary" :icon="Plus">新建网关</el-button></div><el-card class="create-card"><div class="create-copy"><div class="create-icon"><el-icon :size="20"><Link /></el-icon></div><div><strong>新建 Webhook 入口</strong><div class="muted">创建后,在规则编辑页将通知规则关联到此网关</div></div></div><el-form class="create-form" @submit.prevent="create"><el-input v-model="name" size="large" placeholder="例如:生产环境告警" maxlength="64" clearable /><el-button type="primary" size="large" :loading="saving" @click="create">创建网关</el-button></el-form></el-card><div v-if="gateways.length" class="gateway-grid"><el-card v-for="item in gateways" :key="item.id" class="gateway-card"><div class="gateway-top"><div><div class="gateway-name">{{ item.name }}</div><div class="gateway-meta">{{ ruleCount(item) }} 条关联通知规则</div></div><el-button circle text type="danger" :icon="Delete" title="删除网关" @click="remove(item)" /></div><div class="endpoint-label">Webhook 地址</div><div class="endpoint"><code>{{ endpoint(item) }}</code><el-button text :icon="CopyDocument" title="复制地址" @click="copy(endpoint(item))" /></div><div class="payload-hint">POST JSON:<code>{ "message": "...", "title": "..." }</code></div></el-card></div><el-empty v-else-if="!loading" description="还没有消息网关" /></div></template>
|
||||||
|
<style scoped>.create-card{margin-bottom:20px}.create-copy{display:flex;align-items:center;gap:12px;margin-bottom:16px}.create-copy strong{font-size:15px}.create-icon{width:40px;height:40px;display:grid;place-items:center;border-radius:10px;color:var(--gb-primary-deep);background:var(--el-color-primary-light-9)}.create-form{display:flex;gap:10px;max-width:620px}.create-form .el-input{flex:1}.gateway-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px}.gateway-card{min-width:0}.gateway-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:22px}.gateway-name{font-size:17px;font-weight:700}.gateway-meta,.endpoint-label,.payload-hint{color:var(--el-text-color-secondary);font-size:12px}.endpoint-label{margin-bottom:6px}.endpoint{display:flex;align-items:center;gap:6px;min-width:0;padding:10px 12px;border-radius:8px;background:var(--gb-bg)}.endpoint code{flex:1;min-width:0;overflow-wrap:anywhere;color:var(--el-text-color-primary);font-size:12px}.payload-hint{margin-top:12px}.payload-hint code{color:var(--el-text-color-primary)}@media(max-width:600px){.create-form{flex-direction:column}.gateway-grid{grid-template-columns:1fr}}</style>
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus, VideoPlay } from '@element-plus/icons-vue'
|
import { Plus, VideoPlay } from '@element-plus/icons-vue'
|
||||||
import { accountApi, ruleApi, timerApi } from '@/api'
|
import { accountApi, gatewayApi, ruleApi, timerApi } from '@/api'
|
||||||
import { ApiError } from '@/api/client'
|
import { ApiError } from '@/api/client'
|
||||||
import type { Account, Rule, Timer } from '@/api/types'
|
import type { Account, MessageGateway, Rule, Timer } from '@/api/types'
|
||||||
import { useMetaStore } from '@/stores/meta'
|
import { useMetaStore } from '@/stores/meta'
|
||||||
import { formatDateTime } from '@/utils/format'
|
import { formatDateTime } from '@/utils/format'
|
||||||
import ConfigForm from '@/components/ConfigForm.vue'
|
import ConfigForm from '@/components/ConfigForm.vue'
|
||||||
@@ -16,6 +16,7 @@ const metaStore = useMetaStore()
|
|||||||
|
|
||||||
const rules = ref<Rule[]>([])
|
const rules = ref<Rule[]>([])
|
||||||
const timers = ref<Timer[]>([])
|
const timers = ref<Timer[]>([])
|
||||||
|
const gateways = ref<MessageGateway[]>([])
|
||||||
const accounts = ref<Account[]>([])
|
const accounts = ref<Account[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const testingId = ref<number | null>(null)
|
const testingId = ref<number | null>(null)
|
||||||
@@ -30,6 +31,7 @@ const form = ref<{
|
|||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
timer_id: number
|
timer_id: number
|
||||||
|
gateway_id: number
|
||||||
account_id: number | undefined
|
account_id: number | undefined
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
config_json: string
|
config_json: string
|
||||||
@@ -37,6 +39,7 @@ const form = ref<{
|
|||||||
name: '',
|
name: '',
|
||||||
type: '',
|
type: '',
|
||||||
timer_id: 0,
|
timer_id: 0,
|
||||||
|
gateway_id: 0,
|
||||||
account_id: undefined,
|
account_id: undefined,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
config_json: '',
|
config_json: '',
|
||||||
@@ -69,14 +72,16 @@ function accountName(id: number): string {
|
|||||||
async function refresh() {
|
async function refresh() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const [ruleList, timerList, accountList] = await Promise.all([
|
const [ruleList, timerList, accountList, gatewayList] = await Promise.all([
|
||||||
ruleApi.list(),
|
ruleApi.list(),
|
||||||
timerApi.list(),
|
timerApi.list(),
|
||||||
accountApi.list(),
|
accountApi.list(),
|
||||||
|
gatewayApi.list(),
|
||||||
])
|
])
|
||||||
rules.value = ruleList
|
rules.value = ruleList
|
||||||
timers.value = timerList
|
timers.value = timerList
|
||||||
accounts.value = accountList
|
accounts.value = accountList
|
||||||
|
gateways.value = gatewayList
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error(error instanceof ApiError ? error.message : '加载失败')
|
ElMessage.error(error instanceof ApiError ? error.message : '加载失败')
|
||||||
} finally {
|
} finally {
|
||||||
@@ -85,7 +90,7 @@ async function refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openCreate() {
|
function openCreate() {
|
||||||
if (timers.value.length === 0) {
|
if (timers.value.length === 0 && gateways.value.length === 0) {
|
||||||
ElMessage.warning('请先在“定时器”页面创建一个定时器')
|
ElMessage.warning('请先在“定时器”页面创建一个定时器')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -94,6 +99,7 @@ function openCreate() {
|
|||||||
name: '',
|
name: '',
|
||||||
type: metaStore.ruleMetas[0]?.type ?? '',
|
type: metaStore.ruleMetas[0]?.type ?? '',
|
||||||
timer_id: timers.value[0]?.id ?? 0,
|
timer_id: timers.value[0]?.id ?? 0,
|
||||||
|
gateway_id: 0,
|
||||||
account_id: undefined,
|
account_id: undefined,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
config_json: '',
|
config_json: '',
|
||||||
@@ -107,6 +113,7 @@ function openEdit(rule: Rule) {
|
|||||||
name: rule.name,
|
name: rule.name,
|
||||||
type: rule.type,
|
type: rule.type,
|
||||||
timer_id: rule.timer_id,
|
timer_id: rule.timer_id,
|
||||||
|
gateway_id: rule.gateway_id || 0,
|
||||||
account_id: rule.account_id || undefined,
|
account_id: rule.account_id || undefined,
|
||||||
enabled: rule.enabled,
|
enabled: rule.enabled,
|
||||||
config_json: rule.config_json,
|
config_json: rule.config_json,
|
||||||
@@ -133,6 +140,7 @@ async function save() {
|
|||||||
name: form.value.name,
|
name: form.value.name,
|
||||||
type: form.value.type,
|
type: form.value.type,
|
||||||
timer_id: form.value.timer_id,
|
timer_id: form.value.timer_id,
|
||||||
|
gateway_id: form.value.gateway_id,
|
||||||
account_id: form.value.account_id ?? 0,
|
account_id: form.value.account_id ?? 0,
|
||||||
enabled: form.value.enabled,
|
enabled: form.value.enabled,
|
||||||
config_json: form.value.config_json,
|
config_json: form.value.config_json,
|
||||||
@@ -162,6 +170,7 @@ async function toggleEnabled(rule: Rule) {
|
|||||||
name: rule.name,
|
name: rule.name,
|
||||||
type: rule.type,
|
type: rule.type,
|
||||||
timer_id: rule.timer_id,
|
timer_id: rule.timer_id,
|
||||||
|
gateway_id: rule.gateway_id,
|
||||||
account_id: rule.account_id,
|
account_id: rule.account_id,
|
||||||
enabled: rule.enabled,
|
enabled: rule.enabled,
|
||||||
config_json: rule.config_json,
|
config_json: rule.config_json,
|
||||||
@@ -308,10 +317,14 @@ onMounted(async () => {
|
|||||||
</el-select>
|
</el-select>
|
||||||
<div v-if="currentMeta?.description" class="muted">{{ currentMeta.description }}</div>
|
<div v-if="currentMeta?.description" class="muted">{{ currentMeta.description }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="关联定时器" required>
|
<el-form-item label="关联定时器/消息网关" required>
|
||||||
<el-select v-model="form.timer_id" style="width: 100%">
|
<div class="source-hint muted">规则只能选择一种触发方式</div>
|
||||||
|
<el-select v-model="form.timer_id" class="source-select" clearable placeholder="定时器触发">
|
||||||
<el-option v-for="t in timers" :key="t.id" :label="t.name" :value="t.id" />
|
<el-option v-for="t in timers" :key="t.id" :label="t.name" :value="t.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
<el-select v-model="form.gateway_id" clearable placeholder="消息网关(可选)" style="width: 100%; margin-top: 8px" @change="form.gateway_id && (form.timer_id = 0)">
|
||||||
|
<el-option v-for="g in gateways" :key="g.id" :label="g.name" :value="g.id" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="currentMeta?.account_type" label="关联账号" required>
|
<el-form-item v-if="currentMeta?.account_type" label="关联账号" required>
|
||||||
<el-select
|
<el-select
|
||||||
@@ -363,6 +376,9 @@ onMounted(async () => {
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.source-select { width: 100%; margin-top: 8px; }
|
||||||
|
.source-hint { margin-bottom: 2px; }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.header-tools {
|
.header-tools {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ const userStore = useUserStore()
|
|||||||
|
|
||||||
const isAdmin = computed(() => userStore.user?.is_admin === true)
|
const isAdmin = computed(() => userStore.user?.is_admin === true)
|
||||||
|
|
||||||
|
async function copyApiKey() {
|
||||||
|
const key = userStore.user?.api_key
|
||||||
|
if (!key) return
|
||||||
|
await navigator.clipboard?.writeText(key)
|
||||||
|
ElMessage.success('API Key 已复制')
|
||||||
|
}
|
||||||
|
|
||||||
// ---- 系统配置(仅管理员) ----
|
// ---- 系统配置(仅管理员) ----
|
||||||
const adminLoading = ref(false)
|
const adminLoading = ref(false)
|
||||||
const adminSaving = ref(false)
|
const adminSaving = ref(false)
|
||||||
@@ -166,6 +173,13 @@ onMounted(async () => {
|
|||||||
<el-descriptions-item label="注册时间">
|
<el-descriptions-item label="注册时间">
|
||||||
{{ formatDateTime(userStore.user?.create_at ?? 0) }}
|
{{ formatDateTime(userStore.user?.create_at ?? 0) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="API Key">
|
||||||
|
<el-input :model-value="userStore.user?.api_key ?? ''" readonly style="max-width: 380px">
|
||||||
|
<template #append>
|
||||||
|
<el-button title="复制 API Key" @click="copyApiKey">复制</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user