Ztorrent/internal/sorter/sorter.go

67 lines
1.9 KiB
Go

package sorter
import (
"fmt"
"os"
"path/filepath"
"regexp"
"github.com/veggiedefender/torrent-client/internal/logger"
)
var (
tvShowRegex = regexp.MustCompile(`(?i)(s\d{2}e\d{2}|season\s*\d+|сезон\s*\d+)`)
movieRegex = regexp.MustCompile(`(?i)(1080p|720p|2160p|4k|bdrip|web-dl|bluray|camrip)`)
gameRegex = regexp.MustCompile(`(?i)(repack|fitgirl|dodi|skidrow|codex|crack|iso)`)
musicRegex = regexp.MustCompile(`(?i)(discography|flac|mp3\s*320)`)
)
// Categorize analyzes the torrent name and determines its category.
func Categorize(name string) string {
if tvShowRegex.MatchString(name) {
return "TV Shows"
}
if movieRegex.MatchString(name) {
return "Movies"
}
if gameRegex.MatchString(name) {
return "Games"
}
if musicRegex.MatchString(name) {
return "Music"
}
return "Other"
}
// SortAndMove moves the downloaded files (or folder) to a sub-folder based on its category.
func SortAndMove(outputRoot, torrentName string) (string, error) {
category := Categorize(torrentName)
if category == "Other" || category == "" {
return "", nil // Do not move if category is unknown
}
sourcePath := filepath.Join(outputRoot, torrentName)
if _, err := os.Stat(sourcePath); os.IsNotExist(err) {
return "", fmt.Errorf("source path does not exist: %s", sourcePath)
}
destDir := filepath.Join(outputRoot, category)
if err := os.MkdirAll(destDir, 0o755); err != nil {
return "", fmt.Errorf("failed to create category directory: %w", err)
}
destPath := filepath.Join(destDir, torrentName)
// If it already exists in the destination, maybe we resume/overwrite
if _, err := os.Stat(destPath); err == nil {
logger.Warn("SYS", "Destination path already exists, skipping move: %s", destPath)
return "", nil
}
if err := os.Rename(sourcePath, destPath); err != nil {
return "", fmt.Errorf("failed to move files to category folder: %w", err)
}
logger.Info("SYS", "Smart Sorter moved '%s' to '%s'", torrentName, category)
return destDir, nil
}