package main import ( "fmt" "html/template" "math" "time" "git.milar.in/milarin/adverr" "git.milar.in/milarin/anilist" "git.milar.in/milarin/envvars" "git.milar.in/nyaanime/model" ) var ( PollRate = envvars.Object("POLL_RATE", 30*time.Minute, time.ParseDuration) AnilistUsername = envvars.String("ANILIST_USERNAME", "username") AnilistAccessToken = envvars.String("ANILIST_TOKEN", "") StoragePath = envvars.String("STORAGE_PATH", "") StorageUser = envvars.String("STORAGE_USER", "") StoragePass = envvars.String("STORAGE_PASS", "") TorrentPath = envvars.String("TORRENT_PATH", "") AnimePath = envvars.String("ANIME_PATH", "") AnimeEpFilepathPattern = envvars.Object( "EPISODE_FILEPATH_PATTERN", template.Must(template.New("anime-episode-filepath-pattern").Parse(`{{.Title.UserPreferred}}/{{.Title.UserPreferred}} Episode {{.Episode}}.{{.Ext}}`)), template.New("anime-episode-filepath-pattern").Parse, ) AnimeStatus = envvars.ObjectSlice("ANIME_STATUS", ",", ParseMediaListStatus) // essential torrent properties MaxResolution = envvars.Object("MAX_RESOLUTION", model.Resolution4K, model.ParseResolution) MinResolution = envvars.Object("MIN_RESOLUTION", model.ResolutionHD, model.ParseResolution) EssentialLanguages = envvars.StringSlice("ESSENTIAL_LANGUAGES", "|") EssentialSubtitles = envvars.StringSlice("ESSENTIAL_SUBTITLES", "|") MaxSeeders = envvars.Int("MAX_SEEDERS", math.MaxInt) MinSeeders = envvars.Int("MIN_SEEDERS", 0) MaxLeechers = envvars.Int("MAX_LEECHERS", math.MaxInt) MinLeechers = envvars.Int("MIN_LEECHERS", 0) MaxDownloads = envvars.Int("MAX_DOWNLOADS", math.MaxInt) MinDownloads = envvars.Int("MIN_DOWNLOADS", 0) TrustedOnly = envvars.Bool("TRUSTED_ONLY", false) // preferred torrent properties PreferredLanguages = ParsePreferredStringProps(envvars.StringSlice("PREFERRED_LANGUAGES", "|")) PreferredSubtitles = ParsePreferredStringProps(envvars.StringSlice("PREFERRED_SUBTITLES", "|")) PreferredResolutions = ParsePreferredProps(envvars.StringSlice("PREFERRED_RESOLUTIONS", "|"), model.ParseResolution) /* TODO PreferMoreLanguages = envvars.Bool("PREFERER_MORE_LANGUAGES", false) PreferMoreSubtitles = envvars.Bool("PREFERER_MORE_SUBTITLES", false) */ ) func main() { fmt.Println("language priorites:", Map2Str(PreferredLanguages)) fmt.Println("subtitle priorites:", Map2Str(PreferredSubtitles)) fmt.Println("resolution priorites:", Map2Str(PreferredResolutions)) // TODO ugly code (see issue nyaanime/downloader#1) if len(AnimeStatus) == 0 { AnimeStatus = []anilist.MediaListStatus{ anilist.MediaListStatusCurrent, anilist.MediaListStatusPlanning, } } // get access token once at startup to be sure that an access token is obtainable at all if _, err := GetAnilistAccessToken(); err != nil { panic(err) } ticker := time.NewTicker(PollRate) defer ticker.Stop() checkTorrents() for range ticker.C { checkTorrents() } } func checkTorrents() { fmt.Println("checking torrents") start := time.Now() torrents, err := GetLatestNyaaContent() if err != nil { fmt.Println(adverr.Wrap("retrieving torrents failed", err)) return } animes, err := GetAnimesToDownloadByAnimeID() if err != nil { fmt.Println(adverr.Wrap("retrieving anime list failed", err)) return } parsedTorrents := ParseTorrentsByAnimeEpSortedByProperties(torrents) for animeEp, torrentPriorities := range parsedTorrents { _, animeOnList := animes[animeEp.Anime.ID] props, found, err := GetLocalAnimeEpProperties(animeEp) episodeInCollection := err == nil && found fmt.Print(FormatFilePriority(animeEp, props, animeOnList, episodeInCollection, len(torrentPriorities))) if !animeOnList { continue } for _, torrentPriority := range torrentPriorities { torrent := torrentPriority.ParsedTorrent if IsAnimeEpDownloading(animeEp) { fmt.Printf("%s | CURRENTLY DOWNLOADING\n", FormatTorrentPriority(torrentPriority)) continue } if episodeInCollection { if props.Priority > torrentPriority.Priority { fmt.Printf("%s | LOWER PRIORITY\n", FormatTorrentPriority(torrentPriority)) } else { fmt.Printf("%s | HIGHER PRIORITY | STARTING DOWNLOAD\n", FormatTorrentPriority(torrentPriority)) if err := DownloadTorrent(animeEp, torrent); err != nil { panic(err) } } } else { fmt.Printf("%s | NOT IN COLLECTION | STARTING DOWNLOAD\n", FormatTorrentPriority(torrentPriority)) if err := DownloadTorrent(animeEp, torrent); err != nil { panic(err) } } } } duration := time.Since(start) fmt.Printf("\ncheck took %s. sleeping for %s\n", duration.Truncate(time.Millisecond), (PollRate - duration).Truncate(time.Millisecond)) } func ParseTorrentsByAnimeEpSortedByProperties(torrents []model.Torrent) map[model.AnimeEpisode][]*TorrentPriority { // parse torrents parsedTorrentsByAnimeEp := ParseTorrentsByAnimeEp(torrents) // filter out torrents without essential properties filteredTorrentsByAnimeEp := FilterEssentialTorrents(parsedTorrentsByAnimeEp) // sort torrents by preferred properties sortedTorrentsByAnimeEp := SortTorrentsByPreferredProperties(filteredTorrentsByAnimeEp) return sortedTorrentsByAnimeEp }