refactor(internal): 分离runner

This commit is contained in:
mei
2026-06-19 18:47:36 +08:00
parent 7957a91609
commit 5da78f9deb
15 changed files with 209 additions and 53 deletions
+82
View File
@@ -65,6 +65,15 @@ func HandleCreateRule(c *gin.Context) {
return
}
// 检查关联账号和 Timer 是否存在(可以没有关联账号)
if exist, err := checkRuleConfigAccountAndTimerExist(newRule); err != nil {
c.JSON(500, gin.H{"code": 500, "data": "服务器内部错误"})
return
} else if !exist {
c.JSON(400, gin.H{"code": 400, "data": "关联的账户或Timer不存在"})
return
}
// 规则校验
validatorRegistry := ruleConfigChecker.InitValidatorRegistry()
if err := validatorRegistry.Validate(newRule.Type, newRule.ConfigJson); err != nil {
@@ -82,6 +91,79 @@ func HandleCreateRule(c *gin.Context) {
c.JSON(200, gin.H{"code": 200, "data": "规则创建成功"})
}
// 编辑规则
func HandleEditRule(c *gin.Context) {
gormDB, err := db.GetGormDB()
if err != nil {
c.JSON(500, gin.H{"code": 500, "data": "服务器内部错误"})
return
}
userInfo, err := user.GetUserInfoByGinCtx(c)
if err != nil {
c.JSON(401, gin.H{"code": 401, "data": "获取用户信息失败"})
return
}
ruleID, err := strconv.Atoi(c.Param("ruleID"))
if err != nil {
c.JSON(400, gin.H{"code": 400, "data": "规则 ID 格式错误"})
return
}
var rule model.Rule
result := gormDB.Where("id = ? AND uid = ?", ruleID, userInfo.ID).First(&rule)
if result.Error != nil {
c.JSON(404, gin.H{"code": 404, "data": "规则不存在"})
return
}
var updatedRule model.Rule
if err := c.BindJSON(&updatedRule); err != nil {
c.JSON(400, gin.H{"code": 400, "data": "输入参数错误"})
return
}
if updatedRule.Type == "" {
c.JSON(400, gin.H{"code": 400, "data": "规则类型不能为空"})
return
}
if updatedRule.Name == "" {
c.JSON(400, gin.H{"code": 400, "data": "规则名称不能为空"})
return
}
// 检查关联账号和 Timer 是否存在(可以没有关联账号)
if exist, err := checkRuleConfigAccountAndTimerExist(updatedRule); err != nil {
c.JSON(500, gin.H{"code": 500, "data": "服务器内部错误"})
return
} else if !exist {
c.JSON(400, gin.H{"code": 400, "data": "关联的账户或Timer不存在"})
return
}
// 规则校验
validatorRegistry := ruleConfigChecker.InitValidatorRegistry()
if err := validatorRegistry.Validate(updatedRule.Type, updatedRule.ConfigJson); err != nil {
c.JSON(400, gin.H{"code": 400, "data": fmt.Sprintf("规则配置验证失败: %s", err.Error())})
return
}
rule.Name = updatedRule.Name
rule.Type = updatedRule.Type
rule.ConfigJson = updatedRule.ConfigJson
rule.AccountID = updatedRule.AccountID
rule.TimerID = updatedRule.TimerID
result = gormDB.Save(&rule)
if result.Error != nil {
c.JSON(500, gin.H{"code": 500, "data": "更新规则失败"})
return
}
c.JSON(200, gin.H{"code": 200, "data": "规则更新成功"})
}
// 根据删除规则
func HandleDeleteRule(c *gin.Context) {
userInfo, err := user.GetUserInfoByGinCtx(c)
+35
View File
@@ -15,3 +15,38 @@ func DeleteRuleByID(id uint, uid uint) error {
result := gormDB.Where("id = ? AND uid = ?", id, uid).Delete(&model.Rule{})
return result.Error
}
// 检查关联账号和 Timer 是否存在(可以没有关联账号)
func checkRuleConfigAccountAndTimerExist(rule model.Rule) (exist bool, err error) {
gormDB, err := db.GetGormDB()
if err != nil {
return false, err
}
if rule.TimerID == 0 {
return false, nil
}
var count int64
if rule.AccountID != 0 {
result := gormDB.Model(&model.Account{}).Where("id = ? AND uid = ?", rule.AccountID, rule.UID).Count(&count)
if result.Error != nil {
return false, result.Error
}
if count == 0 {
return false, nil
}
}
if rule.TimerID != 0 {
result := gormDB.Model(&model.Timer{}).Where("id = ? AND uid = ?", rule.TimerID, rule.UID).Count(&count)
if result.Error != nil {
return false, result.Error
}
if count == 0 {
return false, nil
}
}
return true, nil
}
@@ -1,10 +1,8 @@
package ruleConfigChecker
package bilibili
import (
"encoding/json"
"fmt"
"github.com/ssdomei232/goodBaby/drivers/bilibili"
)
// BilibiliDynamicRuleValidator B站动态规则验证器
@@ -15,7 +13,7 @@ func (v *BilibiliDynamicRuleValidator) GetType() string {
}
func (v *BilibiliDynamicRuleValidator) Validate(configJSON string) error {
var config bilibili.BiliDynamicConfig
var config BiliDynamicConfig
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
return fmt.Errorf("解析B站动态规则配置失败: %v", err)
}
@@ -1,9 +1,8 @@
package runner
package bilibili
import (
"log"
"github.com/ssdomei232/goodBaby/drivers/bilibili"
"github.com/ssdomei232/goodBaby/model"
)
@@ -17,7 +16,7 @@ func (e *BilibiliDynamicExecutor) GetType() string {
func (e *BilibiliDynamicExecutor) Execute(rule *model.Rule) error {
log.Printf("执行B站动态规则: %s (ID: %d)", rule.Name, rule.ID)
bilibili.SendBiliDynamicMsg(rule)
SendBiliDynamicMsg(rule)
return nil
}
@@ -1,10 +1,8 @@
package ruleConfigChecker
package dingtalk
import (
"encoding/json"
"fmt"
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
)
// DingTalkRuleValidator 钉钉规则验证器
@@ -15,7 +13,7 @@ func (v *DingTalkRuleValidator) GetType() string {
}
func (v *DingTalkRuleValidator) Validate(configJSON string) error {
var config dingtalk.DingTalkConfig
var config DingTalkConfig
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
return fmt.Errorf("解析钉钉规则配置失败: %v", err)
}
@@ -1,11 +1,9 @@
package ruleConfigChecker
package email
import (
"encoding/json"
"fmt"
"net/mail"
"github.com/ssdomei232/goodBaby/drivers/email"
)
// EmailRuleValidator 邮件规则验证器
@@ -16,7 +14,7 @@ func (v *EmailRuleValidator) GetType() string {
}
func (v *EmailRuleValidator) Validate(configJSON string) error {
var config email.EmailRule
var config EmailRule
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
return fmt.Errorf("解析邮件规则配置失败: %v", err)
}
@@ -1,9 +1,8 @@
package runner
package email
import (
"log"
"github.com/ssdomei232/goodBaby/drivers/email"
"github.com/ssdomei232/goodBaby/model"
)
@@ -17,7 +16,7 @@ func (e *EmailExecutor) GetType() string {
func (e *EmailExecutor) Execute(rule *model.Rule) error {
log.Printf("执行邮件规则: %s (ID: %d)", rule.Name, rule.ID)
email.SendMail(rule)
SendMail(rule)
return nil
}
+25
View File
@@ -0,0 +1,25 @@
package github
import (
"encoding/json"
"fmt"
)
type GithubMakeRepositoryPublicRuleValidator struct{}
func (v *GithubMakeRepositoryPublicRuleValidator) GetType() string {
return "github_make_repository_public"
}
func (v *GithubMakeRepositoryPublicRuleValidator) Validate(configJSON string) error {
var config GithubReposConfig
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
return fmt.Errorf("解析 GitHub 规则配置失败: %v", err)
}
if len(config.Repos) == 0 {
return fmt.Errorf("GitHub 规则配置错误: 至少需要指定一个仓库")
}
return nil
}
@@ -1,9 +1,8 @@
package runner
package github
import (
"log"
"github.com/ssdomei232/goodBaby/drivers/github"
"github.com/ssdomei232/goodBaby/model"
)
@@ -17,7 +16,7 @@ func (e *GithubMakeRepoPublicExecutor) GetType() string {
func (e *GithubMakeRepoPublicExecutor) Execute(rule *model.Rule) error {
log.Printf("执行GitHub仓库公开规则: %s (ID: %d)", rule.Name, rule.ID)
github.MakeRepositoryPublic(rule)
MakeRepositoryPublic(rule)
return nil
}
@@ -1,10 +1,8 @@
package ruleConfigChecker
package onebot
import (
"encoding/json"
"fmt"
"github.com/ssdomei232/goodBaby/drivers/onebot"
)
// OneBotRuleValidator OneBot规则验证器
@@ -15,7 +13,7 @@ func (v *OneBotRuleValidator) GetType() string {
}
func (v *OneBotRuleValidator) Validate(configJSON string) error {
var config onebot.OneBotConfig
var config OneBotConfig
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
return fmt.Errorf("解析OneBot规则配置失败: %v", err)
}
@@ -1,9 +1,8 @@
package runner
package onebot
import (
"log"
"github.com/ssdomei232/goodBaby/drivers/onebot"
"github.com/ssdomei232/goodBaby/model"
)
@@ -17,7 +16,7 @@ func (e *OneBotExecutor) GetType() string {
func (e *OneBotExecutor) Execute(rule *model.Rule) error {
log.Printf("执行OneBot规则: %s (ID: %d)", rule.Name, rule.ID)
onebot.SendOneBotMsg(rule)
SendOneBotMsg(rule)
return nil
}
+8 -4
View File
@@ -3,6 +3,10 @@ package runner
import (
"fmt"
"github.com/ssdomei232/goodBaby/drivers/bilibili"
"github.com/ssdomei232/goodBaby/drivers/email"
"github.com/ssdomei232/goodBaby/drivers/github"
"github.com/ssdomei232/goodBaby/drivers/onebot"
"github.com/ssdomei232/goodBaby/model"
)
@@ -57,10 +61,10 @@ func InitExecutorRegistry() *ExecutorRegistry {
registry := NewExecutorRegistry()
// 注册所有规则执行器
registry.Register(&BilibiliDynamicExecutor{})
registry.Register(&EmailExecutor{})
registry.Register(&GithubMakeRepoPublicExecutor{})
registry.Register(&OneBotExecutor{})
registry.Register(&bilibili.BilibiliDynamicExecutor{})
registry.Register(&email.EmailExecutor{})
registry.Register(&github.GithubMakeRepoPublicExecutor{})
registry.Register(&onebot.OneBotExecutor{})
// 未来添加新规则类型时,在这里注册即可
globalExecutorRegistry = registry
@@ -59,16 +59,3 @@ func (vr *ValidatorRegistry) GetSupportedTypes() []string {
}
return types
}
// InitValidatorRegistry 初始化验证器注册表并注册所有验证器
func InitValidatorRegistry() *ValidatorRegistry {
registry := NewValidatorRegistry()
// 注册所有规则验证器
registry.Register(&BilibiliDynamicRuleValidator{})
registry.Register(&EmailRuleValidator{})
registry.Register(&OneBotRuleValidator{})
registry.Register(&DingTalkRuleValidator{})
return registry
}
+23
View File
@@ -0,0 +1,23 @@
package ruleConfigChecker
import (
"github.com/ssdomei232/goodBaby/drivers/bilibili"
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
"github.com/ssdomei232/goodBaby/drivers/email"
"github.com/ssdomei232/goodBaby/drivers/github"
"github.com/ssdomei232/goodBaby/drivers/onebot"
)
// InitValidatorRegistry 初始化验证器注册表并注册所有验证器
func InitValidatorRegistry() *ValidatorRegistry {
registry := NewValidatorRegistry()
// 注册所有规则验证器
registry.Register(&bilibili.BilibiliDynamicRuleValidator{})
registry.Register(&email.EmailRuleValidator{})
registry.Register(&onebot.OneBotRuleValidator{})
registry.Register(&dingtalk.DingTalkRuleValidator{})
registry.Register(&github.GithubMakeRepositoryPublicRuleValidator{})
return registry
}
+20 -8
View File
@@ -36,14 +36,26 @@ func main() {
authorized := v1.Group("/")
authorized.Use(user.AuthMiddleware())
{
authorized.GET("/user/info", user.HandleGetUserInfo)
authorized.GET("/rules", rule.HandleGetAllRules)
authorized.POST("/rules", rule.HandleCreateRule)
authorized.DELETE("/rules/:ruleID", rule.HandleDeleteRule)
authorized.GET("/accounts", account.HandleGetAllAccounts)
authorized.POST("/accounts", account.HandleAddAccount)
authorized.GET("/accounts/:accountID/check", account.HandleCheckDeleteAccount)
authorized.DELETE("/accounts/:accountID", account.HandleDeleteAccount)
users := authorized.Group("/user")
{
users.GET("/info", user.HandleGetUserInfo)
}
rules := authorized.Group("/rules")
{
rules.GET("/", rule.HandleGetAllRules)
rules.POST("/", rule.HandleCreateRule)
rules.PUT("/:ruleID", rule.HandleEditRule)
rules.DELETE("/:ruleID", rule.HandleDeleteRule)
}
accounts := authorized.Group("/accounts")
{
accounts.GET("/", account.HandleGetAllAccounts)
accounts.POST("/", account.HandleAddAccount)
accounts.GET("/:accountID/check", account.HandleCheckDeleteAccount)
accounts.DELETE("/:accountID", account.HandleDeleteAccount)
}
}
r.Run(":8088")