0.3.07
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// decorateSeriesStatuses makes Status on an ordinary Emby series the canonical detail
|
||||
// answer. Sonarr's daily observation wins when it is recognised; otherwise Emby's field
|
||||
// is left untouched as the fallback.
|
||||
func (s *Server) decorateSeriesStatuses(ctx context.Context, collections ...[]json.RawMessage) {
|
||||
if s.store == nil {
|
||||
return
|
||||
}
|
||||
tvdbIDs := []int{}
|
||||
seen := map[int]bool{}
|
||||
identities := make([]map[int]int, len(collections))
|
||||
for collectionIndex, items := range collections {
|
||||
identities[collectionIndex] = map[int]int{}
|
||||
for itemIndex, raw := range items {
|
||||
tvdbID := seriesTVDBID(raw)
|
||||
if tvdbID <= 0 {
|
||||
continue
|
||||
}
|
||||
identities[collectionIndex][itemIndex] = tvdbID
|
||||
if !seen[tvdbID] {
|
||||
seen[tvdbID] = true
|
||||
tvdbIDs = append(tvdbIDs, tvdbID)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(tvdbIDs) == 0 {
|
||||
return
|
||||
}
|
||||
statuses, err := s.store.LatestSonarrSeriesStatuses(ctx, tvdbIDs)
|
||||
if err != nil {
|
||||
s.loggerFor(ctx).Warn("stored Sonarr series statuses unavailable", "error", err)
|
||||
return
|
||||
}
|
||||
for collectionIndex, itemIndexes := range identities {
|
||||
for itemIndex, tvdbID := range itemIndexes {
|
||||
status := canonicalSonarrSeriesStatus(statuses[tvdbID])
|
||||
if status != "" {
|
||||
collections[collectionIndex][itemIndex] = injectSeriesStatus(
|
||||
collections[collectionIndex][itemIndex], status,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func seriesTVDBID(raw json.RawMessage) int {
|
||||
var item struct {
|
||||
Type string `json:"Type"`
|
||||
ProviderIDs map[string]string `json:"ProviderIds"`
|
||||
}
|
||||
if json.Unmarshal(raw, &item) != nil || !strings.EqualFold(item.Type, "Series") {
|
||||
return 0
|
||||
}
|
||||
id, _ := strconv.Atoi(providerID(item.ProviderIDs, "tvdb"))
|
||||
return id
|
||||
}
|
||||
|
||||
// canonicalSonarrSeriesStatus is deliberately conservative. Unknown values are not
|
||||
// copied over a usable Emby status, and American spelling is normalised at the render
|
||||
// boundary before it can become viewer-facing text.
|
||||
func canonicalSonarrSeriesStatus(status string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(status)) {
|
||||
case "continuing":
|
||||
return "Continuing"
|
||||
case "ended":
|
||||
return "Ended"
|
||||
case "cancelled", "canceled":
|
||||
return "Cancelled"
|
||||
case "upcoming":
|
||||
return "Upcoming"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func injectSeriesStatus(raw json.RawMessage, status string) json.RawMessage {
|
||||
if status == "" {
|
||||
return raw
|
||||
}
|
||||
var members map[string]json.RawMessage
|
||||
if json.Unmarshal(raw, &members) != nil || members == nil {
|
||||
return raw
|
||||
}
|
||||
encoded, err := json.Marshal(status)
|
||||
if err != nil {
|
||||
return raw
|
||||
}
|
||||
members["Status"] = encoded
|
||||
out, err := json.Marshal(members)
|
||||
if err != nil {
|
||||
return raw
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user