package release import ( "path" "strconv" "strings" ) // File is one file inside a torrent. type File struct { Index int Path string Size int64 } // Contents is what a torrent's file list holds. type Contents struct { Audio int Video int // Format is the format most of the audio files are in, "" when none. Format string } var videoExt = map[string]bool{ "mkv": true, "mp4": true, "avi": true, "m2ts": true, "vob": true, "mov": true, "webm": true, "wmv": true, "m4v": true, "ts": true, } // Inspect counts a file list's audio and video files. func Inspect(files []File) Contents { var c Contents formats := map[string]int{} for _, f := range files { ext := strings.TrimPrefix(strings.ToLower(path.Ext(f.Path)), ".") if fm := formatOf(ext); fm != "" { c.Audio++ formats[fm]++ } else if videoExt[ext] { c.Video++ } } best := 0 for fm, n := range formats { if n > best || (n == best && formatRank[fm] > formatRank[c.Format]) { c.Format, best = fm, n } } return c } // JudgeFiles says what a torrent's files say about whether it is the album: // a veto (code and sentence), or a doubt for a person, or nothing. func JudgeFiles(w Want, files []File) (veto, reason, doubt string) { if len(files) == 0 { return "", "", "" } c := Inspect(files) switch { case c.Audio == 0 && c.Video > 0: return VetoVideo, "It holds video files and no audio.", "" case c.Audio == 0: return VetoNoAudio, "It holds no audio files Minstrel can read.", "" case w.MinTracks > 0 && c.Audio < w.MinTracks: return VetoIncomplete, "It holds " + tracks(c.Audio) + "; the shortest edition has " + tracks(w.MinTracks) + ".", "" case w.MaxTracks > 0 && c.Audio > 2*w.MaxTracks+4: return "", "", "It holds " + tracks(c.Audio) + ", more than any edition of the album has: probably more than one album." } return "", "", "" } func tracks(n int) string { if n == 1 { return "1 track" } return strconv.Itoa(n) + " tracks" }