152 lines
4.0 KiB
Go
152 lines
4.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/Silo-Server/silo-server/internal/catalog"
|
|
"github.com/Silo-Server/silo-server/internal/models"
|
|
"github.com/Silo-Server/silo-server/internal/userstore"
|
|
)
|
|
|
|
type itemUserStateResponse struct {
|
|
Played bool `json:"played"`
|
|
IsFavorite bool `json:"is_favorite"`
|
|
InWatchlist bool `json:"in_watchlist"`
|
|
}
|
|
|
|
func resolveItemUserStates(
|
|
ctx context.Context,
|
|
store userstore.UserStore,
|
|
profileID string,
|
|
episodeRepo *catalog.EpisodeRepository,
|
|
items []*models.MediaItem,
|
|
) (map[string]*itemUserStateResponse, error) {
|
|
result := make(map[string]*itemUserStateResponse, len(items))
|
|
if store == nil || profileID == "" || len(items) == 0 {
|
|
return result, nil
|
|
}
|
|
|
|
contentIDs := make([]string, 0, len(items))
|
|
seriesIDs := make([]string, 0)
|
|
seasonIDs := make([]string, 0)
|
|
seenContent := make(map[string]struct{}, len(items))
|
|
seenSeries := make(map[string]struct{})
|
|
seenSeason := make(map[string]struct{})
|
|
|
|
for _, item := range items {
|
|
if item == nil || item.ContentID == "" {
|
|
continue
|
|
}
|
|
if _, ok := seenContent[item.ContentID]; ok {
|
|
continue
|
|
}
|
|
seenContent[item.ContentID] = struct{}{}
|
|
contentIDs = append(contentIDs, item.ContentID)
|
|
switch item.Type {
|
|
case "series":
|
|
if _, ok := seenSeries[item.ContentID]; !ok {
|
|
seenSeries[item.ContentID] = struct{}{}
|
|
seriesIDs = append(seriesIDs, item.ContentID)
|
|
}
|
|
case "season":
|
|
if _, ok := seenSeason[item.ContentID]; !ok {
|
|
seenSeason[item.ContentID] = struct{}{}
|
|
seasonIDs = append(seasonIDs, item.ContentID)
|
|
}
|
|
}
|
|
}
|
|
|
|
favoriteMap, err := store.ListFavoritesByMediaItems(ctx, profileID, contentIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
watchlistMap, err := store.ListWatchlistByMediaItems(ctx, profileID, contentIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
progressIDs := append([]string{}, contentIDs...)
|
|
seriesEpisodes := map[string][]*models.Episode{}
|
|
seasonEpisodes := map[string][]*models.Episode{}
|
|
if episodeRepo != nil {
|
|
if len(seriesIDs) > 0 {
|
|
seriesEpisodes, err = episodeRepo.ListBySeriesIDs(ctx, seriesIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, episodes := range seriesEpisodes {
|
|
for _, episode := range episodes {
|
|
if episode == nil || episode.ContentID == "" {
|
|
continue
|
|
}
|
|
if _, ok := seenContent[episode.ContentID]; ok {
|
|
continue
|
|
}
|
|
seenContent[episode.ContentID] = struct{}{}
|
|
progressIDs = append(progressIDs, episode.ContentID)
|
|
}
|
|
}
|
|
}
|
|
if len(seasonIDs) > 0 {
|
|
seasonEpisodes, err = episodeRepo.ListBySeasonIDs(ctx, seasonIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, episodes := range seasonEpisodes {
|
|
for _, episode := range episodes {
|
|
if episode == nil || episode.ContentID == "" {
|
|
continue
|
|
}
|
|
if _, ok := seenContent[episode.ContentID]; ok {
|
|
continue
|
|
}
|
|
seenContent[episode.ContentID] = struct{}{}
|
|
progressIDs = append(progressIDs, episode.ContentID)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
progressMap, err := store.ListProgressByMediaItems(ctx, profileID, progressIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, item := range items {
|
|
if item == nil || item.ContentID == "" {
|
|
continue
|
|
}
|
|
state := &itemUserStateResponse{
|
|
IsFavorite: favoriteMap[item.ContentID],
|
|
InWatchlist: watchlistMap[item.ContentID],
|
|
}
|
|
switch item.Type {
|
|
case "series":
|
|
state.Played = allEpisodesCompleted(seriesEpisodes[item.ContentID], progressMap)
|
|
case "season":
|
|
state.Played = allEpisodesCompleted(seasonEpisodes[item.ContentID], progressMap)
|
|
default:
|
|
state.Played = progressMap[item.ContentID].Completed
|
|
}
|
|
result[item.ContentID] = state
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func allEpisodesCompleted(episodes []*models.Episode, progressMap map[string]userstore.WatchProgress) bool {
|
|
if len(episodes) == 0 {
|
|
return false
|
|
}
|
|
for _, episode := range episodes {
|
|
if episode == nil || episode.ContentID == "" {
|
|
return false
|
|
}
|
|
progress, ok := progressMap[episode.ContentID]
|
|
if !ok || !progress.Completed {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|