From cf03206283a3c7e8e90e9e8ca277efea49b7a2b5 Mon Sep 17 00:00:00 2001 From: Aaron Liu <912394456@qq.com> Date: Fri, 7 Apr 2023 19:33:02 +0800 Subject: [PATCH] feat(thumb): generator settings and test button --- models/defaults.go | 1 + pkg/thumb/tester.go | 74 ++++++++++++++++++++++++++++++++++++ routers/controllers/admin.go | 11 ++++++ routers/router.go | 10 ++++- service/admin/site.go | 20 ++++++++++ 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 pkg/thumb/tester.go diff --git a/models/defaults.go b/models/defaults.go index 97ef7b8..b13f22e 100644 --- a/models/defaults.go +++ b/models/defaults.go @@ -112,6 +112,7 @@ Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; verti {Name: "thumb_ffmpeg_enabled", Value: "0", Type: "thumb"}, {Name: "thumb_vips_path", Value: "vips", Type: "thumb"}, {Name: "thumb_vips_exts", Value: "csv,mat,img,hdr,pbm,pgm,ppm,pfm,pnm,svg,svgz,j2k,jp2,jpt,j2c,jpc,gif,png,jpg,jpeg,jpe,webp,tif,tiff,fits,fit,fts,exr,jxl,pdf,heic,heif,avif,svs,vms,vmu,ndpi,scn,mrxs,svslide,bif,raw", Type: "thumb"}, + {Name: "thumb_ffmpeg_seek", Value: "00:00:01.00", Type: "thumb"}, {Name: "thumb_ffmpeg_path", Value: "ffmpeg", Type: "thumb"}, {Name: "thumb_ffmpeg_exts", Value: "3g2,3gp,asf,asx,avi,divx,flv,m2ts,m2v,m4v,mkv,mov,mp4,mpeg,mpg,mts,mxf,ogv,rm,swf,webm,wmv", Type: "thumb"}, {Name: "thumb_libreoffice_path", Value: "soffice", Type: "thumb"}, diff --git a/pkg/thumb/tester.go b/pkg/thumb/tester.go new file mode 100644 index 0000000..2dcc4be --- /dev/null +++ b/pkg/thumb/tester.go @@ -0,0 +1,74 @@ +package thumb + +import ( + "bytes" + "context" + "errors" + "fmt" + "os/exec" + "strings" +) + +var ( + ErrUnknownGenerator = errors.New("unknown generator type") + ErrUnknownOutput = errors.New("unknown output from generator") +) + +// TestGenerator tests thumb generator by getting lib version +func TestGenerator(ctx context.Context, name, executable string) (string, error) { + switch name { + case "vips": + return testVipsGenerator(ctx, executable) + case "ffmpeg": + return testFfmpegGenerator(ctx, executable) + case "libreOffice": + return testLibreOfficeGenerator(ctx, executable) + default: + return "", ErrUnknownGenerator + } +} + +func testVipsGenerator(ctx context.Context, executable string) (string, error) { + cmd := exec.CommandContext(ctx, executable, "--version") + var output bytes.Buffer + cmd.Stdout = &output + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("failed to invoke vips executable: %w", err) + } + + if !strings.Contains(output.String(), "vips") { + return "", ErrUnknownOutput + } + + return output.String(), nil +} + +func testFfmpegGenerator(ctx context.Context, executable string) (string, error) { + cmd := exec.CommandContext(ctx, executable, "-version") + var output bytes.Buffer + cmd.Stdout = &output + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("failed to invoke ffmpeg executable: %w", err) + } + + if !strings.Contains(output.String(), "ffmpeg") { + return "", ErrUnknownOutput + } + + return output.String(), nil +} + +func testLibreOfficeGenerator(ctx context.Context, executable string) (string, error) { + cmd := exec.CommandContext(ctx, executable, "--version") + var output bytes.Buffer + cmd.Stdout = &output + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("failed to invoke libreoffice executable: %w", err) + } + + if !strings.Contains(output.String(), "LibreOffice") { + return "", ErrUnknownOutput + } + + return output.String(), nil +} diff --git a/routers/controllers/admin.go b/routers/controllers/admin.go index 7d6bc40..2412777 100644 --- a/routers/controllers/admin.go +++ b/routers/controllers/admin.go @@ -98,6 +98,17 @@ func AdminSendTestMail(c *gin.Context) { } } +// AdminTestThumbGenerator Tests thumb generator +func AdminTestThumbGenerator(c *gin.Context) { + var service admin.ThumbGeneratorTestService + if err := c.ShouldBindJSON(&service); err == nil { + res := service.Test(c) + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} + // AdminTestAria2 测试aria2连接 func AdminTestAria2(c *gin.Context) { var service admin.Aria2TestService diff --git a/routers/router.go b/routers/router.go index 8d872c7..d5f6b43 100644 --- a/routers/router.go +++ b/routers/router.go @@ -422,8 +422,14 @@ func InitMasterRouter() *gin.Engine { admin.GET("groups", controllers.AdminGetGroups) // 重新加载子服务 admin.GET("reload/:service", controllers.AdminReloadService) - // 重新加载子服务 - admin.POST("mailTest", controllers.AdminSendTestMail) + // 测试设置 + test := admin.Group("test") + { + // 测试邮件设置 + test.POST("mail", controllers.AdminSendTestMail) + // 测试缩略图生成器调用 + test.POST("thumb", controllers.AdminTestThumbGenerator) + } // 离线下载相关 aria2 := admin.Group("aria2") diff --git a/service/admin/site.go b/service/admin/site.go index 918b33b..69aa2d8 100644 --- a/service/admin/site.go +++ b/service/admin/site.go @@ -9,6 +9,8 @@ import ( "github.com/cloudreve/Cloudreve/v3/pkg/conf" "github.com/cloudreve/Cloudreve/v3/pkg/email" "github.com/cloudreve/Cloudreve/v3/pkg/serializer" + "github.com/cloudreve/Cloudreve/v3/pkg/thumb" + "github.com/gin-gonic/gin" ) func init() { @@ -143,3 +145,21 @@ func (service *NoParamService) Summary() serializer.Response { Data: resp, } } + +// ThumbGeneratorTestService 缩略图生成测试服务 +type ThumbGeneratorTestService struct { + Name string `json:"name" binding:"required"` + Executable string `json:"executable" binding:"required"` +} + +// Test 通过获取生成器版本来测试 +func (s *ThumbGeneratorTestService) Test(c *gin.Context) serializer.Response { + version, err := thumb.TestGenerator(c, s.Name, s.Executable) + if err != nil { + return serializer.Err(serializer.CodeParamErr, err.Error(), err) + } + + return serializer.Response{ + Data: version, + } +}