Detect arithmetic progression
This commit is contained in:
@@ -4,8 +4,10 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/debridmediamanager.com/zurg/pkg/utils"
|
||||
"go.uber.org/zap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -88,13 +90,23 @@ func (z *ZurgConfigV1) matchFilter(torrentName string, torrentIDs, fileNames []s
|
||||
if filter.RegexStr != "" {
|
||||
regex, err := compilePattern(filter.RegexStr)
|
||||
if err != nil {
|
||||
z.log.Errorf("Failed to compile regex: %v", err)
|
||||
z.log.Errorf("Failed to compile regex %s error: %v", filter.RegexStr, err)
|
||||
return false
|
||||
}
|
||||
if regex.MatchString(torrentName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if filter.NotRegexStr != "" {
|
||||
regex, err := compilePattern(filter.NotRegexStr)
|
||||
if err != nil {
|
||||
z.log.Errorf("Failed to compile not_regex %s error: %v", filter.NotRegexStr, err)
|
||||
return false
|
||||
}
|
||||
if !regex.MatchString(torrentName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if filter.ContainsStrict != "" && strings.Contains(torrentName, filter.ContainsStrict) {
|
||||
return true
|
||||
}
|
||||
@@ -127,7 +139,7 @@ func (z *ZurgConfigV1) matchFilter(torrentName string, torrentIDs, fileNames []s
|
||||
if filter.FileInsideRegexStr != "" {
|
||||
regex, err := compilePattern(filter.FileInsideRegexStr)
|
||||
if err != nil {
|
||||
z.log.Errorf("Failed to compile regex: %v", err)
|
||||
z.log.Errorf("Failed to compile any_file_inside_regex %s error: %v", filter.FileInsideRegexStr, err)
|
||||
return false
|
||||
}
|
||||
for _, filename := range fileNames {
|
||||
@@ -136,12 +148,34 @@ func (z *ZurgConfigV1) matchFilter(torrentName string, torrentIDs, fileNames []s
|
||||
}
|
||||
}
|
||||
}
|
||||
if filter.FileInsideNotRegexStr != "" {
|
||||
regex, err := compilePattern(filter.FileInsideNotRegexStr)
|
||||
if err != nil {
|
||||
z.log.Errorf("Failed to compile any_file_inside_not_regex %s error: %v", filter.FileInsideNotRegexStr, err)
|
||||
return false
|
||||
}
|
||||
for _, filename := range fileNames {
|
||||
if !regex.MatchString(filename) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if filter.FileInsideContains != "" {
|
||||
for _, filename := range fileNames {
|
||||
if strings.Contains(strings.ToLower(filename), strings.ToLower(filter.FileInsideContains)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if filter.FileInsideNotContains != "" {
|
||||
for _, filename := range fileNames {
|
||||
if !strings.Contains(strings.ToLower(filename), strings.ToLower(filter.FileInsideNotContains)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if filter.FileInsideContainsStrict != "" {
|
||||
for _, filename := range fileNames {
|
||||
@@ -149,6 +183,24 @@ func (z *ZurgConfigV1) matchFilter(torrentName string, torrentIDs, fileNames []s
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if filter.FileInsideNotContainsStrict != "" {
|
||||
for _, filename := range fileNames {
|
||||
if !strings.Contains(filename, filter.FileInsideNotContainsStrict) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if filter.HasEpisodes {
|
||||
regex := regexp.MustCompile(`(?i)s\d\de\d\d`)
|
||||
for _, filename := range fileNames {
|
||||
if regex.MatchString(filename) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return checkArithmeticSequenceInFilenames(fileNames)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -188,3 +240,54 @@ func compilePattern(pattern string) (*regexp.Regexp, error) {
|
||||
|
||||
return regexp.Compile(finalPattern)
|
||||
}
|
||||
|
||||
func hasIncreasingSequence(arr []int) bool {
|
||||
if len(arr) < 3 {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(arr)-2; i++ {
|
||||
if arr[i] < arr[i+1] && arr[i+1] < arr[i+2] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func checkArithmeticSequenceInFilenames(files []string) bool {
|
||||
if len(files) < 3 {
|
||||
return false
|
||||
}
|
||||
r := regexp.MustCompile(`\d+`)
|
||||
for _, file := range files {
|
||||
if !utils.IsStreamable(file) {
|
||||
continue
|
||||
}
|
||||
matches := r.FindAllStringIndex(file, -1)
|
||||
for _, match := range matches {
|
||||
numSet := make(map[int]struct{})
|
||||
for _, file := range files {
|
||||
if !utils.IsStreamable(file) {
|
||||
continue
|
||||
}
|
||||
if match[0] >= 0 && match[1] <= len(file) {
|
||||
num, err := strconv.Atoi(file[match[0]:match[1]])
|
||||
if err == nil {
|
||||
numSet[num] = struct{}{}
|
||||
}
|
||||
} else {
|
||||
// out of bounds, ignore
|
||||
continue
|
||||
}
|
||||
}
|
||||
numList := make([]int, 0, len(numSet))
|
||||
for num := range numSet {
|
||||
numList = append(numList, num)
|
||||
}
|
||||
sort.Ints(numList)
|
||||
if hasIncreasingSequence(numList) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -18,13 +18,19 @@ type FilterConditionsV1 struct {
|
||||
RegexStr string `yaml:"regex"`
|
||||
Contains string `yaml:"contains"`
|
||||
ContainsStrict string `yaml:"contains_strict"`
|
||||
NotRegexStr string `yaml:"not_regex"`
|
||||
NotContains string `yaml:"not_contains"`
|
||||
NotContainsStrict string `yaml:"not_contains_strict"`
|
||||
|
||||
And []*FilterConditionsV1 `yaml:"and"`
|
||||
Or []*FilterConditionsV1 `yaml:"or"`
|
||||
|
||||
FileInsideRegexStr string `yaml:"any_file_inside_regex"`
|
||||
FileInsideContains string `yaml:"any_file_inside_contains"`
|
||||
FileInsideContainsStrict string `yaml:"any_file_inside_contains_strict"`
|
||||
FileInsideRegexStr string `yaml:"any_file_inside_regex"`
|
||||
FileInsideContains string `yaml:"any_file_inside_contains"`
|
||||
FileInsideContainsStrict string `yaml:"any_file_inside_contains_strict"`
|
||||
FileInsideNotRegexStr string `yaml:"any_file_inside_not_regex"`
|
||||
FileInsideNotContains string `yaml:"any_file_inside_not_contains"`
|
||||
FileInsideNotContainsStrict string `yaml:"any_file_inside_not_contains_strict"`
|
||||
|
||||
HasEpisodes bool `yaml:"has_episodes"`
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/debridmediamanager.com/zurg/internal/config"
|
||||
"github.com/debridmediamanager.com/zurg/pkg/logutil"
|
||||
"github.com/debridmediamanager.com/zurg/pkg/realdebrid"
|
||||
"github.com/debridmediamanager.com/zurg/pkg/utils"
|
||||
cmap "github.com/orcaman/concurrent-map/v2"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"go.uber.org/zap"
|
||||
@@ -96,9 +97,7 @@ func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, p
|
||||
}
|
||||
}
|
||||
|
||||
anotherCt := 0
|
||||
allTorrents.IterCb(func(accessKey string, torrent *Torrent) {
|
||||
anotherCt++
|
||||
// get IDs
|
||||
var torrentIDs []string
|
||||
for _, instance := range torrent.Instances {
|
||||
@@ -293,11 +292,7 @@ func (t *TorrentManager) startRefreshJob() {
|
||||
}
|
||||
|
||||
// get filenames
|
||||
var filenames []string
|
||||
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
|
||||
filenames = append(filenames, file.Path)
|
||||
})
|
||||
|
||||
filenames := torrent.SelectedFiles.Keys()
|
||||
// Map torrents to directories
|
||||
switch t.cfg.GetVersion() {
|
||||
case "v1":
|
||||
@@ -593,7 +588,7 @@ func (t *TorrentManager) Repair(accessKey string) {
|
||||
var links []string
|
||||
streamableCount := 0
|
||||
torrent.SelectedFiles.IterCb(func(_ string, file *File) {
|
||||
if isStreamable(file.Path) {
|
||||
if utils.IsStreamable(file.Path) {
|
||||
streamableCount++
|
||||
}
|
||||
fileCopy := &File{
|
||||
|
||||
@@ -3,7 +3,6 @@ package torrent
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getFileIDs(files []File) []string {
|
||||
@@ -16,14 +15,6 @@ func getFileIDs(files []File) []string {
|
||||
return fileIDs
|
||||
}
|
||||
|
||||
func isStreamable(filePath string) bool {
|
||||
return strings.HasSuffix(filePath, ".mkv") ||
|
||||
strings.HasSuffix(filePath, ".mp4") ||
|
||||
strings.HasSuffix(filePath, ".avi") ||
|
||||
strings.HasSuffix(filePath, ".wmv") ||
|
||||
strings.HasSuffix(filePath, ".m4v")
|
||||
}
|
||||
|
||||
func ensureDir(dirName string) error {
|
||||
if _, err := os.Stat(dirName); os.IsNotExist(err) {
|
||||
err := os.Mkdir(dirName, 0755)
|
||||
|
||||
Reference in New Issue
Block a user