112 lines
3.3 KiB
Go
112 lines
3.3 KiB
Go
package anime
|
|
|
|
import (
|
|
"fmt"
|
|
"seanime/internal/api/anilist"
|
|
"seanime/internal/hook"
|
|
"time"
|
|
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type ScheduleItem struct {
|
|
MediaId int `json:"mediaId"`
|
|
Title string `json:"title"`
|
|
// Time is in 15:04 format
|
|
Time string `json:"time"`
|
|
// DateTime is in UTC
|
|
DateTime time.Time `json:"dateTime"`
|
|
Image string `json:"image"`
|
|
EpisodeNumber int `json:"episodeNumber"`
|
|
IsMovie bool `json:"isMovie"`
|
|
IsSeasonFinale bool `json:"isSeasonFinale"`
|
|
}
|
|
|
|
func GetScheduleItems(animeSchedule *anilist.AnimeAiringSchedule, animeCollection *anilist.AnimeCollection) []*ScheduleItem {
|
|
animeEntryMap := make(map[int]*anilist.AnimeListEntry)
|
|
for _, list := range animeCollection.MediaListCollection.GetLists() {
|
|
for _, entry := range list.GetEntries() {
|
|
animeEntryMap[entry.GetMedia().GetID()] = entry
|
|
}
|
|
}
|
|
|
|
type animeScheduleNode interface {
|
|
GetAiringAt() int
|
|
GetTimeUntilAiring() int
|
|
GetEpisode() int
|
|
}
|
|
|
|
type animeScheduleMedia interface {
|
|
GetMedia() []*anilist.AnimeSchedule
|
|
}
|
|
|
|
formatNodeItem := func(node animeScheduleNode, entry *anilist.AnimeListEntry) *ScheduleItem {
|
|
t := time.Unix(int64(node.GetAiringAt()), 0)
|
|
item := &ScheduleItem{
|
|
MediaId: entry.GetMedia().GetID(),
|
|
Title: *entry.GetMedia().GetTitle().GetUserPreferred(),
|
|
Time: t.UTC().Format("15:04"),
|
|
DateTime: t.UTC(),
|
|
Image: entry.GetMedia().GetCoverImageSafe(),
|
|
EpisodeNumber: node.GetEpisode(),
|
|
IsMovie: entry.GetMedia().IsMovie(),
|
|
IsSeasonFinale: false,
|
|
}
|
|
if entry.GetMedia().GetTotalEpisodeCount() > 0 && node.GetEpisode() == entry.GetMedia().GetTotalEpisodeCount() {
|
|
item.IsSeasonFinale = true
|
|
}
|
|
return item
|
|
}
|
|
|
|
formatPart := func(m animeScheduleMedia) ([]*ScheduleItem, bool) {
|
|
if m == nil {
|
|
return nil, false
|
|
}
|
|
ret := make([]*ScheduleItem, 0)
|
|
for _, m := range m.GetMedia() {
|
|
entry, ok := animeEntryMap[m.GetID()]
|
|
if !ok || entry.Status == nil || *entry.Status == anilist.MediaListStatusDropped {
|
|
continue
|
|
}
|
|
for _, n := range m.GetPrevious().GetNodes() {
|
|
ret = append(ret, formatNodeItem(n, entry))
|
|
}
|
|
for _, n := range m.GetUpcoming().GetNodes() {
|
|
ret = append(ret, formatNodeItem(n, entry))
|
|
}
|
|
}
|
|
return ret, true
|
|
}
|
|
|
|
ongoingItems, _ := formatPart(animeSchedule.GetOngoing())
|
|
ongoingNextItems, _ := formatPart(animeSchedule.GetOngoingNext())
|
|
precedingItems, _ := formatPart(animeSchedule.GetPreceding())
|
|
upcomingItems, _ := formatPart(animeSchedule.GetUpcoming())
|
|
upcomingNextItems, _ := formatPart(animeSchedule.GetUpcomingNext())
|
|
|
|
allItems := make([]*ScheduleItem, 0)
|
|
allItems = append(allItems, ongoingItems...)
|
|
allItems = append(allItems, ongoingNextItems...)
|
|
allItems = append(allItems, precedingItems...)
|
|
allItems = append(allItems, upcomingItems...)
|
|
allItems = append(allItems, upcomingNextItems...)
|
|
|
|
ret := lo.UniqBy(allItems, func(item *ScheduleItem) string {
|
|
if item == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("%d-%d-%d", item.MediaId, item.EpisodeNumber, item.DateTime.Unix())
|
|
})
|
|
|
|
event := &AnimeScheduleItemsEvent{
|
|
AnimeCollection: animeCollection,
|
|
Items: ret,
|
|
}
|
|
err := hook.GlobalHookManager.OnAnimeScheduleItems().Trigger(event)
|
|
if err != nil {
|
|
return ret
|
|
}
|
|
|
|
return event.Items
|
|
}
|