mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 11:36:36 +08:00
196 lines
6.0 KiB
Go
196 lines
6.0 KiB
Go
package service
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/ShukeBta/MediaStationGo/internal/config"
|
|
"github.com/ShukeBta/MediaStationGo/internal/model"
|
|
)
|
|
|
|
func TestDownloadCompleteAutoOrganizesContentPath(t *testing.T) {
|
|
root := t.TempDir()
|
|
src := filepath.Join(root, "downloads", "国产剧", "狂飙.S01E01.2023.1080p.mkv")
|
|
dest := filepath.Join(root, "media")
|
|
if err := os.MkdirAll(filepath.Dir(src), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(src, []byte("episode"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
repos := newOrganizerTestRepo(t)
|
|
if err := repos.DB.AutoMigrate(&model.DownloadTask{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for key, value := range map[string]string{
|
|
"organizer.auto_after_download": "true",
|
|
"organize.target_dir": dest,
|
|
"organize.transfer_mode": "copy",
|
|
} {
|
|
if err := repos.Setting.Set(t.Context(), key, value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
org := NewOrganizerService(&config.Config{}, zap.NewNop(), repos)
|
|
svc := NewDownloadService(zap.NewNop(), repos, NewHub(zap.NewNop()), org)
|
|
svc.onTorrentComplete(t.Context(), QBitTorrent{
|
|
Hash: "done123",
|
|
Name: "狂飙.S01E01.2023.1080p",
|
|
Progress: 1,
|
|
SavePath: filepath.Join(root, "downloads", "国产剧"),
|
|
ContentPath: src,
|
|
})
|
|
|
|
want := filepath.Join(dest, "电视剧", "国产剧", "狂飙", "Season 01", "狂飙 - S01E01.mkv")
|
|
if _, err := os.Stat(want); err != nil {
|
|
t.Fatalf("auto organized file missing at %q: %v", want, err)
|
|
}
|
|
if _, err := os.Stat(src); err != nil {
|
|
t.Fatalf("copy mode should keep source: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDownloadCompleteAutoOrganizeUsesTaskMediaCategory(t *testing.T) {
|
|
root := t.TempDir()
|
|
src := filepath.Join(root, "downloads", "Motherhood.of.Taihang.S01E01.2026.1080p.mkv")
|
|
dest := filepath.Join(root, "media")
|
|
writeOrgFile(t, src, "episode")
|
|
|
|
repos := newOrganizerTestRepo(t)
|
|
if err := repos.DB.AutoMigrate(&model.DownloadTask{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for key, value := range map[string]string{
|
|
"organizer.auto_after_download": "true",
|
|
"organize.target_dir": dest,
|
|
"organize.transfer_mode": "copy",
|
|
} {
|
|
if err := repos.Setting.Set(t.Context(), key, value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
task := &model.DownloadTask{
|
|
UserID: "u1",
|
|
Source: "qbittorrent",
|
|
URL: "magnet:?xt=urn:btih:motherhood",
|
|
Title: "Motherhood.of.Taihang.S01E01.2026.1080p",
|
|
SavePath: filepath.Join(root, "downloads"),
|
|
MediaType: "tv",
|
|
MediaCategory: "国产剧",
|
|
Status: "completed",
|
|
Progress: 1,
|
|
}
|
|
if err := repos.Download.Create(t.Context(), task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
org := NewOrganizerService(&config.Config{}, zap.NewNop(), repos)
|
|
svc := NewDownloadService(zap.NewNop(), repos, NewHub(zap.NewNop()), org)
|
|
svc.onTorrentComplete(t.Context(), QBitTorrent{
|
|
Hash: "done-category",
|
|
Name: "Motherhood.of.Taihang.S01E01.2026.1080p",
|
|
Progress: 1,
|
|
SavePath: filepath.Join(root, "downloads"),
|
|
ContentPath: src,
|
|
})
|
|
|
|
categoryRoot := filepath.Join(dest, "电视剧", "国产剧")
|
|
var organized string
|
|
err := filepath.WalkDir(categoryRoot, func(path string, entry os.DirEntry, err error) error {
|
|
if err != nil || entry.IsDir() {
|
|
return err
|
|
}
|
|
if filepath.Ext(path) == ".mkv" {
|
|
organized = path
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("walk organized category: %v", err)
|
|
}
|
|
if organized == "" {
|
|
t.Fatalf("expected organized file under %q", categoryRoot)
|
|
}
|
|
wrongRoot := filepath.Join(dest, "电视剧", "Motherhood Of Taihang")
|
|
if _, err := os.Stat(wrongRoot); !os.IsNotExist(err) {
|
|
t.Fatalf("unexpected uncategorized organize root %q, err=%v", wrongRoot, err)
|
|
}
|
|
}
|
|
|
|
func TestDownloadCompleteOnlyReplacesExistingWhenTaskAllowsWash(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
allowWash bool
|
|
wantContent string
|
|
}{
|
|
{name: "wash disabled keeps existing", allowWash: false, wantContent: "inception-1080p"},
|
|
{name: "wash enabled replaces existing", allowWash: true, wantContent: "inception-2160p"},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
root := t.TempDir()
|
|
src := filepath.Join(root, "downloads", "Inception 2010 2160p BluRay.mkv")
|
|
dest := filepath.Join(root, "media")
|
|
existing := filepath.Join(dest, "电影", "Inception (2010)", "Inception (2010).mkv")
|
|
writeOrgFile(t, src, "inception-2160p")
|
|
writeOrgFile(t, existing, "inception-1080p")
|
|
|
|
repos := newOrganizerTestRepo(t)
|
|
if err := repos.DB.AutoMigrate(&model.DownloadTask{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for key, value := range map[string]string{
|
|
"organizer.auto_after_download": "true",
|
|
"organize.target_dir": dest,
|
|
"organize.transfer_mode": "copy",
|
|
} {
|
|
if err := repos.Setting.Set(t.Context(), key, value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := repos.Media.Upsert(t.Context(), &model.Media{
|
|
Title: "Inception",
|
|
Path: existing,
|
|
Year: 2010,
|
|
Container: "mkv",
|
|
Width: 1920,
|
|
Height: 1080,
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := repos.Download.Create(t.Context(), &model.DownloadTask{
|
|
Source: "qbittorrent",
|
|
URL: "magnet:?xt=urn:btih:inception",
|
|
Title: "Inception 2010 2160p BluRay",
|
|
SavePath: filepath.Dir(src),
|
|
Status: "completed",
|
|
Progress: 1,
|
|
AllowExistingLibrary: tc.allowWash,
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
org := NewOrganizerService(&config.Config{}, zap.NewNop(), repos)
|
|
svc := NewDownloadService(zap.NewNop(), repos, NewHub(zap.NewNop()), org)
|
|
svc.onTorrentComplete(t.Context(), QBitTorrent{
|
|
Hash: "inception",
|
|
Name: "Inception 2010 2160p BluRay",
|
|
Progress: 1,
|
|
SavePath: filepath.Dir(src),
|
|
ContentPath: src,
|
|
})
|
|
|
|
got, err := os.ReadFile(existing)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(got) != tc.wantContent {
|
|
t.Fatalf("existing content = %q, want %q", string(got), tc.wantContent)
|
|
}
|
|
})
|
|
}
|
|
}
|