From 95920064be45944a2c3b2e2c54174275733318f6 Mon Sep 17 00:00:00 2001 From: 3343780376 <3343780376@qq.com> Date: Fri, 13 Jan 2023 19:32:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9D=99=E6=80=81=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E8=87=AA=E5=8A=A8=E4=B8=8B=E8=BD=BD=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 2 + Dockerfile | 7 ++- controller/router.go | 2 + go.mod | 2 + go.sum | 8 ++++ main.go | 27 +++++++++++ service/config/config.go | 8 ++-- service/cron/manager.go | 12 +++-- service/subscription/manager.go | 6 +-- utils/tar.go | 85 +++++++++++++++++++++++++++++++++ 10 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 utils/tar.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e6da7c..cccb28e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,3 +27,5 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.TOKEN }} + + diff --git a/Dockerfile b/Dockerfile index 6aa26bc..a283f81 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,10 +9,14 @@ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/local/go/bin:/usr/sbin:/usr/bin:/sb SHELL=/bin/bash \ PS1="\u@\h:\w \$ " \ QL_DIR=/ql \ - QL_BRANCH=${QL_BRANCH} + QL_BRANCH=${QL_BRANCH} \ + GO111MODULE=on \ + GOPROXY=https://goproxy.cn WORKDIR ${QL_DIR} +COPY --from=golang:1.18-alpine /usr/local/go/ /usr/local/go/ + RUN set -x \ && sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ && apk update -f \ @@ -46,7 +50,6 @@ RUN set -x \ COPY ./dist/docker_linux_$TARGETARCH*/qinglong-go ${QL_DIR}/ql -RUN chmod -R 777 /ql/ql EXPOSE 5700 diff --git a/controller/router.go b/controller/router.go index d213078..55eb8db 100644 --- a/controller/router.go +++ b/controller/router.go @@ -1,6 +1,7 @@ package controller import ( + "github.com/gin-contrib/gzip" "github.com/gin-contrib/static" "github.com/gin-gonic/gin" "github.com/huoxue1/qinglong-go/api" @@ -11,6 +12,7 @@ func Router() *gin.Engine { engine := gin.New() engine.Use(gin.Logger()) engine.Use(gin.Recovery()) + engine.Use(gzip.Gzip(gzip.DefaultCompression)) engine.Use(static.Serve("/", static.LocalFile("static/dist/", false))) engine.NoRoute(func(ctx *gin.Context) { if ctx.Request.Method == http.MethodGet { diff --git a/go.mod b/go.mod index 2de0d2c..1343f93 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,9 @@ require ( require ( github.com/cheekybits/genny v1.0.0 // indirect + github.com/dablelv/go-huge-util v0.0.31 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gin-contrib/gzip v0.0.6 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect diff --git a/go.sum b/go.sum index 9c72082..6bb0b2a 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,8 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/dablelv/go-huge-util v0.0.31 h1:V6OFWmGwjdl1s+dGImF/S6crESVzm8x9+PaUF7KrYBk= +github.com/dablelv/go-huge-util v0.0.31/go.mod h1:CTdXt+L11UBDS+dg9LPgslqDMXcCvhTv51IikcQDxGA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -86,6 +88,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U= @@ -339,6 +343,7 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -404,6 +409,7 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= @@ -675,6 +681,7 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -768,6 +775,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/main.go b/main.go index 424459c..5280709 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,13 @@ package main import ( + "fmt" nested "github.com/Lyrics-you/sail-logrus-formatter/sailor" + "github.com/dablelv/go-huge-util/zip" "github.com/huoxue1/qinglong-go/controller" "github.com/huoxue1/qinglong-go/service" + "github.com/huoxue1/qinglong-go/service/config" + "github.com/huoxue1/qinglong-go/utils" rotates "github.com/lestrrat-go/file-rotatelogs" log "github.com/sirupsen/logrus" "io" @@ -37,7 +41,30 @@ func init() { } func main() { + checkStatic() service.AppInit() engine := controller.Router() _ = engine.Run(":5700") } + +func checkStatic() { + if !utils.FileExist("./static/") { + log.Warningln("检测到静态文件资源不存在,即将自动下载文件!") + log.Infoln("downloading file from ", fmt.Sprintf("https://github.com/huoxue1/qinglong/releases/download/%s/static.zip", config.GetVersion())) + response, err := utils.GetClient().R().Get(fmt.Sprintf("https://github.com/huoxue1/qinglong/releases/download/%s/static.zip", config.GetVersion())) + if err != nil { + log.Errorln("下载静态资源文件失败 " + err.Error()) + return + } + err = os.WriteFile("static.zip", response.Bytes(), 0666) + if err != nil { + log.Errorln("写入压缩文件错误 " + err.Error()) + return + } + err = zip.Unzip("static.zip", ".") + if err != nil { + log.Errorln(err.Error()) + return + } + } +} diff --git a/service/config/config.go b/service/config/config.go index a5fa5c2..b2e2bc9 100644 --- a/service/config/config.go +++ b/service/config/config.go @@ -6,16 +6,16 @@ import ( "regexp" ) -var VERSION = "test" +var VERSION = "v1.0.0" -func GetKey(key string) string { +func GetKey(key, defaultValue string) string { file, err := os.ReadFile(path.Join("data", "config", "config.sh")) if err != nil { - return "" + return defaultValue } compile := regexp.MustCompile(key + `="(.*?)"`) if !compile.Match(file) { - return "" + return defaultValue } datas := compile.FindAllStringSubmatch(string(file), 1) return datas[0][1] diff --git a/service/cron/manager.go b/service/cron/manager.go index d8f869e..2b67a18 100644 --- a/service/cron/manager.go +++ b/service/cron/manager.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/google/uuid" "github.com/huoxue1/qinglong-go/models" + "github.com/huoxue1/qinglong-go/service/config" "github.com/huoxue1/qinglong-go/service/env" "github.com/huoxue1/qinglong-go/utils" "github.com/robfig/cron/v3" @@ -156,13 +157,18 @@ func AddTask(crontabs *models.Crontabs) { func handCommand(command string) *task { ta := new(task) commands := strings.Split(command, " ") + + pythonCmd := config.GetKey("PythonCmd", "python") + JsCmd := config.GetKey("JsCmd", "node") + ShCmd := config.GetKey("ShCmd", "bash") + if commands[0] == "task" { if strings.HasSuffix(commands[1], ".py") { - ta.cmd = "python3 " + commands[1] + ta.cmd = pythonCmd + " " + commands[1] } else if strings.HasSuffix(commands[1], ".js") { - ta.cmd = "node " + commands[1] + ta.cmd = JsCmd + " " + commands[1] } else if strings.HasSuffix(commands[1], ".sh") { - ta.cmd = "bash " + commands[1] + ta.cmd = ShCmd + " " + commands[1] } else if strings.HasSuffix(commands[1], ".ts") { ta.cmd = "ts-node-transpile-only " + commands[1] } diff --git a/service/subscription/manager.go b/service/subscription/manager.go index d48a563..c5fd597 100644 --- a/service/subscription/manager.go +++ b/service/subscription/manager.go @@ -46,7 +46,7 @@ func downloadFiles(subscriptions *models.Subscriptions) { if err != nil { return } - if config.GetKey("AutoAddCron") == "true" { + if config.GetKey("AutoAddCron", "true") == "true" { addScripts(subscriptions) } else { log.Infoln("未配置自动添加定时任务,不添加任务!") @@ -141,7 +141,7 @@ func addScripts(subscriptions *models.Subscriptions) { if subscriptions.Extensions != "" { extensions = strings.Split(subscriptions.Extensions, " ") } else { - extensions = strings.Split(config.GetKey("RepoFileExtensions"), " ") + extensions = strings.Split(config.GetKey("RepoFileExtensions", "js py sh"), " ") } dir, err := os.ReadDir(path.Join("data", "repo", subscriptions.Alias)) if err != nil { @@ -194,7 +194,7 @@ func addScripts(subscriptions *models.Subscriptions) { } } } - if config.GetKey("AutoDelCron") == "true" { + if config.GetKey("AutoDelCron", "true") == "true" { for _, m := range cronMap { file.WriteString("已删除失效的任务 " + m.Name + "\n") models.DeleteCron(m.Id) diff --git a/utils/tar.go b/utils/tar.go new file mode 100644 index 0000000..a9be230 --- /dev/null +++ b/utils/tar.go @@ -0,0 +1,85 @@ +package utils + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "os" + "path/filepath" +) + +func UnTar(dst, src string) (err error) { + // 打开准备解压的 tar 包 + fr, err := os.Open(src) + if err != nil { + return + } + defer fr.Close() + + // 将打开的文件先解压 + gr, err := gzip.NewReader(fr) + if err != nil { + return + } + defer gr.Close() + + // 通过 gr 创建 tar.Reader + tr := tar.NewReader(gr) + + // 现在已经获得了 tar.Reader 结构了,只需要循环里面的数据写入文件就可以了 + for { + hdr, err := tr.Next() + + switch { + case err == io.EOF: + return nil + case err != nil: + return err + case hdr == nil: + continue + } + + // 处理下保存路径,将要保存的目录加上 header 中的 Name + // 这个变量保存的有可能是目录,有可能是文件,所以就叫 FileDir 了…… + dstFileDir := filepath.Join(dst, hdr.Name) + + // 根据 header 的 Typeflag 字段,判断文件的类型 + switch hdr.Typeflag { + case tar.TypeDir: // 如果是目录时候,创建目录 + // 判断下目录是否存在,不存在就创建 + if b := ExistDir(dstFileDir); !b { + // 使用 MkdirAll 不使用 Mkdir ,就类似 Linux 终端下的 mkdir -p, + // 可以递归创建每一级目录 + if err := os.MkdirAll(dstFileDir, 0775); err != nil { + return err + } + } + case tar.TypeReg: // 如果是文件就写入到磁盘 + // 创建一个可以读写的文件,权限就使用 header 中记录的权限 + // 因为操作系统的 FileMode 是 int32 类型的,hdr 中的是 int64,所以转换下 + file, err := os.OpenFile(dstFileDir, os.O_CREATE|os.O_RDWR, os.FileMode(hdr.Mode)) + if err != nil { + return err + } + n, err := io.Copy(file, tr) + if err != nil { + return err + } + // 将解压结果输出显示 + fmt.Printf("成功解压: %s , 共处理了 %d 个字符\n", dstFileDir, n) + + // 不要忘记关闭打开的文件,因为它是在 for 循环中,不能使用 defer + // 如果想使用 defer 就放在一个单独的函数中 + file.Close() + } + } + + return nil +} + +// 判断目录是否存在 +func ExistDir(dirname string) bool { + fi, err := os.Stat(dirname) + return (err == nil || os.IsExist(err)) && fi.IsDir() +}