added anilist API

This commit is contained in:
milarin 2023-01-13 11:10:07 +01:00
parent 1d81e01d6c
commit e0018688e4
7 changed files with 163 additions and 7 deletions

39
access_token.go Normal file
View File

@ -0,0 +1,39 @@
package logic
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
}

64
anilist.go Normal file
View File

@ -0,0 +1,64 @@
package logic
import (
"context"
"git.milar.in/milarin/anilist"
"git.milar.in/milarin/channel"
"git.milar.in/nyaanime/model"
)
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]model.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] = model.Pair[*anilist.Media, error]{First: anime, Second: 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
}

View File

@ -4,11 +4,19 @@ import (
"html/template"
"math"
"git.milar.in/milarin/anilist"
"git.milar.in/milarin/envvars/v2"
"git.milar.in/nyaanime/model"
)
var (
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", "")
AnimePath = envvars.String("ANIME_PATH", "")
AnimeEpFilepathPattern = envvars.Object(
@ -41,6 +49,11 @@ var (
PreferredSubtitles = ParsePreferredStringProps(envvars.StringSlice("PREFERRED_SUBTITLES", "|", []string{}))
PreferredResolutions = ParsePreferredProps(envvars.StringSlice("PREFERRED_RESOLUTIONS", "|", []string{}), model.ParseResolution)
AnimeStatuses = envvars.ObjectSlice("ANIME_STATUSES", ",", []anilist.MediaListStatus{
anilist.MediaListStatusCurrent,
anilist.MediaListStatusPlanning,
}, ParseMediaListStatus)
/*
TODO

View File

@ -3,5 +3,11 @@ package logic
import "git.milar.in/milarin/adverr"
var (
ErrInvalidGlobSyntax = adverr.NewErrTmpl("ErrInvalidGlobSyntax", "invalid filepath.Glob syntax: '%s'")
ErrInvalidGlobSyntax = adverr.NewErrTmpl("ErrInvalidGlobSyntax", "invalid filepath.Glob syntax: '%s'")
ErrAnilistTokenNotObtainable = adverr.NewErrTmpl("ErrAnilistTokenNotObtainable", "neither ANILIST_TOKEN nor STORAGE_PATH provided")
ErrAnimeListNotObtainable = adverr.NewErrTmpl("ErrAnimeListNotObtainable", "anime list from anilist.co not obtainable (reason: %s)")
ErrAnimeNotFound = adverr.NewErrTmpl("ErrAnimeNotFound", "could not find anime with name '%s'")
ErrInvalidStorageParams = adverr.NewErrTmpl("ErrInvalidStorageParams", "STORAGE_USER or STORAGE_PASS not provided")
ErrStorageRequestFailed = adverr.NewErrTmpl("ErrStorageRequestFailed", "request to file storage could not be made")
ErrInvalidAnimeStatus = adverr.NewErrTmpl("ErrInvalidAnimeStatus", "invalid status '%s' in ANIME_STATUS (allowed: %s)")
)

5
go.mod
View File

@ -4,11 +4,12 @@ go 1.19
require (
git.milar.in/milarin/adverr v0.2.1
git.milar.in/milarin/anilist v1.5.0
git.milar.in/milarin/anilist v1.5.1
git.milar.in/milarin/channel v0.0.14
git.milar.in/milarin/envvars/v2 v2.0.0
git.milar.in/milarin/gmath v0.0.3
git.milar.in/milarin/slices v0.0.6
git.milar.in/nyaanime/model v0.0.0-20221008104642-466e1111ddea
git.milar.in/nyaanime/model v0.0.0-20230113095840-5eb2822653c3
git.milar.in/nyaanime/parsers v0.0.0-20221207192513-e7bce7c418d8
)

10
go.sum
View File

@ -1,15 +1,17 @@
git.milar.in/milarin/adverr v0.2.1 h1:eyXFGC+Ui/kcNt2+NqP3HiAplwxzqeNr9DfitsUb3c4=
git.milar.in/milarin/adverr v0.2.1/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/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.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/nyaanime/model v0.0.0-20221008104642-466e1111ddea h1:iBwxI3vZ+Hix/5HHB3k9f9/R0nkwR0EvVJ3o5RJEKP4=
git.milar.in/nyaanime/model v0.0.0-20221008104642-466e1111ddea/go.mod h1:kPWLDvFrhc1Uf77gxsBOxNeJ5JTVF2HhVs1IdVcw0tg=
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=
gopkg.in/vansante/go-ffprobe.v2 v2.1.1 h1:DIh5fMn+tlBvG7pXyUZdemVmLdERnf2xX6XOFF+0BBU=

31
utils.go Normal file
View File

@ -0,0 +1,31 @@
package logic
import (
"strings"
"git.milar.in/milarin/anilist"
"git.milar.in/milarin/slices"
)
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
}