Release Memby 0.2.64
This commit is contained in:
@@ -85,24 +85,78 @@ const MDBListSettingsKey = "mdblist_settings"
|
||||
// HeroPolicy stores only Emby ids and the optional prime-card copy. Names and artwork
|
||||
// remain library data, so a metadata correction appears without rewriting operator policy.
|
||||
type HeroPolicy struct {
|
||||
PinnedItemIDs []string `json:"pinnedItemIds"`
|
||||
LegacyPinnedMovieIDs []string `json:"pinnedMovieIds,omitempty"`
|
||||
PrimeSubtitle string `json:"primeSubtitle"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Schedules []HeroSchedule `json:"schedules"`
|
||||
PinnedItemIDs []string `json:"pinnedItemIds"`
|
||||
LegacyPinnedMovieIDs []string `json:"pinnedMovieIds,omitempty"`
|
||||
PrimeSubtitle string `json:"primeSubtitle"`
|
||||
Placements map[string]HeroPlacementPolicy `json:"placements,omitempty"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Schedules []HeroSchedule `json:"schedules"`
|
||||
}
|
||||
|
||||
// HeroPlacementPolicy is one independently resolved spotlight. Keeping the placement as
|
||||
// a map key means another section can be added without changing the stored document.
|
||||
type HeroPlacementPolicy struct {
|
||||
PinnedItemIDs []string `json:"pinnedItemIds"`
|
||||
PrimeSubtitle string `json:"primeSubtitle"`
|
||||
}
|
||||
|
||||
// HeroSchedule is resolved by the gateway for every home response. Times are UTC RFC3339;
|
||||
// weekdays use the local calendar day (Sunday=0) and an empty list means every day.
|
||||
type HeroSchedule struct {
|
||||
ID string `json:"id"`
|
||||
ItemID string `json:"itemId"`
|
||||
StartAt time.Time `json:"startAt"`
|
||||
EndAt time.Time `json:"endAt"`
|
||||
Weekdays []int `json:"weekdays,omitempty"`
|
||||
Priority int `json:"priority"`
|
||||
UserID string `json:"userId,omitempty"`
|
||||
Enabled bool `json:"enabled"`
|
||||
ID string `json:"id"`
|
||||
ItemID string `json:"itemId"`
|
||||
StartAt time.Time `json:"startAt"`
|
||||
EndAt time.Time `json:"endAt"`
|
||||
Weekdays []int `json:"weekdays,omitempty"`
|
||||
Priority int `json:"priority"`
|
||||
UserID string `json:"userId,omitempty"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Placements []string `json:"placements,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
HeroPlacementHome = "home"
|
||||
HeroPlacementMovies = "movies"
|
||||
HeroPlacementTVShows = "tv_shows"
|
||||
)
|
||||
|
||||
func ValidHeroPlacement(value string) bool {
|
||||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||||
case HeroPlacementHome, HeroPlacementMovies, HeroPlacementTVShows:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func normaliseHeroPlacementPolicy(policy HeroPlacementPolicy) HeroPlacementPolicy {
|
||||
seen := map[string]bool{}
|
||||
ids := make([]string, 0, min(len(policy.PinnedItemIDs), 4))
|
||||
for _, id := range policy.PinnedItemIDs {
|
||||
id = strings.TrimSpace(id)
|
||||
if id == "" || seen[id] || len(ids) == 4 {
|
||||
continue
|
||||
}
|
||||
seen[id] = true
|
||||
ids = append(ids, id)
|
||||
}
|
||||
policy.PinnedItemIDs = ids
|
||||
policy.PrimeSubtitle = strings.TrimSpace(policy.PrimeSubtitle)
|
||||
if runes := []rune(policy.PrimeSubtitle); len(runes) > 160 {
|
||||
policy.PrimeSubtitle = string(runes[:160])
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func (policy HeroPolicy) Placement(name string) HeroPlacementPolicy {
|
||||
name = strings.ToLower(strings.TrimSpace(name))
|
||||
if placement, ok := policy.Placements[name]; ok {
|
||||
return placement
|
||||
}
|
||||
if name == HeroPlacementHome {
|
||||
return HeroPlacementPolicy{PinnedItemIDs: policy.PinnedItemIDs, PrimeSubtitle: policy.PrimeSubtitle}
|
||||
}
|
||||
return HeroPlacementPolicy{PinnedItemIDs: []string{}}
|
||||
}
|
||||
|
||||
func normalizeHeroPolicy(policy HeroPolicy) HeroPolicy {
|
||||
@@ -126,6 +180,27 @@ func normalizeHeroPolicy(policy HeroPolicy) HeroPolicy {
|
||||
if len(runes) > 160 {
|
||||
policy.PrimeSubtitle = string(runes[:160])
|
||||
}
|
||||
if policy.Placements == nil {
|
||||
policy.Placements = map[string]HeroPlacementPolicy{}
|
||||
}
|
||||
if _, exists := policy.Placements[HeroPlacementHome]; !exists {
|
||||
policy.Placements[HeroPlacementHome] = HeroPlacementPolicy{PinnedItemIDs: policy.PinnedItemIDs, PrimeSubtitle: policy.PrimeSubtitle}
|
||||
}
|
||||
cleanPlacements := make(map[string]HeroPlacementPolicy, len(policy.Placements))
|
||||
for name, placement := range policy.Placements {
|
||||
name = strings.ToLower(strings.TrimSpace(name))
|
||||
if ValidHeroPlacement(name) {
|
||||
cleanPlacements[name] = normaliseHeroPlacementPolicy(placement)
|
||||
}
|
||||
}
|
||||
for _, name := range []string{HeroPlacementHome, HeroPlacementMovies, HeroPlacementTVShows} {
|
||||
if _, exists := cleanPlacements[name]; !exists {
|
||||
cleanPlacements[name] = HeroPlacementPolicy{PinnedItemIDs: []string{}}
|
||||
}
|
||||
}
|
||||
policy.Placements = cleanPlacements
|
||||
home := policy.Placement(HeroPlacementHome)
|
||||
policy.PinnedItemIDs, policy.PrimeSubtitle = home.PinnedItemIDs, home.PrimeSubtitle
|
||||
cleanSchedules := make([]HeroSchedule, 0, len(policy.Schedules))
|
||||
seenSchedules := map[string]bool{}
|
||||
for _, schedule := range policy.Schedules {
|
||||
@@ -149,6 +224,19 @@ func normalizeHeroPolicy(policy HeroPolicy) HeroPolicy {
|
||||
}
|
||||
}
|
||||
schedule.Weekdays = weekdays
|
||||
placements := make([]string, 0, len(schedule.Placements))
|
||||
seenPlacements := map[string]bool{}
|
||||
for _, placement := range schedule.Placements {
|
||||
placement = strings.ToLower(strings.TrimSpace(placement))
|
||||
if ValidHeroPlacement(placement) && !seenPlacements[placement] {
|
||||
seenPlacements[placement] = true
|
||||
placements = append(placements, placement)
|
||||
}
|
||||
}
|
||||
if len(placements) == 0 {
|
||||
placements = []string{HeroPlacementHome}
|
||||
}
|
||||
schedule.Placements = placements
|
||||
cleanSchedules = append(cleanSchedules, schedule)
|
||||
}
|
||||
policy.Schedules = cleanSchedules
|
||||
|
||||
Reference in New Issue
Block a user