From 4d4bab1134a84d16a64e9db09e1bdcf835405ecb Mon Sep 17 00:00:00 2001 From: milarin Date: Fri, 13 Jan 2023 13:38:51 +0100 Subject: [PATCH] moved code used by organizer into logic repo --- access_token.go | 39 --------------- anilist.go | 68 -------------------------- check_torrents.go | 12 +++-- envvars.go | 54 --------------------- file_filter.go | 25 ---------- file_priority.go | 17 ------- file_properties.go | 113 ++++++++++++++++++++------------------------ go.mod | 17 +++---- go.sum | 34 ++++++------- local_file_check.go | 51 ++------------------ main.go | 14 +++--- preferred_props.go | 53 --------------------- torrent_filter.go | 15 +++--- torrent_parse.go | 3 +- torrent_priority.go | 3 +- torrent_sort.go | 25 ---------- utils.go | 31 ++---------- 17 files changed, 113 insertions(+), 461 deletions(-) delete mode 100644 access_token.go delete mode 100644 anilist.go delete mode 100644 file_filter.go delete mode 100644 file_priority.go delete mode 100644 preferred_props.go diff --git a/access_token.go b/access_token.go deleted file mode 100644 index c41bb2c..0000000 --- a/access_token.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "io" - "net/http" - "strings" -) - -func GetAnilistAccessToken() (string, error) { - if strings.HasPrefix(AnilistAccessToken, "ey") { - return AnilistAccessToken, nil - } - - if StoragePath == "" { - return "", ErrAnilistTokenNotObtainable.New() - } else if StorageUser == "" || StoragePass == "" { - return "", ErrInvalidStorageParams.New() - } - - req, err := http.NewRequest("GET", StoragePath, nil) - if err != nil { - return "", ErrStorageRequestFailed.Wrap(err) - } - - req.SetBasicAuth(StorageUser, StoragePass) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", ErrStorageRequestFailed.Wrap(err) - } - defer resp.Body.Close() - - data, err := io.ReadAll(resp.Body) - if err != nil { - return "", ErrStorageRequestFailed.Wrap(err) - } - - return strings.TrimSpace(string(data)), nil -} diff --git a/anilist.go b/anilist.go deleted file mode 100644 index 9fab1e1..0000000 --- a/anilist.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "context" - - "git.milar.in/milarin/anilist" - "git.milar.in/milarin/channel" -) - -type Pair[A, B any] struct { - First A - Second B -} - -func GetAnimeListByAnimeID() (map[anilist.MediaID]*anilist.MediaList, error) { - watchingAnimesChannel, err := GetCurrentlyWatchingAnimes() - if err != nil { - return nil, err - } - - toMapFunc := func(entry *anilist.MediaList) (anilist.MediaID, *anilist.MediaList) { return entry.MediaID, entry } - return channel.ToMap(watchingAnimesChannel, toMapFunc), nil -} - -func GetCurrentlyWatchingAnimes() (<-chan *anilist.MediaList, error) { - token, err := GetAnilistAccessToken() - if err != nil { - return nil, ErrAnimeListNotObtainable.Wrap(err, "access token acquisition failed") - } - - media := channel.Map(channel.Of(AnimeStatuses...), func(status anilist.MediaListStatus) <-chan *anilist.MediaList { - return anilist.NewApi(token).GetMediaList(context.Background(), anilist.MediaListQuery{ - UserName: AnilistUsername, - Type: anilist.MediaTypeAnime, - Status: status, - }, nil).Chan - }) - - return channel.FlatChan(media), nil -} - -var ( - animeByTitleCache = map[string]Pair[*anilist.Media, error]{} -) - -func SearchAnimeByTitle(title string) (anime *anilist.Media, err error) { - // caching - if cacheEntry, ok := animeByTitleCache[title]; ok { - return cacheEntry.First, cacheEntry.Second - } - defer func() { animeByTitleCache[title] = Pair[*anilist.Media, error]{anime, err} }() - - token, err := GetAnilistAccessToken() - if err != nil { - return nil, err - } - - anime = anilist.NewApi(token).GetMedia(context.Background(), anilist.MediaQuery{ - Search: title, - Type: anilist.MediaTypeAnime, - }, nil).First() - - if anime == nil { - return nil, ErrAnimeNotFound.New(title) - } - - return anime, nil -} diff --git a/check_torrents.go b/check_torrents.go index 8fcdb4d..9c99fa8 100644 --- a/check_torrents.go +++ b/check_torrents.go @@ -2,14 +2,16 @@ package main import ( "fmt" + "log" "time" "git.milar.in/milarin/adverr" + "git.milar.in/nyaanime/logic" "git.milar.in/nyaanime/model" ) -func checkTorrents() { - fmt.Println("checking torrents") +func CheckTorrents() { + log.Println("checking torrents") start := time.Now() torrents, err := GetTorrents() @@ -18,7 +20,7 @@ func checkTorrents() { return } - animeList, err := GetAnimeListByAnimeID() + animeList, err := logic.GetAnimeListByAnimeID() if err != nil { fmt.Println(adverr.Wrap("retrieving anime list failed", err)) return @@ -48,7 +50,7 @@ func checkTorrents() { continue } - props, inCollection := GetAnimeEpProps(animeEp) + props, inCollection := logic.GetAnimeEpProps(animeEp) inCollectionEpisodes[animeEp] = inCollection // debug output if inCollection { @@ -79,5 +81,5 @@ func checkTorrents() { downloadedTorrents, ) - fmt.Printf("check took %s. sleeping for %s\n", duration.Truncate(time.Millisecond), (PollRate - duration).Truncate(time.Millisecond)) + log.Printf("check took %s. sleeping for %s\n", duration.Truncate(time.Millisecond), (PollRate - duration).Truncate(time.Millisecond)) } diff --git a/envvars.go b/envvars.go index 59c5a40..dccc192 100644 --- a/envvars.go +++ b/envvars.go @@ -2,32 +2,15 @@ package main import ( "html/template" - "math" "time" - "git.milar.in/milarin/anilist" "git.milar.in/milarin/envvars/v2" - "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_USERNAME", "") - StoragePass = envvars.String("STORAGE_PASSWORD", "") - 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, - ) DebugAnimeEpisodePattern = envvars.Object( "DEBUG_ANIME_LANGUAGE_PATTERN", @@ -35,42 +18,5 @@ var ( template.New("anime-episode-pattern").Parse, ) - AnimeStatuses = envvars.ObjectSlice("ANIME_STATUSES", ",", []anilist.MediaListStatus{ - anilist.MediaListStatusCurrent, - anilist.MediaListStatusPlanning, - }, ParseMediaListStatus) - DownloadAll = envvars.Bool("DOWNLOAD_ALL_ANIMES", false) - - // 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", "|", []string{}) - EssentialSubtitles = envvars.StringSlice("ESSENTIAL_SUBTITLES", "|", []string{}) - - 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", "|", []string{})) - PreferredSubtitles = ParsePreferredStringProps(envvars.StringSlice("PREFERRED_SUBTITLES", "|", []string{})) - PreferredResolutions = ParsePreferredProps(envvars.StringSlice("PREFERRED_RESOLUTIONS", "|", []string{}), model.ParseResolution) - - /* - TODO - - PreferMoreLanguages = envvars.Bool("PREFERER_MORE_LANGUAGES", false) - PreferMoreSubtitles = envvars.Bool("PREFERER_MORE_SUBTITLES", false) - */ ) diff --git a/file_filter.go b/file_filter.go deleted file mode 100644 index c31a2ee..0000000 --- a/file_filter.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "git.milar.in/milarin/slices" -) - -func HasFileEssentialProperties(props *FileProperties) bool { - if props.Resolution < MinResolution || props.Resolution > MaxResolution { - return false - } - - for _, essentialLanguage := range EssentialLanguages { - if !slices.Contains(props.Languages, essentialLanguage) { - return false - } - } - - for _, essentialSubtitle := range EssentialSubtitles { - if !slices.Contains(props.Subtitles, essentialSubtitle) { - return false - } - } - - return true -} diff --git a/file_priority.go b/file_priority.go deleted file mode 100644 index 48f14d7..0000000 --- a/file_priority.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -type FilePriority struct { - Properties *FileProperties - Priority int - PreferredProperties map[string]int -} - -func NewFilePriority(props *FileProperties) *FilePriority { - priority, preferredProperties := DeterminePriority(props) - - return &FilePriority{ - Properties: props, - Priority: priority, - PreferredProperties: preferredProperties, - } -} diff --git a/file_properties.go b/file_properties.go index cf2e766..5fcac23 100644 --- a/file_properties.go +++ b/file_properties.go @@ -1,74 +1,65 @@ package main -import ( - "context" - "os" +// type FileProperties struct { +// Filepath string +// Languages []string +// Subtitles []string +// Resolution model.Resolution +// } - "git.milar.in/nyaanime/model" - "git.milar.in/nyaanime/parsers" - ffprobe "gopkg.in/vansante/go-ffprobe.v2" -) +// var _ model.PropertyHolder = &FileProperties{} -type FileProperties struct { - Filepath string - Languages []string - Subtitles []string - Resolution model.Resolution -} +// // TODO cache +// func AnalyzeFile(path string) (*FileProperties, error) { +// props := &FileProperties{Filepath: path} -var _ model.PropertyHolder = &FileProperties{} +// file, err := os.Open(path) +// if err != nil { +// return nil, err +// } +// defer file.Close() -// TODO cache -func AnalyzeFile(path string) (*FileProperties, error) { - props := &FileProperties{Filepath: path} +// data, err := ffprobe.ProbeReader(context.Background(), file) +// if err != nil { +// return nil, err +// } - file, err := os.Open(path) - if err != nil { - return nil, err - } - defer file.Close() +// defaultVideoLang := "" +// for _, s := range data.StreamType(ffprobe.StreamVideo) { +// if s.Disposition.Default > 0 { +// props.Resolution = model.Resolution(s.Height) +// defaultVideoLang = parsers.ParseLanguage(s.Tags.Language) +// break +// } +// } - data, err := ffprobe.ProbeReader(context.Background(), file) - if err != nil { - return nil, err - } +// for _, s := range data.StreamType(ffprobe.StreamAudio) { +// if s.Tags.Language != "" { +// props.Languages = append(props.Languages, parsers.ParseLanguage(s.Tags.Language)) +// } else if s.Disposition.Default > 0 { +// props.Languages = append(props.Languages, defaultVideoLang) +// } +// } - defaultVideoLang := "" - for _, s := range data.StreamType(ffprobe.StreamVideo) { - if s.Disposition.Default > 0 { - props.Resolution = model.Resolution(s.Height) - defaultVideoLang = parsers.ParseLanguage(s.Tags.Language) - break - } - } +// for _, s := range data.StreamType(ffprobe.StreamSubtitle) { +// if s.Tags.Language != "" { +// props.Subtitles = append(props.Subtitles, parsers.ParseLanguage(s.Tags.Language)) +// } else if s.Disposition.Default > 0 { +// props.Subtitles = append(props.Subtitles, defaultVideoLang) +// } +// } - for _, s := range data.StreamType(ffprobe.StreamAudio) { - if s.Tags.Language != "" { - props.Languages = append(props.Languages, parsers.ParseLanguage(s.Tags.Language)) - } else if s.Disposition.Default > 0 { - props.Languages = append(props.Languages, defaultVideoLang) - } - } +// return props, nil +// } - for _, s := range data.StreamType(ffprobe.StreamSubtitle) { - if s.Tags.Language != "" { - props.Subtitles = append(props.Subtitles, parsers.ParseLanguage(s.Tags.Language)) - } else if s.Disposition.Default > 0 { - props.Subtitles = append(props.Subtitles, defaultVideoLang) - } - } +// func (fp *FileProperties) GetLanguages() []string { +// return fp.Languages +// } - return props, nil -} +// func (fp *FileProperties) GetSubtitles() []string { +// return fp.Subtitles +// } -func (fp *FileProperties) GetLanguages() []string { - return fp.Languages -} - -func (fp *FileProperties) GetSubtitles() []string { - return fp.Subtitles -} - -func (fp *FileProperties) GetResolution() model.Resolution { - return fp.Resolution -} +// func (fp *FileProperties) GetResolution() model.Resolution { +// return fp.Resolution +// } diff --git a/go.mod b/go.mod index 0e92281..b8d4dbb 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,21 @@ module git.milar.in/nyaanime/downloader go 1.18 require ( - git.milar.in/milarin/adverr v1.0.0 - git.milar.in/milarin/anilist v1.5.0 - git.milar.in/milarin/channel v0.0.9 + git.milar.in/milarin/adverr v1.1.0 + git.milar.in/milarin/anilist v1.5.1 git.milar.in/milarin/envvars/v2 v2.0.0 - git.milar.in/milarin/gmath v0.0.2 - git.milar.in/milarin/slices v0.0.3 + git.milar.in/milarin/slices v0.0.6 git.milar.in/milarin/tprint v0.0.7 - git.milar.in/nyaanime/model v0.0.0-20220825203652-2504dcc85f73 - git.milar.in/nyaanime/parsers v0.0.0-20220825163541-c840c68b761d + git.milar.in/nyaanime/logic v0.0.0-20230113101007-e0018688e419 + git.milar.in/nyaanime/model v0.0.0-20230113095840-5eb2822653c3 + git.milar.in/nyaanime/parsers v0.0.0-20221207192513-e7bce7c418d8 github.com/PuerkitoBio/goquery v1.8.0 github.com/fatih/color v1.13.0 - gopkg.in/vansante/go-ffprobe.v2 v2.1.0 ) require ( + git.milar.in/milarin/channel v0.0.14 // indirect + git.milar.in/milarin/gmath v0.0.3 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect @@ -25,4 +25,5 @@ require ( github.com/rivo/uniseg v0.3.4 // indirect golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect + gopkg.in/vansante/go-ffprobe.v2 v2.1.1 // indirect ) diff --git a/go.sum b/go.sum index 19fd76f..d19857e 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,23 @@ -git.milar.in/milarin/adverr v1.0.0 h1:9povP074PjpoZlNuiKPa9w6fDA8a4RSI5hEDo5T9Tqo= -git.milar.in/milarin/adverr v1.0.0/go.mod h1:wwfglcey4R3vqjNL/d8mbnvFJGzETRXzAEolIHZY32w= -git.milar.in/milarin/anilist v1.5.0 h1:fSiAXY/topNk4ISEp2QtcG9HHKLJfMc8w05iqc+Paf0= -git.milar.in/milarin/anilist v1.5.0/go.mod h1:8PTHXFMA45JpfRFIpcdrKwDHue8fbT/wwV1BuHFn6c0= -git.milar.in/milarin/channel v0.0.9 h1:vYJnXOaIn/+mng1+8CyepQgDfRse2s4FSLNc7zv85To= -git.milar.in/milarin/channel v0.0.9/go.mod h1:We83LTI8S7u7II3pD+A2ChCDWJfCkcBUCUqii9HjTtM= +git.milar.in/milarin/adverr v1.1.0 h1:jD9WnOvs40lfMhvqQ7cllOaRJNBMWr1f07/s9jAadp0= +git.milar.in/milarin/adverr v1.1.0/go.mod h1:joU9sBb7ySyNv4SpTXB0Z4o1mjXsArBw4N27wjgzj9E= +git.milar.in/milarin/anilist v1.5.1 h1:gW08WaAvXxC5/+P1QCjyfa5YtaiY9XvF5x/8G4orT6I= +git.milar.in/milarin/anilist v1.5.1/go.mod h1:8PTHXFMA45JpfRFIpcdrKwDHue8fbT/wwV1BuHFn6c0= +git.milar.in/milarin/channel v0.0.14 h1:1jBaKNNOK/mmMMgC7yVW1Cgnbb7q9aKBXZ5WnWptDek= +git.milar.in/milarin/channel v0.0.14/go.mod h1:We83LTI8S7u7II3pD+A2ChCDWJfCkcBUCUqii9HjTtM= git.milar.in/milarin/envvars/v2 v2.0.0 h1:DWRQCWaHqzDD8NGpSgv5tYLuF9A/dVFPAtTvz3oiIqE= git.milar.in/milarin/envvars/v2 v2.0.0/go.mod h1:HkdEi+gG2lJSmVq547bTlQV4qQ0hO333bE8IrE0B9yY= -git.milar.in/milarin/gmath v0.0.2 h1:avz+75f8XqAYA1wEB6kis0R5xvRuepBKTqBuJBjh6Yw= -git.milar.in/milarin/gmath v0.0.2/go.mod h1:HDLftG5RLpiNGKiIWh+O2G1PYkNzyLDADO8Cd/1abiE= -git.milar.in/milarin/slices v0.0.3 h1:kzaLrE/G4rO2DQq3nVk2TYbuqOsiauLHClVUpgSZM8s= -git.milar.in/milarin/slices v0.0.3/go.mod h1:XRNfE99aNKeaPOY1phjOlpIQqeGCW1LOqqh8UHS+vAk= +git.milar.in/milarin/gmath v0.0.3 h1:ii6rKNItS55O/wtIFhD1cTN2BMwDZjTBmiOocKURvxM= +git.milar.in/milarin/gmath v0.0.3/go.mod h1:HDLftG5RLpiNGKiIWh+O2G1PYkNzyLDADO8Cd/1abiE= +git.milar.in/milarin/slices v0.0.6 h1:AQoSarZ58WHYol9c6woWJSe8wFpPC2RC4cvIlZpfg9s= +git.milar.in/milarin/slices v0.0.6/go.mod h1:NOr53AOeur/qscu/FBj3lsFR262PNYBccLYSTCAXRk4= git.milar.in/milarin/tprint v0.0.7 h1:dvm4l4BhXOie4vtnRMZii0WTLTz2wju8wyUPB/lNeVo= git.milar.in/milarin/tprint v0.0.7/go.mod h1:UwW/B+0cTCbN5hi0bQBE9rIRgLkq+x4V751rrS2KVoI= -git.milar.in/nyaanime/model v0.0.0-20220825203652-2504dcc85f73 h1:fnHpasTZiZyVrXH6Yt0pARibWUveO8pLO+3upK1tboc= -git.milar.in/nyaanime/model v0.0.0-20220825203652-2504dcc85f73/go.mod h1:DqRaTKOh6JRSTVLmoTQ6jrnDvGZvWrfKj3nimr6yuKs= -git.milar.in/nyaanime/parsers v0.0.0-20220825163541-c840c68b761d h1:LskYoxsMQ3UgPF/6P7p7qm5xYCoe7GrYH1MZnwMTdEI= -git.milar.in/nyaanime/parsers v0.0.0-20220825163541-c840c68b761d/go.mod h1:qm6fIFBFs90uz7IJ8RKgDir0K8Fa8isixGLgrtC6kgU= +git.milar.in/nyaanime/logic v0.0.0-20230113101007-e0018688e419 h1:Am9LlW/2UJuUvWsoA2c9FPBJpTZfSWjHCkWSHlAoX8M= +git.milar.in/nyaanime/logic v0.0.0-20230113101007-e0018688e419/go.mod h1:SkgdD87uNP60swIBtrDRZPBF5rLIgBLL6OetP1sETLY= +git.milar.in/nyaanime/model v0.0.0-20230113095840-5eb2822653c3 h1:mXcEA47FQQzeSDXE3UvhNfIt4fBfpDSq1/f0r+jbHpY= +git.milar.in/nyaanime/model v0.0.0-20230113095840-5eb2822653c3/go.mod h1:kPWLDvFrhc1Uf77gxsBOxNeJ5JTVF2HhVs1IdVcw0tg= +git.milar.in/nyaanime/parsers v0.0.0-20221207192513-e7bce7c418d8 h1:vb7jasvTdan0E8VY5snnRj1Xe+60NA7Lpn+GSYE6pW0= +git.milar.in/nyaanime/parsers v0.0.0-20221207192513-e7bce7c418d8/go.mod h1:GG4vtUIfxopZc/+Y8OAa//vWJw/m6aeoGN7fw6SLiEM= github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= @@ -48,5 +50,5 @@ golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/vansante/go-ffprobe.v2 v2.1.0 h1:Gh8oVkvOSZG/DgEMmBw8h4oLvJhSQHROEGp3TaVGq08= -gopkg.in/vansante/go-ffprobe.v2 v2.1.0/go.mod h1:qF0AlAjk7Nqzqf3y333Ly+KxN3cKF2JqA3JT5ZheUGE= +gopkg.in/vansante/go-ffprobe.v2 v2.1.1 h1:DIh5fMn+tlBvG7pXyUZdemVmLdERnf2xX6XOFF+0BBU= +gopkg.in/vansante/go-ffprobe.v2 v2.1.1/go.mod h1:qF0AlAjk7Nqzqf3y333Ly+KxN3cKF2JqA3JT5ZheUGE= diff --git a/local_file_check.go b/local_file_check.go index fdec8fd..1028768 100644 --- a/local_file_check.go +++ b/local_file_check.go @@ -4,9 +4,9 @@ import ( "errors" "os" "path/filepath" - "strings" "git.milar.in/milarin/anilist" + "git.milar.in/nyaanime/logic" "git.milar.in/nyaanime/model" ) @@ -16,22 +16,8 @@ type AnimePathPatternData struct { Ext string } -func GetAnimeEpFilepath(animeEp model.AnimeEpisode, ext string) string { - tmplData := AnimePathPatternData{ - Title: animeEp.Anime.Title, - Episode: animeEp.Episode, - Ext: ext, - } - - b := new(strings.Builder) - if err := AnimeEpFilepathPattern.Execute(b, tmplData); err != nil { - panic(err) - } - return filepath.Join(AnimePath, b.String()) -} - func AnimeEpExistsLocally(animeEp model.AnimeEpisode) bool { - animeEpPath := GetAnimeEpFilepath(animeEp, "*") + animeEpPath := logic.GetAnimeEpFilepath(animeEp, "*") files, err := filepath.Glob(animeEpPath) if err != nil { @@ -41,43 +27,14 @@ func AnimeEpExistsLocally(animeEp model.AnimeEpisode) bool { return len(files) > 0 } -func GetAnimeEpProps(animeEp model.AnimeEpisode) (*FilePriority, bool) { - animeEpPath := GetAnimeEpFilepath(animeEp, "*") - files, err := filepath.Glob(animeEpPath) - if err != nil { - panic(ErrInvalidGlobSyntax.Wrap(err, animeEpPath)) - } - - var mostPrio *FilePriority - - for _, file := range files { - props, err := AnalyzeFile(file) - if err != nil { - continue - } - - if !HasFileEssentialProperties(props) { - continue - } - - fp := NewFilePriority(props) - - if mostPrio == nil || fp.Priority > mostPrio.Priority { - mostPrio = fp - } - } - - return mostPrio, mostPrio != nil -} - func IsCurrentlyDownloading(animeEp model.AnimeEpisode) bool { - animeEpPath := GetAnimeEpFilepath(animeEp, "lock") + animeEpPath := logic.GetAnimeEpFilepath(animeEp, "lock") _, err := os.Stat(animeEpPath) return !errors.Is(err, os.ErrNotExist) } func SetCurrentlyDownloading(animeEp model.AnimeEpisode) error { - animeEpPath := GetAnimeEpFilepath(animeEp, "lock") + animeEpPath := logic.GetAnimeEpFilepath(animeEp, "lock") dir := filepath.Dir(animeEpPath) if err := os.MkdirAll(dir, 0755); err != nil { diff --git a/main.go b/main.go index 5bfd760..2d6e84d 100644 --- a/main.go +++ b/main.go @@ -3,25 +3,27 @@ package main import ( "fmt" "time" + + "git.milar.in/nyaanime/logic" ) func main() { fmt.Println("generated priority values:") - fmt.Print(Map2Table("language", PreferredLanguages)) - fmt.Print(Map2Table("subtitle", PreferredSubtitles)) - fmt.Print(Map2Table("resolution", PreferredResolutions)) + fmt.Print(Map2Table("language", logic.PreferredLanguages)) + fmt.Print(Map2Table("subtitle", logic.PreferredSubtitles)) + fmt.Print(Map2Table("resolution", logic.PreferredResolutions)) fmt.Println() // get access token once at startup to be sure that an access token is obtainable at all - if _, err := GetAnilistAccessToken(); err != nil { + if _, err := logic.GetAnilistAccessToken(); err != nil { panic(err) } ticker := time.NewTicker(PollRate) defer ticker.Stop() - checkTorrents() + CheckTorrents() for range ticker.C { - checkTorrents() + CheckTorrents() } } diff --git a/preferred_props.go b/preferred_props.go deleted file mode 100644 index 6b1f4c9..0000000 --- a/preferred_props.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "strings" - - "git.milar.in/milarin/gmath" - "git.milar.in/milarin/slices" -) - -// ParsePreferredProps parses properties and its corresponding priority. -// priorities are distributed exponentially in reverse order. -// -// That means the last entry will have priority 1, the second last 2, then 4, 8 and so on. -// -// Properties with name "_" will be ignored and function as a placeholder to increase the priority -// of the properties which comes before them. -// -// Properties separated by comma will have the same priorities. -// -// str usually is the return value of a call to strings.Split(str, "|") -// -// Examples: -// str = "a|b|c" -> c:1 b:2 a:4 -// str = "a|b|_|c" -> c:1 b:4 a:8 -// str = "a,b|c" -> c:1 b:4 a:4 -// str = "d|_|a,b|c" -> c:1 b:4 a:4 d:16 -// -// Additionally, properties can be converted to a generic type with the converter function -func ParsePreferredProps[T comparable](str []string, converter func(string) (T, error)) map[T]int { - props := map[T]int{} - - for i, subProps := range slices.Reverse(str) { - if subProps == "_" { - continue - } - - propPriority := gmath.Pow(2, i) - for _, subProp := range strings.Split(subProps, ",") { - subPropT, err := converter(subProp) - if err != nil { - continue - } - - props[subPropT] = propPriority - } - } - - return props -} - -func ParsePreferredStringProps(str []string) map[string]int { - return ParsePreferredProps(str, func(s string) (string, error) { return s, nil }) -} diff --git a/torrent_filter.go b/torrent_filter.go index 14ea96b..94a3e9b 100644 --- a/torrent_filter.go +++ b/torrent_filter.go @@ -3,6 +3,7 @@ package main import ( "git.milar.in/milarin/anilist" "git.milar.in/milarin/slices" + "git.milar.in/nyaanime/logic" "git.milar.in/nyaanime/model" ) @@ -33,33 +34,33 @@ func FilterEssentialTorrents(allTorrents map[model.AnimeEpisode][]*model.ParsedT } func HasEssentialProperties(torrent *model.ParsedTorrent) bool { - if torrent.Resolution < MinResolution || torrent.Resolution > MaxResolution { + if torrent.Resolution < logic.MinResolution || torrent.Resolution > logic.MaxResolution { return false } - if torrent.Torrent.Seeders < MinSeeders || torrent.Torrent.Seeders > MaxSeeders { + if torrent.Torrent.Seeders < logic.MinSeeders || torrent.Torrent.Seeders > logic.MaxSeeders { return false } - if torrent.Torrent.Leechers < MinLeechers || torrent.Torrent.Leechers > MaxLeechers { + if torrent.Torrent.Leechers < logic.MinLeechers || torrent.Torrent.Leechers > logic.MaxLeechers { return false } - if torrent.Torrent.Downloads < MinDownloads || torrent.Torrent.Downloads > MaxDownloads { + if torrent.Torrent.Downloads < logic.MinDownloads || torrent.Torrent.Downloads > logic.MaxDownloads { return false } - if TrustedOnly && !torrent.Torrent.Trusted { + if logic.TrustedOnly && !torrent.Torrent.Trusted { return false } - for _, essentialLanguage := range EssentialLanguages { + for _, essentialLanguage := range logic.EssentialLanguages { if !slices.Contains(torrent.Languages, essentialLanguage) { return false } } - for _, essentialSubtitle := range EssentialSubtitles { + for _, essentialSubtitle := range logic.EssentialSubtitles { if !slices.Contains(torrent.Subtitles, essentialSubtitle) { return false } diff --git a/torrent_parse.go b/torrent_parse.go index b29533b..e2b384b 100644 --- a/torrent_parse.go +++ b/torrent_parse.go @@ -5,6 +5,7 @@ import ( "fmt" "git.milar.in/milarin/adverr" + "git.milar.in/nyaanime/logic" "git.milar.in/nyaanime/model" "git.milar.in/nyaanime/parsers" ) @@ -13,7 +14,7 @@ func ParseTorrent(torrent *model.Torrent) (*model.ParsedTorrent, error) { for _, parser := range parsers.Parsers { parsedTorrent, ok := parser.TorrentParser(&parser, torrent) if ok { - anime, err := SearchAnimeByTitle(parsedTorrent.OriginalAnimeTitle) + anime, err := logic.SearchAnimeByTitle(parsedTorrent.OriginalAnimeTitle) if err != nil { return parsedTorrent, ErrTorrentParseFailed.Wrap(err, torrent.ID, parser.String()) } diff --git a/torrent_priority.go b/torrent_priority.go index cd87a79..9072b31 100644 --- a/torrent_priority.go +++ b/torrent_priority.go @@ -3,6 +3,7 @@ package main import ( "fmt" + "git.milar.in/nyaanime/logic" "git.milar.in/nyaanime/model" ) @@ -13,7 +14,7 @@ type TorrentPriority struct { } func NewTorrentPriority(torrent *model.ParsedTorrent) *TorrentPriority { - priority, preferredProperties := DeterminePriority(torrent) + priority, preferredProperties := logic.DeterminePriority(torrent) return &TorrentPriority{ ParsedTorrent: torrent, diff --git a/torrent_sort.go b/torrent_sort.go index 51e7218..9ca9879 100644 --- a/torrent_sort.go +++ b/torrent_sort.go @@ -26,28 +26,3 @@ func GetTorrentsWithMaxPrioByAnimeEp(torrents map[model.AnimeEpisode][]*model.Pa return torrentsWithPrio } - -func DeterminePriority(props model.PropertyHolder) (priority int, preferredProperties map[string]int) { - preferredProperties = map[string]int{} - - for _, lang := range props.GetLanguages() { - if langPriority, ok := PreferredLanguages[lang]; ok { - priority += langPriority - preferredProperties["lang/"+lang] = langPriority - } - } - - for _, sub := range props.GetSubtitles() { - if subPriority, ok := PreferredSubtitles[sub]; ok { - priority += subPriority - preferredProperties["sub/"+sub] = subPriority - } - } - - if prefRes, ok := PreferredResolutions[props.GetResolution()]; ok { - priority += prefRes - preferredProperties["res/"+props.GetResolution().String()] = prefRes - } - - return -} diff --git a/utils.go b/utils.go index 4ad4e42..b81f97f 100644 --- a/utils.go +++ b/utils.go @@ -2,42 +2,17 @@ package main import ( "sort" - "strings" - "git.milar.in/milarin/anilist" - "git.milar.in/milarin/slices" "git.milar.in/milarin/tprint" + "git.milar.in/nyaanime/model" ) -var AllMediaListStatuses = []anilist.MediaListStatus{ - anilist.MediaListStatusCurrent, - anilist.MediaListStatusPlanning, - anilist.MediaListStatusCompleted, - anilist.MediaListStatusDropped, - anilist.MediaListStatusPaused, - anilist.MediaListStatusRepeating, -} - -func ParseMediaListStatus(str string) (anilist.MediaListStatus, error) { - s := anilist.MediaListStatus(strings.ToUpper(str)) - - allStatusesStr := slices.Map(AllMediaListStatuses, func(status anilist.MediaListStatus) string { - return string(status) - }) - - if !slices.Contains(AllMediaListStatuses, s) { - return s, ErrInvalidAnimeStatus.New(s, strings.Join(allStatusesStr, ",")) - } - - return s, nil -} - func Map2Table[K comparable](title string, m map[K]int) string { table := tprint.NewTable(title, "priority") - entries := make([]Pair[K, int], 0, len(m)) + entries := make([]model.Pair[K, int], 0, len(m)) for name, priority := range m { - entries = append(entries, Pair[K, int]{name, priority}) + entries = append(entries, model.Pair[K, int]{First: name, Second: priority}) } sort.Slice(entries, func(i, j int) bool { return entries[i].Second > entries[j].Second })