node build fixed
This commit is contained in:
212
seanime-2.9.10/internal/api/metadata/provider.go
Normal file
212
seanime-2.9.10/internal/api/metadata/provider.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"seanime/internal/api/anilist"
|
||||
"seanime/internal/api/animap"
|
||||
"seanime/internal/hook"
|
||||
"seanime/internal/util/filecache"
|
||||
"seanime/internal/util/result"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/samber/mo"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
type (
|
||||
ProviderImpl struct {
|
||||
logger *zerolog.Logger
|
||||
fileCacher *filecache.Cacher
|
||||
animeMetadataCache *result.BoundedCache[string, *AnimeMetadata]
|
||||
singleflight *singleflight.Group
|
||||
}
|
||||
|
||||
NewProviderImplOptions struct {
|
||||
Logger *zerolog.Logger
|
||||
FileCacher *filecache.Cacher
|
||||
}
|
||||
)
|
||||
|
||||
func GetAnimeMetadataCacheKey(platform Platform, mId int) string {
|
||||
return fmt.Sprintf("%s$%d", platform, mId)
|
||||
}
|
||||
|
||||
// NewProvider creates a new metadata provider.
|
||||
func NewProvider(options *NewProviderImplOptions) Provider {
|
||||
return &ProviderImpl{
|
||||
logger: options.Logger,
|
||||
fileCacher: options.FileCacher,
|
||||
animeMetadataCache: result.NewBoundedCache[string, *AnimeMetadata](100),
|
||||
singleflight: &singleflight.Group{},
|
||||
}
|
||||
}
|
||||
|
||||
// GetCache returns the anime metadata cache.
|
||||
func (p *ProviderImpl) GetCache() *result.BoundedCache[string, *AnimeMetadata] {
|
||||
return p.animeMetadataCache
|
||||
}
|
||||
|
||||
// GetAnimeMetadata fetches anime metadata from api.ani.zip.
|
||||
func (p *ProviderImpl) GetAnimeMetadata(platform Platform, mId int) (ret *AnimeMetadata, err error) {
|
||||
cacheKey := GetAnimeMetadataCacheKey(platform, mId)
|
||||
if cached, ok := p.animeMetadataCache.Get(cacheKey); ok {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
res, err, _ := p.singleflight.Do(cacheKey, func() (interface{}, error) {
|
||||
return p.fetchAnimeMetadata(platform, mId)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.(*AnimeMetadata), nil
|
||||
}
|
||||
|
||||
func (p *ProviderImpl) fetchAnimeMetadata(platform Platform, mId int) (*AnimeMetadata, error) {
|
||||
ret := &AnimeMetadata{
|
||||
Titles: make(map[string]string),
|
||||
Episodes: make(map[string]*EpisodeMetadata),
|
||||
EpisodeCount: 0,
|
||||
SpecialCount: 0,
|
||||
Mappings: &AnimeMappings{},
|
||||
}
|
||||
|
||||
// Invoke AnimeMetadataRequested hook
|
||||
reqEvent := &AnimeMetadataRequestedEvent{
|
||||
MediaId: mId,
|
||||
AnimeMetadata: ret,
|
||||
}
|
||||
err := hook.GlobalHookManager.OnAnimeMetadataRequested().Trigger(reqEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mId = reqEvent.MediaId
|
||||
|
||||
// Default prevented by hook, return the metadata
|
||||
if reqEvent.DefaultPrevented {
|
||||
// Override the metadata
|
||||
ret = reqEvent.AnimeMetadata
|
||||
|
||||
// Trigger the event
|
||||
event := &AnimeMetadataEvent{
|
||||
MediaId: mId,
|
||||
AnimeMetadata: ret,
|
||||
}
|
||||
err = hook.GlobalHookManager.OnAnimeMetadata().Trigger(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = event.AnimeMetadata
|
||||
mId = event.MediaId
|
||||
|
||||
if ret == nil {
|
||||
return nil, errors.New("no metadata was returned")
|
||||
}
|
||||
p.animeMetadataCache.SetT(GetAnimeMetadataCacheKey(platform, mId), ret, 1*time.Hour)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
m, err := animap.FetchAnimapMedia(string(platform), mId)
|
||||
if err != nil || m == nil {
|
||||
//return p.AnizipFallback(platform, mId)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret.Titles = m.Titles
|
||||
ret.EpisodeCount = 0
|
||||
ret.SpecialCount = 0
|
||||
ret.Mappings.AnimeplanetId = m.Mappings.AnimePlanetID
|
||||
ret.Mappings.KitsuId = m.Mappings.KitsuID
|
||||
ret.Mappings.MalId = m.Mappings.MalID
|
||||
ret.Mappings.Type = m.Mappings.Type
|
||||
ret.Mappings.AnilistId = m.Mappings.AnilistID
|
||||
ret.Mappings.AnisearchId = m.Mappings.AnisearchID
|
||||
ret.Mappings.AnidbId = m.Mappings.AnidbID
|
||||
ret.Mappings.NotifymoeId = m.Mappings.NotifyMoeID
|
||||
ret.Mappings.LivechartId = m.Mappings.LivechartID
|
||||
ret.Mappings.ThetvdbId = m.Mappings.TheTvdbID
|
||||
ret.Mappings.ImdbId = ""
|
||||
ret.Mappings.ThemoviedbId = m.Mappings.TheMovieDbID
|
||||
|
||||
for key, ep := range m.Episodes {
|
||||
firstChar := key[0]
|
||||
if firstChar == 'S' {
|
||||
ret.SpecialCount++
|
||||
} else {
|
||||
if firstChar >= '0' && firstChar <= '9' {
|
||||
ret.EpisodeCount++
|
||||
}
|
||||
}
|
||||
em := &EpisodeMetadata{
|
||||
AnidbId: ep.AnidbId,
|
||||
TvdbId: ep.TvdbId,
|
||||
Title: ep.AnidbTitle,
|
||||
Image: ep.Image,
|
||||
AirDate: ep.AirDate,
|
||||
Length: ep.Runtime,
|
||||
Summary: strings.ReplaceAll(ep.Overview, "`", "'"),
|
||||
Overview: strings.ReplaceAll(ep.Overview, "`", "'"),
|
||||
EpisodeNumber: ep.Number,
|
||||
Episode: key,
|
||||
SeasonNumber: ep.SeasonNumber,
|
||||
AbsoluteEpisodeNumber: ep.AbsoluteNumber,
|
||||
AnidbEid: ep.AnidbId,
|
||||
HasImage: ep.Image != "",
|
||||
}
|
||||
if em.Length == 0 && ep.Runtime > 0 {
|
||||
em.Length = ep.Runtime
|
||||
}
|
||||
if em.Summary == "" && ep.Overview != "" {
|
||||
em.Summary = ep.Overview
|
||||
}
|
||||
if em.Overview == "" && ep.Overview != "" {
|
||||
em.Overview = ep.Overview
|
||||
}
|
||||
if ep.TvdbTitle != "" && ep.AnidbTitle == "Episode "+ep.AnidbEpisode {
|
||||
em.Title = ep.TvdbTitle
|
||||
|
||||
}
|
||||
ret.Episodes[key] = em
|
||||
}
|
||||
|
||||
// Event
|
||||
event := &AnimeMetadataEvent{
|
||||
MediaId: mId,
|
||||
AnimeMetadata: ret,
|
||||
}
|
||||
err = hook.GlobalHookManager.OnAnimeMetadata().Trigger(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = event.AnimeMetadata
|
||||
mId = event.MediaId
|
||||
|
||||
p.animeMetadataCache.SetT(GetAnimeMetadataCacheKey(platform, mId), ret, 1*time.Hour)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetAnimeMetadataWrapper creates a new anime wrapper.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// metadataProvider.GetAnimeMetadataWrapper(media, metadata)
|
||||
// metadataProvider.GetAnimeMetadataWrapper(media, nil)
|
||||
func (p *ProviderImpl) GetAnimeMetadataWrapper(media *anilist.BaseAnime, metadata *AnimeMetadata) AnimeMetadataWrapper {
|
||||
aw := &AnimeWrapperImpl{
|
||||
metadata: mo.None[*AnimeMetadata](),
|
||||
baseAnime: media,
|
||||
fileCacher: p.fileCacher,
|
||||
logger: p.logger,
|
||||
}
|
||||
|
||||
if metadata != nil {
|
||||
aw.metadata = mo.Some(metadata)
|
||||
}
|
||||
|
||||
return aw
|
||||
}
|
||||
Reference in New Issue
Block a user