feat(checker): checker
This commit is contained in:
@@ -73,7 +73,6 @@ func HandleCheckDeleteAccount(c *gin.Context) {
|
|||||||
c.JSON(401, gin.H{"code": 401, "data": "获取用户信息失败"})
|
c.JSON(401, gin.H{"code": 401, "data": "获取用户信息失败"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountID, err := strconv.Atoi(c.Param("accountID"))
|
accountID, err := strconv.Atoi(c.Param("accountID"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"code": 400, "data": "账号ID格式错误"})
|
c.JSON(400, gin.H{"code": 400, "data": "账号ID格式错误"})
|
||||||
@@ -96,19 +95,18 @@ func HandleDeleteAccount(c *gin.Context) {
|
|||||||
c.JSON(401, gin.H{"code": 401, "data": "获取用户信息失败"})
|
c.JSON(401, gin.H{"code": 401, "data": "获取用户信息失败"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountID, err := strconv.Atoi(c.Param("accountID"))
|
accountID, err := strconv.Atoi(c.Param("accountID"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"code": 400, "data": "账号ID格式错误"})
|
c.JSON(400, gin.H{"code": 400, "data": "账号ID格式错误"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除相关规则
|
||||||
rules, err := getRulesByAccountID(uint(accountID), userInfo.ID)
|
rules, err := getRulesByAccountID(uint(accountID), userInfo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"code": 500, "data": "获取相关规则失败"})
|
c.JSON(500, gin.H{"code": 500, "data": "获取相关规则失败"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, oneRule := range rules {
|
for _, oneRule := range rules {
|
||||||
err = rule.DeleteRuleByID(oneRule.ID, userInfo.ID)
|
err = rule.DeleteRuleByID(oneRule.ID, userInfo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -117,12 +115,12 @@ func HandleDeleteAccount(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除账号
|
||||||
gormDB, err := db.GetGormDB()
|
gormDB, err := db.GetGormDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"code": 500, "data": "服务器内部错误"})
|
c.JSON(500, gin.H{"code": 500, "data": "服务器内部错误"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result := gormDB.Where("id = ? AND uid = ?", accountID, userInfo.ID).Delete(&model.Account{})
|
result := gormDB.Where("id = ? AND uid = ?", accountID, userInfo.ID).Delete(&model.Account{})
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
c.JSON(500, gin.H{"code": 500, "data": "删除账号失败"})
|
c.JSON(500, gin.H{"code": 500, "data": "删除账号失败"})
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/ssdomei232/goodBaby/handler/db"
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
@@ -34,6 +36,8 @@ func createUser(u *model.User) error {
|
|||||||
}
|
}
|
||||||
u.Password = hashedPassword
|
u.Password = hashedPassword
|
||||||
|
|
||||||
|
u.CreateAt = time.Now().Unix()
|
||||||
|
|
||||||
result := gormDB.Create(u)
|
result := gormDB.Create(u)
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-4
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
// 处理注册请求,配置文件中可设置禁用注册
|
// 处理注册请求,配置文件中可设置禁用注册
|
||||||
func HandleRegistry(c *gin.Context) {
|
func HandleRegistry(c *gin.Context) {
|
||||||
var user model.User
|
var userRegistryRequest model.UserRegistryReuest
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
config, err := configs.GetConfig()
|
config, err := configs.GetConfig()
|
||||||
@@ -23,12 +23,17 @@ func HandleRegistry(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.BindJSON(&user)
|
err = c.BindJSON(&userRegistryRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"code": 400, "data": "输入错误"})
|
c.JSON(400, gin.H{"code": 400, "data": "输入错误"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user := model.User{
|
||||||
|
Username: userRegistryRequest.Username,
|
||||||
|
Password: userRegistryRequest.Password,
|
||||||
|
}
|
||||||
|
|
||||||
if err = user.IsValid(); err != nil {
|
if err = user.IsValid(); err != nil {
|
||||||
c.JSON(400, gin.H{"code": 400, "data": err.Error()})
|
c.JSON(400, gin.H{"code": 400, "data": err.Error()})
|
||||||
return
|
return
|
||||||
@@ -53,15 +58,20 @@ func HandleRegistry(c *gin.Context) {
|
|||||||
|
|
||||||
// 处理登录请求
|
// 处理登录请求
|
||||||
func HandleLogin(c *gin.Context) {
|
func HandleLogin(c *gin.Context) {
|
||||||
var user model.User
|
var userLoginRequest model.UserRegistryReuest
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
err = c.BindJSON(&user)
|
err = c.BindJSON(&userLoginRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"code": 400, "data": "输入错误"})
|
c.JSON(400, gin.H{"code": 400, "data": "输入错误"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user := model.User{
|
||||||
|
Username: userLoginRequest.Username,
|
||||||
|
Password: userLoginRequest.Password,
|
||||||
|
}
|
||||||
|
|
||||||
if err = user.IsValid(); err != nil {
|
if err = user.IsValid(); err != nil {
|
||||||
c.JSON(400, gin.H{"code": 400, "data": err.Error()})
|
c.JSON(400, gin.H{"code": 400, "data": err.Error()})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ import (
|
|||||||
"github.com/CuteReimu/bilibili/v2"
|
"github.com/CuteReimu/bilibili/v2"
|
||||||
"github.com/cenkalti/backoff/v5"
|
"github.com/cenkalti/backoff/v5"
|
||||||
"github.com/ssdomei232/goodBaby/configs"
|
"github.com/ssdomei232/goodBaby/configs"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 在Bilibili动态发送消息
|
// 在Bilibili动态发送消息
|
||||||
//
|
//
|
||||||
// 暂时没有处理 429 和 403 的区别对待
|
// 暂时没有处理 429 和 403 的区别对待
|
||||||
func SendBiliDynamicMsg(biliClient *bilibili.Client, msg string) {
|
func SendBiliDynamicMsg(rule *model.Rule) {
|
||||||
config, err := configs.GetConfig()
|
config, err := configs.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("获取配置失败: %v", err)
|
log.Printf("获取配置失败: %v", err)
|
||||||
@@ -21,12 +22,23 @@ func SendBiliDynamicMsg(biliClient *bilibili.Client, msg string) {
|
|||||||
}
|
}
|
||||||
var timeout time.Duration = time.Duration(config.TimeoutDurationHours) * time.Hour
|
var timeout time.Duration = time.Duration(config.TimeoutDurationHours) * time.Hour
|
||||||
|
|
||||||
|
biliClient, err := getBiliClient(rule)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("获取B站客户端失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
biliDyncmicConfig, err := getBiliDynamicConfig(rule)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("获取B站动态配置失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var dynamicParams bilibili.CreateDynamicParam
|
var dynamicParams bilibili.CreateDynamicParam
|
||||||
dynamicParams = bilibili.CreateDynamicParam{
|
dynamicParams = bilibili.CreateDynamicParam{
|
||||||
DynamicId: 0,
|
DynamicId: 0,
|
||||||
Type: 4,
|
Type: 4,
|
||||||
Rid: 0,
|
Rid: 0,
|
||||||
Content: msg,
|
Content: biliDyncmicConfig.Msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ type BiliAccount struct {
|
|||||||
RawCookies string `json:"raw_cookies"`
|
RawCookies string `json:"raw_cookies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BiliDynamicRule struct {
|
type BiliDynamicConfig struct {
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 获取 Bilibili Client
|
// 获取 Bilibili Client
|
||||||
func GetBiliClient(rule *model.Rule) (*bilibili.Client, error) {
|
func getBiliClient(rule *model.Rule) (*bilibili.Client, error) {
|
||||||
client := bilibili.New()
|
client := bilibili.New()
|
||||||
gormDB, err := db.GetGormDB()
|
gormDB, err := db.GetGormDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -34,3 +34,14 @@ func GetBiliClient(rule *model.Rule) (*bilibili.Client, error) {
|
|||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取 Bilibili Dynamic Config
|
||||||
|
func getBiliDynamicConfig(rule *model.Rule) (*BiliDynamicConfig, error) {
|
||||||
|
var biliDynamicConfig BiliDynamicConfig
|
||||||
|
err := json.Unmarshal([]byte(rule.ConfigJson), &biliDynamicConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &biliDynamicConfig, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package checker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/reminder"
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/runner"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 定时检查所有 timers 是否需要被触发
|
||||||
|
//
|
||||||
|
// 同时向即将被触发的 timers 发送通知
|
||||||
|
func CheckTimers() {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to get gorm db: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 获取所有 timers
|
||||||
|
var timers []model.Timer
|
||||||
|
if err := gormDB.Find(&timers).Error; err != nil {
|
||||||
|
log.Printf("failed to get timers: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查每个 timer 是否需要被触发
|
||||||
|
for _, timer := range timers {
|
||||||
|
// 计算下次触发时间
|
||||||
|
nextSignTime := timer.LastSign + timer.SignDerationSeconds
|
||||||
|
|
||||||
|
// 计算提醒时间
|
||||||
|
remindTime := nextSignTime - timer.RemindTimeSeconds
|
||||||
|
|
||||||
|
// 获取当前时间
|
||||||
|
currentTime := time.Now().Unix()
|
||||||
|
|
||||||
|
if currentTime >= remindTime && currentTime < nextSignTime {
|
||||||
|
// 发送通知
|
||||||
|
reminder.Reminder(&timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentTime >= nextSignTime {
|
||||||
|
// 触发 timer
|
||||||
|
runner.Runner(&timer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package reminder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/ssdomei232/goodBaby/drivers/dingtalk"
|
||||||
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// reminder 负责在 checker 检查到 timer 即将被触发时,向用户发送提醒
|
||||||
|
func Reminder(timer *model.Timer) {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to get gorm db: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 获取 timer 对应的 user
|
||||||
|
var user model.User
|
||||||
|
if err := gormDB.Where("id = ?", timer.UID).First(&user).Error; err != nil {
|
||||||
|
log.Printf("failed to get user: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 向用户发送提醒
|
||||||
|
dingtalk.SendDingTalkMsg(&user, "您的 goodbaby timer 即将被触发", "您的 goodbaby timer 即将被触发")
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package runner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"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/handler/db"
|
||||||
|
"github.com/ssdomei232/goodBaby/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// runner 执行需要被执行的 Rule
|
||||||
|
func Runner(timer *model.Timer) {
|
||||||
|
gormDB, err := db.GetGormDB()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to get gorm db: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 获取所有需要执行的 Rule
|
||||||
|
var rules []model.Rule
|
||||||
|
if err := gormDB.Where("timer_id = ?", timer.ID).Find(&rules).Error; err != nil {
|
||||||
|
log.Printf("failed to get rules: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 执行每个 Rule
|
||||||
|
for _, rule := range rules {
|
||||||
|
// 执行 rule
|
||||||
|
go executeRule(&rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// super switch
|
||||||
|
func executeRule(rule *model.Rule) {
|
||||||
|
switch rule.Type {
|
||||||
|
case "bilibili-dynamic":
|
||||||
|
bilibili.SendBiliDynamicMsg(rule)
|
||||||
|
case "email":
|
||||||
|
email.SendMail(rule)
|
||||||
|
case "github-make-repo-public":
|
||||||
|
github.MakeRepositoryPublic(rule)
|
||||||
|
case "onebot":
|
||||||
|
onebot.SendOneBotMsg(rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ func main() {
|
|||||||
authorized.GET("/accounts", account.HandleGetAllAccounts)
|
authorized.GET("/accounts", account.HandleGetAllAccounts)
|
||||||
authorized.POST("/accounts", account.HandleAddAccount)
|
authorized.POST("/accounts", account.HandleAddAccount)
|
||||||
authorized.GET("/accounts/:accountID/check", account.HandleCheckDeleteAccount)
|
authorized.GET("/accounts/:accountID/check", account.HandleCheckDeleteAccount)
|
||||||
|
authorized.DELETE("/accounts/:accountID", account.HandleDeleteAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Run(":8088")
|
r.Run(":8088")
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ type Timer struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
SignDerationSeconds int64 `json:"sign_deration_seconds"`
|
SignDerationSeconds int64 `json:"sign_deration_seconds"`
|
||||||
LastSign int64 `json:"last_sign"`
|
LastSign int64 `json:"last_sign"`
|
||||||
|
RemindTimeSeconds int64 `json:"remind_time_seconds"` // 提前多少秒提醒
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ import (
|
|||||||
"github.com/ssdomei232/goodBaby/handler/db"
|
"github.com/ssdomei232/goodBaby/handler/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type UserRegistryReuest struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID uint `json:"id" gorm:"primaryKey"`
|
ID uint `json:"id" gorm:"primaryKey"`
|
||||||
CreateAt int64 `json:"create_at"`
|
CreateAt int64 `json:"create_at"`
|
||||||
|
|||||||
Reference in New Issue
Block a user