149 lines
4.2 KiB
Go
149 lines
4.2 KiB
Go
package anime
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"seanime/internal/api/anilist"
|
|
"seanime/internal/platforms/platform"
|
|
"sort"
|
|
|
|
"github.com/sourcegraph/conc/pool"
|
|
)
|
|
|
|
type (
|
|
SimpleEntry struct {
|
|
MediaId int `json:"mediaId"`
|
|
Media *anilist.BaseAnime `json:"media"`
|
|
EntryListData *EntryListData `json:"listData"`
|
|
EntryLibraryData *EntryLibraryData `json:"libraryData"`
|
|
Episodes []*Episode `json:"episodes"`
|
|
NextEpisode *Episode `json:"nextEpisode"`
|
|
LocalFiles []*LocalFile `json:"localFiles"`
|
|
CurrentEpisodeCount int `json:"currentEpisodeCount"`
|
|
}
|
|
|
|
SimpleEntryListData struct {
|
|
Progress int `json:"progress,omitempty"`
|
|
Score float64 `json:"score,omitempty"`
|
|
Status *anilist.MediaListStatus `json:"status,omitempty"`
|
|
StartedAt string `json:"startedAt,omitempty"`
|
|
CompletedAt string `json:"completedAt,omitempty"`
|
|
}
|
|
|
|
NewSimpleAnimeEntryOptions struct {
|
|
MediaId int
|
|
LocalFiles []*LocalFile // All local files
|
|
AnimeCollection *anilist.AnimeCollection
|
|
Platform platform.Platform
|
|
}
|
|
)
|
|
|
|
func NewSimpleEntry(ctx context.Context, opts *NewSimpleAnimeEntryOptions) (*SimpleEntry, error) {
|
|
|
|
if opts.AnimeCollection == nil ||
|
|
opts.Platform == nil {
|
|
return nil, errors.New("missing arguments when creating simple media entry")
|
|
}
|
|
// Create new Entry
|
|
entry := new(SimpleEntry)
|
|
entry.MediaId = opts.MediaId
|
|
|
|
// +---------------------+
|
|
// | AniList entry |
|
|
// +---------------------+
|
|
|
|
// Get the Anilist List entry
|
|
anilistEntry, found := opts.AnimeCollection.GetListEntryFromAnimeId(opts.MediaId)
|
|
|
|
// Set the media
|
|
// If the Anilist List entry does not exist, fetch the media from AniList
|
|
if !found {
|
|
// If the Anilist entry does not exist, instantiate one with zero values
|
|
anilistEntry = &anilist.AnimeListEntry{}
|
|
|
|
// Fetch the media
|
|
fetchedMedia, err := opts.Platform.GetAnime(ctx, opts.MediaId) // DEVNOTE: Maybe cache it?
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
entry.Media = fetchedMedia
|
|
} else {
|
|
entry.Media = anilistEntry.Media
|
|
}
|
|
|
|
entry.CurrentEpisodeCount = entry.Media.GetCurrentEpisodeCount()
|
|
|
|
// +---------------------+
|
|
// | Local files |
|
|
// +---------------------+
|
|
|
|
// Get the entry's local files
|
|
lfs := GetLocalFilesFromMediaId(opts.LocalFiles, opts.MediaId)
|
|
entry.LocalFiles = lfs // Returns empty slice if no local files are found
|
|
|
|
libraryData, _ := NewEntryLibraryData(&NewEntryLibraryDataOptions{
|
|
EntryLocalFiles: lfs,
|
|
MediaId: entry.Media.ID,
|
|
CurrentProgress: anilistEntry.GetProgressSafe(),
|
|
})
|
|
entry.EntryLibraryData = libraryData
|
|
|
|
// Instantiate EntryListData
|
|
// If the media exist in the user's anime list, add the details
|
|
if found {
|
|
entry.EntryListData = &EntryListData{
|
|
Progress: anilistEntry.GetProgressSafe(),
|
|
Score: anilistEntry.GetScoreSafe(),
|
|
Status: anilistEntry.Status,
|
|
Repeat: anilistEntry.GetRepeatSafe(),
|
|
StartedAt: anilist.ToEntryStartDate(anilistEntry.StartedAt),
|
|
CompletedAt: anilist.ToEntryCompletionDate(anilistEntry.CompletedAt),
|
|
}
|
|
}
|
|
|
|
// +---------------------+
|
|
// | Episodes |
|
|
// +---------------------+
|
|
|
|
// Create episode entities
|
|
entry.hydrateEntryEpisodeData()
|
|
|
|
return entry, nil
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
|
|
// hydrateEntryEpisodeData
|
|
// AniZipData, Media and LocalFiles should be defined
|
|
func (e *SimpleEntry) hydrateEntryEpisodeData() {
|
|
|
|
// +---------------------+
|
|
// | Episodes |
|
|
// +---------------------+
|
|
|
|
p := pool.NewWithResults[*Episode]()
|
|
for _, lf := range e.LocalFiles {
|
|
lf := lf
|
|
p.Go(func() *Episode {
|
|
return NewSimpleEpisode(&NewSimpleEpisodeOptions{
|
|
LocalFile: lf,
|
|
Media: e.Media,
|
|
IsDownloaded: true,
|
|
})
|
|
})
|
|
}
|
|
episodes := p.Wait()
|
|
// Sort by progress number
|
|
sort.Slice(episodes, func(i, j int) bool {
|
|
return episodes[i].EpisodeNumber < episodes[j].EpisodeNumber
|
|
})
|
|
e.Episodes = episodes
|
|
|
|
nextEp, found := e.FindNextEpisode()
|
|
if found {
|
|
e.NextEpisode = nextEp
|
|
}
|
|
|
|
}
|