Files
zurg/internal/config/v1.go
2023-11-05 01:23:41 +01:00

183 lines
4.7 KiB
Go

package config
import (
"regexp"
"sort"
"strings"
"github.com/debridmediamanager.com/zurg/pkg/logutil"
"gopkg.in/yaml.v3"
)
func loadV1Config(content []byte) (*ZurgConfigV1, error) {
var configV1 ZurgConfigV1
if err := yaml.Unmarshal(content, &configV1); err != nil {
return nil, err
}
return &configV1, nil
}
func (z *ZurgConfigV1) GetVersion() string {
return "v1"
}
func (z *ZurgConfigV1) GetDirectories() []string {
rootDirectories := make([]string, len(z.Directories))
i := 0
for directory := range z.Directories {
rootDirectories[i] = directory
i++
}
return rootDirectories
}
func (z *ZurgConfigV1) GetGroupMap() map[string][]string {
rlog := logutil.NewLogger()
log := rlog.Named("config")
var groupMap = make(map[string][]string)
var groupOrderMap = make(map[string]int) // To store GroupOrder for each directory
// Populate the groupMap and groupOrderMap
for directory, val := range z.Directories {
groupMap[val.Group] = append(groupMap[val.Group], directory)
groupOrderMap[directory] = val.GroupOrder
log.Debugf("Added directory to group: %s, group: %s, order: %d", directory, val.Group, val.GroupOrder)
}
// Sort the slice based on GroupOrder and then directory name for deterministic order
for group, dirs := range groupMap {
sort.Slice(dirs, func(i, j int) bool {
if groupOrderMap[dirs[i]] == groupOrderMap[dirs[j]] {
return dirs[i] < dirs[j] // Use directory name as secondary sort criterion
}
return groupOrderMap[dirs[i]] < groupOrderMap[dirs[j]]
})
groupMap[group] = dirs
log.Debugf("Sorted directories within a group: %s %v", group, dirs)
}
// Return a deep copy of the map
result := make(map[string][]string)
for k, v := range groupMap {
temp := make([]string, len(v))
copy(temp, v)
result[k] = temp
}
return result
}
func (z *ZurgConfigV1) MeetsConditions(directory, torrentID, torrentName string, fileNames []string) bool {
if _, ok := z.Directories[directory]; !ok {
return false
}
for _, filter := range z.Directories[directory].Filters {
if z.matchFilter(torrentID, torrentName, fileNames, filter) {
return true
}
}
return false
}
func (z *ZurgConfigV1) matchFilter(fileID, torrentName string, fileNames []string, filter *FilterConditionsV1) bool {
if filter.ID != "" && fileID == filter.ID {
return true
}
if filter.RegexStr != "" {
regex := compilePattern(filter.RegexStr)
if regex.MatchString(torrentName) {
return true
}
}
if filter.ContainsStrict != "" && strings.Contains(torrentName, filter.ContainsStrict) {
return true
}
if filter.Contains != "" && strings.Contains(strings.ToLower(torrentName), strings.ToLower(filter.Contains)) {
return true
}
if filter.NotContainsStrict != "" && !strings.Contains(torrentName, filter.NotContainsStrict) {
return true
}
if filter.NotContains != "" && !strings.Contains(strings.ToLower(torrentName), strings.ToLower(filter.NotContains)) {
return true
}
if len(filter.And) > 0 {
andResult := true
for _, andFilter := range filter.And {
andResult = andResult && z.matchFilter(fileID, torrentName, fileNames, andFilter)
if !andResult {
return false
}
}
return true
}
if len(filter.Or) > 0 {
for _, orFilter := range filter.Or {
if z.matchFilter(fileID, torrentName, fileNames, orFilter) {
return true
}
}
}
if filter.FileInsideRegexStr != "" {
regex := compilePattern(filter.FileInsideRegexStr)
for _, filename := range fileNames {
if regex.MatchString(filename) {
return true
}
}
}
if filter.FileInsideContains != "" {
for _, filename := range fileNames {
if strings.Contains(strings.ToLower(filename), strings.ToLower(filter.FileInsideContains)) {
return true
}
}
}
if filter.FileInsideContainsStrict != "" {
for _, filename := range fileNames {
if strings.Contains(filename, filter.FileInsideContainsStrict) {
return true
}
}
}
return false
}
func compilePattern(pattern string) *regexp.Regexp {
flags := map[rune]string{
'i': "(?i)",
'm': "(?m)",
's': "(?s)",
'x': "(?x)",
}
lastSlash := strings.LastIndex(pattern, "/")
secondLastSlash := strings.LastIndex(pattern[:lastSlash], "/")
// Extract the core pattern
corePattern := pattern[secondLastSlash+1 : lastSlash]
// Extract and process flags
flagSection := pattern[lastSlash+1:]
flagString := ""
processedFlags := make(map[rune]bool)
for _, flag := range flagSection {
if replacement, ok := flags[flag]; ok && !processedFlags[flag] {
flagString += replacement
processedFlags[flag] = true
}
}
// Combine the processed flags with the core pattern
finalPattern := flagString + corePattern
// Validate pattern
if finalPattern == "" || finalPattern == flagString {
return nil
}
return regexp.MustCompile(finalPattern)
}