downloader/main.go
2022-08-22 00:13:50 +02:00

154 lines
4.7 KiB
Go

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", "")
DownloadPath = envvars.String("DOWNLOAD_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))
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 {
fmt.Printf("\nanime: %s | episode: %d | torrents found: %d\n", animeEp.Anime.Title.Romaji, animeEp.Episode, len(torrentPriorities))
for _, torrentPriority := range torrentPriorities {
/*animeListEntry*/ _, ok := animes[torrentPriority.ParsedTorrent.Anime.ID]
if !ok {
fmt.Printf("%s | NOT ON LIST\n", FormatTorrentPriority(torrentPriority))
continue
}
if AnimeEpExistsLocally(animeEp) {
// TODO check if current torrent has higher priority than downloaded one (might not have any priority)
continue
}
// TODO is currently downloading? (database query)
fmt.Println(FormatTorrentPriority(torrentPriority))
// TODO download anime episode with highest priority (first one in slice)
}
}
// TODO store preferred properties of downloaded torrents in db
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
}