2022-11-20 14:11:47 +00:00
|
|
|
|
package subscription
|
|
|
|
|
|
|
|
|
|
import (
|
2023-01-15 03:12:54 +00:00
|
|
|
|
"context"
|
2022-11-20 14:11:47 +00:00
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2023-09-04 06:02:25 +00:00
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"regexp"
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
2023-05-12 05:11:38 +00:00
|
|
|
|
"github.com/go-git/go-git/v5"
|
|
|
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
|
|
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
2023-09-04 06:02:25 +00:00
|
|
|
|
"github.com/huoxue1/go-utils/base/log"
|
2023-04-22 10:02:50 +00:00
|
|
|
|
"github.com/huoxue1/qinglong-go/internal/cron-manager"
|
2022-11-20 14:11:47 +00:00
|
|
|
|
"github.com/huoxue1/qinglong-go/models"
|
|
|
|
|
"github.com/huoxue1/qinglong-go/service/config"
|
|
|
|
|
"github.com/huoxue1/qinglong-go/service/cron"
|
|
|
|
|
"github.com/huoxue1/qinglong-go/utils"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
manager sync.Map
|
|
|
|
|
)
|
|
|
|
|
|
2023-04-22 14:17:05 +00:00
|
|
|
|
func InitSub() {
|
2023-02-03 04:43:37 +00:00
|
|
|
|
log.Infoln("开始初始化订阅任务定时!")
|
|
|
|
|
subscriptions, err := models.QuerySubscription("")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for _, subscription := range subscriptions {
|
|
|
|
|
cron_manager.AddCron(fmt.Sprintf("sub_%d", subscription.Id), subscription.GetCron(), func() {
|
|
|
|
|
downloadFiles(subscription)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getDepFiles() []string {
|
|
|
|
|
var files []string
|
|
|
|
|
dir, err := os.ReadDir(path.Join("data", "deps"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return []string{}
|
|
|
|
|
}
|
|
|
|
|
for _, entry := range dir {
|
|
|
|
|
if !entry.IsDir() {
|
|
|
|
|
files = append(files, entry.Name())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return files
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
func stopSubscription(sub *models.Subscriptions) {
|
|
|
|
|
defer func() {
|
|
|
|
|
_ = recover()
|
|
|
|
|
}()
|
|
|
|
|
sub.Status = 1
|
|
|
|
|
_ = models.UpdateSubscription(sub)
|
|
|
|
|
value, ok := manager.Load(sub.Id)
|
|
|
|
|
if !ok {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
cancel := value.(func())
|
|
|
|
|
cancel()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func downloadFiles(subscriptions *models.Subscriptions) {
|
|
|
|
|
if subscriptions.Type == "public-repo" {
|
2023-02-03 04:43:37 +00:00
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
os.RemoveAll(path.Join("data", "repo", subscriptions.Alias))
|
|
|
|
|
err := downloadPublicRepo(subscriptions)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-02-03 04:43:37 +00:00
|
|
|
|
os.RemoveAll(path.Join("data", "scripts", subscriptions.Alias))
|
2023-01-13 11:32:50 +00:00
|
|
|
|
if config.GetKey("AutoAddCron", "true") == "true" {
|
2022-11-26 02:31:26 +00:00
|
|
|
|
addScripts(subscriptions)
|
|
|
|
|
} else {
|
|
|
|
|
log.Infoln("未配置自动添加定时任务,不添加任务!")
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
file, _ := os.OpenFile(subscriptions.LogPath, os.O_APPEND|os.O_RDWR, 0666)
|
|
|
|
|
file.WriteString(fmt.Sprintf("\n##执行结束.. %s,耗时0秒\n\n", time.Now().Format("2006-01-02 15:04:05")))
|
|
|
|
|
_ = file.Close()
|
|
|
|
|
subscriptions.Status = 1
|
|
|
|
|
models.UpdateSubscription(subscriptions)
|
2023-02-03 04:43:37 +00:00
|
|
|
|
manager.LoadAndDelete(subscriptions.Id)
|
2022-11-26 02:31:26 +00:00
|
|
|
|
} else if subscriptions.Type == "file" {
|
|
|
|
|
addRawFiles(subscriptions)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func addRawFiles(subscriptions *models.Subscriptions) {
|
|
|
|
|
_ = models.UpdateSubscription(subscriptions)
|
|
|
|
|
defer func() {
|
|
|
|
|
subscriptions.Status = 1
|
|
|
|
|
_ = models.UpdateSubscription(subscriptions)
|
|
|
|
|
}()
|
|
|
|
|
err := utils.DownloadFile(subscriptions.Url, path.Join("data", "raw", subscriptions.Alias))
|
|
|
|
|
if err != nil {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
_, _ = subscriptions.WriteString(err.Error() + "\n")
|
2022-11-26 02:31:26 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
name, c, err := getSubCron(path.Join("data", "raw", subscriptions.Alias))
|
|
|
|
|
if err != nil {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
_, _ = subscriptions.WriteString(err.Error() + "\n")
|
2022-11-26 02:31:26 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
utils.Copy(path.Join("data", "raw", subscriptions.Alias), path.Join("data", "scripts", subscriptions.Alias))
|
|
|
|
|
if c != "" {
|
|
|
|
|
command, err := models.GetCronByCommand(fmt.Sprintf("task %s", subscriptions.Alias))
|
|
|
|
|
if err != nil {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
subscriptions.WriteString("已添加新的定时任务 " + name + "\n")
|
2022-11-26 02:31:26 +00:00
|
|
|
|
_, _ = cron.AddCron(&models.Crontabs{
|
|
|
|
|
Name: name,
|
|
|
|
|
Command: fmt.Sprintf("task %s", subscriptions.Alias),
|
|
|
|
|
Schedule: c,
|
|
|
|
|
Timestamp: time.Now().Format("Mon Jan 02 2006 15:04:05 MST"),
|
|
|
|
|
Status: 1,
|
|
|
|
|
Labels: []string{},
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
command.Name = name
|
|
|
|
|
command.Schedule = c
|
|
|
|
|
_ = cron.UpdateCron(command)
|
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func downloadPublicRepo(subscriptions *models.Subscriptions) error {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
|
|
|
|
|
_, _ = subscriptions.Write([]byte(fmt.Sprintf("##开始执行.. %s\n\n", time.Now().Format("2006-01-02 15:04:05"))))
|
2023-05-12 05:11:38 +00:00
|
|
|
|
|
|
|
|
|
_, err := git.PlainClone(path.Join("data", "repo", subscriptions.Alias), false, &git.CloneOptions{
|
|
|
|
|
URL: subscriptions.Url,
|
|
|
|
|
SingleBranch: true,
|
|
|
|
|
ReferenceName: plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", subscriptions.Branch)),
|
2023-09-04 06:02:25 +00:00
|
|
|
|
Progress: subscriptions,
|
2023-05-12 05:11:38 +00:00
|
|
|
|
ProxyOptions: transport.ProxyOptions{URL: config.GetKey("ProxyUrl", "")},
|
|
|
|
|
})
|
2022-11-20 14:11:47 +00:00
|
|
|
|
if err != nil {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
_, _ = subscriptions.Write([]byte(fmt.Sprintf("err: %s", err.Error())))
|
2022-11-20 14:11:47 +00:00
|
|
|
|
return err
|
|
|
|
|
}
|
2023-02-03 04:43:37 +00:00
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func addScripts(subscriptions *models.Subscriptions) {
|
2023-02-03 04:43:37 +00:00
|
|
|
|
depFiles := getDepFiles()
|
2022-11-20 14:11:47 +00:00
|
|
|
|
var extensions []string
|
|
|
|
|
if subscriptions.Extensions != "" {
|
|
|
|
|
extensions = strings.Split(subscriptions.Extensions, " ")
|
|
|
|
|
} else {
|
2023-01-13 11:32:50 +00:00
|
|
|
|
extensions = strings.Split(config.GetKey("RepoFileExtensions", "js py sh"), " ")
|
2022-11-20 14:11:47 +00:00
|
|
|
|
}
|
|
|
|
|
dir, err := os.ReadDir(path.Join("data", "repo", subscriptions.Alias))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-11-26 02:31:26 +00:00
|
|
|
|
crontabs, _ := models.QueryCronByDir(subscriptions.Alias)
|
|
|
|
|
cronMap := make(map[string]*models.Crontabs, len(crontabs))
|
|
|
|
|
for _, crontab := range crontabs {
|
|
|
|
|
cronMap[crontab.Command] = crontab
|
|
|
|
|
}
|
2023-01-15 03:12:54 +00:00
|
|
|
|
isGoMod := false
|
2022-11-20 14:11:47 +00:00
|
|
|
|
for _, entry := range dir {
|
2023-01-15 03:12:54 +00:00
|
|
|
|
|
|
|
|
|
if entry.Name() == "go.mod" {
|
|
|
|
|
isGoMod = true
|
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
// 判断文件后缀
|
|
|
|
|
if !utils.In(strings.TrimPrefix(filepath.Ext(entry.Name()), "."), extensions) {
|
|
|
|
|
if !entry.IsDir() {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 判断黑名单
|
|
|
|
|
if utils.In(entry.Name(), strings.Split(subscriptions.Blacklist, "|")) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
compile := regexp.MustCompile(`(` + subscriptions.Whitelist + `)`)
|
|
|
|
|
if compile.MatchString(entry.Name()) {
|
|
|
|
|
name, c, _ := getSubCron(path.Join("data", "repo", subscriptions.Alias, entry.Name()))
|
|
|
|
|
if c != "" {
|
|
|
|
|
command, err := models.GetCronByCommand(fmt.Sprintf("task %s", path.Join(subscriptions.Alias, entry.Name())))
|
|
|
|
|
if err != nil {
|
2023-02-03 04:43:37 +00:00
|
|
|
|
_, err1 := cron.AddCron(&models.Crontabs{
|
2022-11-20 14:11:47 +00:00
|
|
|
|
Name: name,
|
|
|
|
|
Command: fmt.Sprintf("task %s", path.Join(subscriptions.Alias, entry.Name())),
|
|
|
|
|
Schedule: c,
|
|
|
|
|
Timestamp: time.Now().Format("Mon Jan 02 2006 15:04:05 MST"),
|
|
|
|
|
Status: 1,
|
|
|
|
|
Labels: []string{},
|
|
|
|
|
})
|
2023-02-03 04:43:37 +00:00
|
|
|
|
if err1 != nil {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
_, _ = subscriptions.WriteString("定时任务添加失败: " + name + " " + err1.Error())
|
|
|
|
|
|
2023-02-03 04:43:37 +00:00
|
|
|
|
} else {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
_, _ = subscriptions.WriteString("已添加新的定时任务 " + name + "\n")
|
2023-02-03 04:43:37 +00:00
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
command.Name = name
|
|
|
|
|
command.Schedule = c
|
|
|
|
|
_ = cron.UpdateCron(command)
|
2022-11-26 02:31:26 +00:00
|
|
|
|
delete(cronMap, command.Command)
|
2022-11-20 14:11:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
utils.Copy(path.Join("data", "repo", subscriptions.Alias, entry.Name()), path.Join("data", "scripts", subscriptions.Alias, entry.Name()))
|
|
|
|
|
} else {
|
|
|
|
|
depen := regexp.MustCompile(`(` + subscriptions.Dependences + `)`)
|
|
|
|
|
if depen.MatchString(entry.Name()) {
|
|
|
|
|
utils.Copy(path.Join("data", "repo", subscriptions.Alias, entry.Name()), path.Join("data", "scripts", subscriptions.Alias, entry.Name()))
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-03 04:43:37 +00:00
|
|
|
|
if utils.In(entry.Name(), depFiles) {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
subscriptions.WriteString("已替换依赖文件: " + entry.Name() + "\n")
|
2023-02-03 04:43:37 +00:00
|
|
|
|
utils.Copy(path.Join("data", "deps", entry.Name()), path.Join("data", "scripts", subscriptions.Alias, entry.Name()))
|
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
}
|
2023-01-13 11:32:50 +00:00
|
|
|
|
if config.GetKey("AutoDelCron", "true") == "true" {
|
2022-11-26 02:31:26 +00:00
|
|
|
|
for _, m := range cronMap {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
subscriptions.WriteString("已删除失效的任务 " + m.Name + "\n")
|
2022-11-26 02:31:26 +00:00
|
|
|
|
models.DeleteCron(m.Id)
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-15 03:12:54 +00:00
|
|
|
|
if isGoMod {
|
2023-09-04 06:02:25 +00:00
|
|
|
|
subscriptions.WriteString("检测到go模块,开始自动下载golang依赖!!")
|
2023-01-15 03:12:54 +00:00
|
|
|
|
cancelChan := make(chan int, 1)
|
|
|
|
|
ctx := context.WithValue(context.Background(), "cancel", cancelChan)
|
|
|
|
|
utils.RunWithOption(ctx, &utils.RunOption{
|
|
|
|
|
Command: "go mod tidy",
|
|
|
|
|
Env: map[string]string{},
|
|
|
|
|
OnStart: func(ctx context.Context) {
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
OnEnd: func(ctx context.Context) {
|
|
|
|
|
|
|
|
|
|
},
|
2023-09-04 06:02:25 +00:00
|
|
|
|
LogFile: subscriptions,
|
2023-01-15 03:12:54 +00:00
|
|
|
|
CmdDir: path.Join("data", "scripts", subscriptions.Alias),
|
|
|
|
|
})
|
|
|
|
|
}
|
2023-02-03 04:43:37 +00:00
|
|
|
|
for _, depFile := range depFiles {
|
|
|
|
|
utils.Copy(path.Join("data", "deps", depFile), path.Join("data", "scripts", subscriptions.Alias, depFile))
|
|
|
|
|
|
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getSubCron(filePath string) (name string, cron string, err error) {
|
|
|
|
|
data, err := os.ReadFile(filePath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", "", err
|
|
|
|
|
}
|
|
|
|
|
cronReg := regexp.MustCompile(`([0-9\-*/,]{1,} ){4,5}([0-9\-*/,]){1,}`)
|
|
|
|
|
nameEnv := regexp.MustCompile(`new\sEnv\(['|"](.*?)['|"]\)`)
|
2023-02-05 04:25:36 +00:00
|
|
|
|
if nameEnv.Match(data) {
|
|
|
|
|
if cronReg.Match(data) {
|
|
|
|
|
cron = strings.TrimPrefix(strings.TrimPrefix(string(cronReg.FindAll(data, 1)[0]), "//"), " ")
|
2022-11-20 14:11:47 +00:00
|
|
|
|
} else {
|
2023-02-05 04:25:36 +00:00
|
|
|
|
key := config.GetKey("DefaultCronRule", "0 9 * * *")
|
|
|
|
|
if key == "" {
|
|
|
|
|
key = "0 9 * * *"
|
|
|
|
|
}
|
|
|
|
|
cron = key
|
2022-11-20 14:11:47 +00:00
|
|
|
|
}
|
2023-02-05 04:25:36 +00:00
|
|
|
|
name = string(nameEnv.FindAllSubmatch(data, 1)[0][1])
|
|
|
|
|
return
|
2022-11-20 14:11:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
return "", "", errors.New("not found cron")
|
|
|
|
|
}
|
|
|
|
|
}
|