package main import ( "fmt" "path/filepath" "regexp" "slices" "strconv" "strings" ) type mediaElement struct { Directory string Name string Year int Episode string Title string Tags []string Extension string } func newMediaElementWithParent(p string) *mediaElement { name := filepath.Base(p) parentDir := filepath.Dir(p) ext := filepath.Ext(name) name = strings.TrimSuffix(name, ext) dir := filepath.Base(parentDir) fileElement := newMediaElement(name, ext, parentDir) //fmt.Println("file: ", fileElement) directoryElement := newMediaElement(dir, ext, parentDir) //fmt.Println("directory: ", directoryElement) if fileElement.Name == "" { fileElement.Name = directoryElement.Name } if fileElement.Episode == "" { if directoryElement.Episode != "" { fileElement.Name = directoryElement.Name } fileElement.Episode = directoryElement.Episode fileElement.Title = directoryElement.Title } // append to fileElement.Tags if not already present for _, tag := range directoryElement.Tags { if !slices.Contains(fileElement.Tags, tag) { fileElement.Tags = append(fileElement.Tags, tag) } } return fileElement } func newMediaElement(name, ext, parentDir string) *mediaElement { episodeMatch := regexp.MustCompile(`[.\- ]?(S\d\dE\d\d)[.\- ]?`) yearMatch := regexp.MustCompile(`[.\- ]?(\d{4})[.\- ]?`) name = strings.ReplaceAll(name, ".", " ") name = strings.ReplaceAll(name, "-", " ") name = strings.ReplaceAll(name, "_", " ") element := &mediaElement{ Directory: parentDir, Extension: ext, } title := "" // get first group of regex match from episodeMatch match := episodeMatch.FindStringSubmatch(name) if len(match) > 0 { element.Episode = match[1] indexOfEpisode := strings.Index(name, match[0]) name = strings.Replace(name, match[0], "", -1) title = name[indexOfEpisode:] name = name[:indexOfEpisode] } match = yearMatch.FindStringSubmatch(name) if len(match) > 0 { year, err := strconv.Atoi(match[1]) if err == nil { if year >= 1800 { element.Year = year } } indexOfYear := strings.Index(name, match[0]) name = strings.Replace(name, match[0], "", -1) title = name[indexOfYear:] name = name[:indexOfYear] } element.Name = strings.TrimSpace(name) words := strings.Split(title, " ") titleWords := []string{} for i := len(words) - 1; i >= 0; i-- { word := words[i] upperWord := strings.ToUpper(word) switch upperWord { case "SYNCED": case "BD": case "DL": case "TVS": case "TVR": case "AC3": case "5": case "1": case "WEB": // ignore case "EN": fallthrough case "DE": fallthrough case "FORCED": fallthrough case "3D": fallthrough case "UNCUT": element.Tags = append(element.Tags, upperWord) case "GERMAN": element.Tags = append(element.Tags, "DE") case "1080P": element.Tags = append(element.Tags, "1080p") case "X264": element.Tags = append(element.Tags, "x264") case "H264": element.Tags = append(element.Tags, "x264") case "X265": element.Tags = append(element.Tags, "x265") case "H265": element.Tags = append(element.Tags, "x265") default: titleWords = append(titleWords, word) } } title = "" first := true for i := len(titleWords) - 1; i >= 0; i-- { if !first { title += " " } title += titleWords[i] first = false } if element.Episode != "" { element.Title = strings.TrimSpace(title) } return element } func (element *mediaElement) String() string { result := "" result += fmt.Sprintf("Directory: %s\n", element.Directory) result += fmt.Sprintf("Name: %s\n", element.Name) result += fmt.Sprintf("Episode: %s\n", element.Episode) result += fmt.Sprintf("Title: %s\n", element.Title) result += fmt.Sprintf("Extension: %s\n", element.Extension) result += fmt.Sprintf("Year: %d\n", element.Year) result += "Tags:" for _, tag := range element.Tags { result += " " + tag } return result } func (element *mediaElement) Path() string { result := element.Name if element.Episode != "" { result += " - " + element.Episode } if element.Title != "" { if result != "" { result += " - " } result += element.Title } if element.Year != 0 { result += " (" + strconv.Itoa(element.Year) + ")" } for i := len(element.Tags) - 1; i >= 0; i-- { result += " " + element.Tags[i] } result += element.Extension return filepath.Join(element.Directory, result) }