media: support rss movie items with tmdb ids (#22)

This commit is contained in:
l3uddz
2021-02-21 22:30:56 +00:00
committed by GitHub
parent db9fdc97a2
commit 10a70f1da2
10 changed files with 118 additions and 57 deletions

View File

@@ -207,6 +207,9 @@ func main() {
case "imdb": case "imdb":
testItem.Title = "Test.Mode.2021.BluRay.1080p.TrueHD.Atmos.7.1.AVC.HYBRID.REMUX-FraMeSToR" testItem.Title = "Test.Mode.2021.BluRay.1080p.TrueHD.Atmos.7.1.AVC.HYBRID.REMUX-FraMeSToR"
testItem.ImdbId = idParts[1] testItem.ImdbId = idParts[1]
case "tmdb":
testItem.Title = "Test.Mode.2021.BluRay.1080p.TrueHD.Atmos.7.1.AVC.HYBRID.REMUX-FraMeSToR"
testItem.TmdbId = idParts[1]
case "tvdb": case "tvdb":
testItem.Title = "Test.Mode.S01E01.1080p.DTS-HD.MA.5.1.AVC.REMUX-FraMeSToR" testItem.Title = "Test.Mode.S01E01.1080p.DTS-HD.MA.5.1.AVC.REMUX-FraMeSToR"
testItem.TvdbId = idParts[1] testItem.TvdbId = idParts[1]

View File

@@ -9,13 +9,19 @@ import (
) )
func (c *Client) GetMovieInfo(item *FeedItem) (*Item, error) { func (c *Client) GetMovieInfo(item *FeedItem) (*Item, error) {
// retrieve and validate media provider data
mdp, mdi := item.GetProviderData()
if mdp == "" || mdi == "" {
return nil, fmt.Errorf("trakt: get movie: no media provider details found")
}
// lookup on trakt // lookup on trakt
t, err := c.trakt.GetMovie(item.ImdbId) t, err := c.trakt.GetMovie(mdp, mdi)
if err != nil { if err != nil {
if errors.Is(err, trakt.ErrItemNotFound) { if errors.Is(err, trakt.ErrItemNotFound) {
return nil, fmt.Errorf("trakt: get movie: movie with imdbId %q: %w", item.ImdbId, ErrItemNotFound) return nil, fmt.Errorf("trakt: get movie: movie with %sId %q: %w", mdp, mdi, ErrItemNotFound)
} }
return nil, fmt.Errorf("trakt: get movie: movie with imdbId %q: %w", item.ImdbId, err) return nil, fmt.Errorf("trakt: get movie: movie with %sId %q: %w", mdp, mdi, err)
} }
// transform trakt info // transform trakt info

View File

@@ -8,13 +8,19 @@ import (
) )
func (c *Client) GetShowInfo(item *FeedItem) (*Item, error) { func (c *Client) GetShowInfo(item *FeedItem) (*Item, error) {
// retrieve and validate media provider data
mdp, mdi := item.GetProviderData()
if mdp == "" || mdi == "" {
return nil, fmt.Errorf("trakt: get show: no media provider details found")
}
// lookup on trakt // lookup on trakt
t, err := c.trakt.GetShow(item.TvdbId) t, err := c.trakt.GetShow(mdp, mdi)
if err != nil { if err != nil {
if errors.Is(err, trakt.ErrItemNotFound) { if errors.Is(err, trakt.ErrItemNotFound) {
return nil, fmt.Errorf("trakt: get show: show with tvdbId %q: %w", item.TvdbId, ErrItemNotFound) return nil, fmt.Errorf("trakt: get show: show with %sId %q: %w", mdp, mdi, ErrItemNotFound)
} }
return nil, fmt.Errorf("trakt: get show: show with tvdbId %q: %w", item.TvdbId, err) return nil, fmt.Errorf("trakt: get show: show with %sId %q: %w", mdp, mdi, err)
} }
// transform trakt info to MediaItem // transform trakt info to MediaItem

View File

@@ -8,6 +8,8 @@ import (
"time" "time"
) )
/* Media Item(s) */
type Item struct { type Item struct {
TvdbId string `json:"TvdbId,omitempty"` TvdbId string `json:"TvdbId,omitempty"`
TmdbId string `json:"TmdbId,omitempty"` TmdbId string `json:"TmdbId,omitempty"`
@@ -33,6 +35,20 @@ type Item struct {
Tvdb tvdb.Item `json:"Tvdb,omitempty"` Tvdb tvdb.Item `json:"Tvdb,omitempty"`
} }
func (i *Item) GetProviderData() (string, string) {
switch {
case i.TvdbId != "" && i.TvdbId != "0":
return "tvdb", i.TvdbId
case i.TmdbId != "" && i.TmdbId != "0":
return "tmdb", i.TmdbId
case i.ImdbId != "":
return "imdb", i.ImdbId
}
return "", ""
}
/* Rss Item(s) */
type Rss struct { type Rss struct {
Channel struct { Channel struct {
Items []FeedItem `xml:"item"` Items []FeedItem `xml:"item"`
@@ -53,6 +69,7 @@ type FeedItem struct {
TvdbId string `xml:"tvdb,omitempty"` TvdbId string `xml:"tvdb,omitempty"`
TvMazeId string TvMazeId string
ImdbId string `xml:"imdb,omitempty"` ImdbId string `xml:"imdb,omitempty"`
TmdbId string `xml:"tmdb,omitempty"`
Attributes []struct { Attributes []struct {
XMLName xml.Name XMLName xml.Name
@@ -61,6 +78,18 @@ type FeedItem struct {
} `xml:"attr"` } `xml:"attr"`
} }
func (f *FeedItem) GetProviderData() (string, string) {
switch {
case f.TvdbId != "" && f.TvdbId != "0":
return "tvdb", f.TvdbId
case f.TmdbId != "" && f.TmdbId != "0":
return "tmdb", f.TmdbId
case f.ImdbId != "":
return "imdb", f.ImdbId
}
return "", ""
}
// Time credits: https://github.com/mrobinsn/go-newznab/blob/cd89d9c56447859fa1298dc9a0053c92c45ac7ef/newznab/structs.go#L150 // Time credits: https://github.com/mrobinsn/go-newznab/blob/cd89d9c56447859fa1298dc9a0053c92c45ac7ef/newznab/structs.go#L150
type Time struct { type Time struct {
time.Time time.Time

View File

@@ -13,9 +13,9 @@ var (
ErrItemNotFound = errors.New("not found") ErrItemNotFound = errors.New("not found")
) )
func (c *Client) GetShow(tvdbId string) (*Show, error) { func (c *Client) GetShow(providerType string, providerId string) (*Show, error) {
// prepare request // prepare request
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "search", "tvdb", tvdbId), reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "search", providerType, providerId),
url.Values{ url.Values{
"type": []string{"show"}, "type": []string{"show"},
"extended": []string{"full"}}) "extended": []string{"full"}})
@@ -52,9 +52,9 @@ func (c *Client) GetShow(tvdbId string) (*Show, error) {
return show, nil return show, nil
} }
func (c *Client) GetMovie(imdbId string) (*Movie, error) { func (c *Client) GetMovie(providerType string, providerId string) (*Movie, error) {
// prepare request // prepare request
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "search", "imdb", imdbId), reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "search", providerType, providerId),
url.Values{ url.Values{
"type": []string{"movie"}, "type": []string{"movie"},
"extended": []string{"full"}}) "extended": []string{"full"}})

View File

@@ -69,19 +69,15 @@ func (c *Client) getQualityProfileId(profileName string) (int, error) {
} }
func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) { func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) {
// determine metadata id to use // retrieve and validate media provider data
mdType := "imdb" mdp, mdi := item.GetProviderData()
mdId := item.ImdbId if mdp == "" || mdi == "" {
return nil, fmt.Errorf("no media provider details found")
if item.TmdbId != "" && item.TmdbId != "0" {
// radarr prefers tmdb
mdType = "tmdb"
mdId = item.TmdbId
} }
// prepare request // prepare request
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "movie", "lookup"), reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "movie", "lookup"),
url.Values{"term": []string{fmt.Sprintf("%s:%s", mdType, mdId)}}) url.Values{"term": []string{fmt.Sprintf("%s:%s", mdp, mdi)}})
if err != nil { if err != nil {
return nil, fmt.Errorf("generate movie lookup request url: %w", err) return nil, fmt.Errorf("generate movie lookup request url: %w", err)
} }
@@ -106,19 +102,19 @@ func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) {
// find movie // find movie
for _, s := range *b { for _, s := range *b {
switch mdType { switch mdp {
case "tmdb": case "tmdb":
if strconv.Itoa(s.TmdbId) == item.TmdbId { if strconv.Itoa(s.TmdbId) == mdi {
return &s, nil return &s, nil
} }
default: default:
if s.ImdbId == item.ImdbId { if s.ImdbId == mdi {
return &s, nil return &s, nil
} }
} }
} }
return nil, fmt.Errorf("movie lookup %sId: %v: %w", mdType, mdId, ErrItemNotFound) return nil, fmt.Errorf("movie lookup %sId: %v: %w", mdp, mdi, ErrItemNotFound)
} }
func (c *Client) AddMediaItem(item *media.Item, opts ...nabarr.PvrOption) error { func (c *Client) AddMediaItem(item *media.Item, opts ...nabarr.PvrOption) error {

View File

@@ -32,17 +32,18 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
return return
} }
// validate item has required id(s) // retrieve and validate media provider data
if feedItem.ImdbId == "" { mdp, mdi := feedItem.GetProviderData()
if mdp == "" || mdi == "" {
continue continue
} }
// check cache / add item to cache // check cache / add item to cache
pvrCacheBucket := fmt.Sprintf("pvr_%s_%s", c.Type(), c.name) cacheBucket := fmt.Sprintf("pvr_%s_%s", c.Type(), c.name)
cacheKey := fmt.Sprintf("imdb_%s", feedItem.ImdbId) cacheKey := fmt.Sprintf("%s_%s", mdp, mdi)
if !c.testMode { if !c.testMode {
// not running in test mode, so use cache // not running in test mode, so use cache
if cacheValue, err := c.cache.Get(pvrCacheBucket, cacheKey); err == nil { if cacheValue, err := c.cache.Get(cacheBucket, cacheKey); err == nil {
// item already exists in the cache // item already exists in the cache
switch string(cacheValue) { switch string(cacheValue) {
case c.name: case c.name:
@@ -55,7 +56,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
} }
// insert temp cache entry // insert temp cache entry
if err := c.cache.Put(pvrCacheBucket, cacheKey, []byte(c.cacheFiltersHash), c.cacheTempDuration); err != nil { if err := c.cache.Put(cacheBucket, cacheKey, []byte(c.cacheFiltersHash), c.cacheTempDuration); err != nil {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Msg("Failed storing item in temp cache") Msg("Failed storing item in temp cache")
@@ -69,7 +70,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Debug(). c.log.Debug().
Err(err). Err(err).
Str("feed_title", feedItem.Title). Str("feed_title", feedItem.Title).
Str("feed_imdb_id", feedItem.ImdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Item was not found on trakt") Msg("Item was not found on trakt")
continue continue
@@ -78,7 +79,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Str("feed_title", feedItem.Title). Str("feed_title", feedItem.Title).
Str("feed_imdb_id", feedItem.ImdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Failed finding item on trakt") Msg("Failed finding item on trakt")
continue continue
@@ -90,11 +91,11 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
Msg("Item found on trakt") Msg("Item found on trakt")
} }
// validate tmdbId was found // validate tmdbId was found (radarr works best with these)
if mediaItem.TmdbId == "" || mediaItem.TmdbId == "0" { if mediaItem.TmdbId == "" || mediaItem.TmdbId == "0" {
c.log.Warn(). c.log.Warn().
Str("feed_title", mediaItem.FeedTitle). Str("feed_title", mediaItem.FeedTitle).
Str("feed_imdb_id", feedItem.ImdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Item had no tmdbId on trakt") Msg("Item had no tmdbId on trakt")
continue continue
@@ -133,7 +134,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Warn(). c.log.Warn().
Err(err). Err(err).
Str("feed_title", mediaItem.FeedTitle). Str("feed_title", mediaItem.FeedTitle).
Str("feed_imdb_id", feedItem.ImdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Item was not found via pvr lookup") Msg("Item was not found via pvr lookup")
continue continue
@@ -142,7 +143,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Str("feed_title", mediaItem.FeedTitle). Str("feed_title", mediaItem.FeedTitle).
Str("feed_imdb_id", feedItem.ImdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Failed finding item via pvr lookup") Msg("Failed finding item via pvr lookup")
continue continue
@@ -160,7 +161,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
// add item to perm cache (items already in pvr) // add item to perm cache (items already in pvr)
if !c.testMode { if !c.testMode {
if err := c.cache.Put(pvrCacheBucket, cacheKey, []byte(c.name), 0); err != nil { if err := c.cache.Put(cacheBucket, cacheKey, []byte(c.name), 0); err != nil {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Msg("Failed storing item in perm cache") Msg("Failed storing item in perm cache")
@@ -215,7 +216,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
// add item to perm cache (item was added to pvr) // add item to perm cache (item was added to pvr)
if !c.testMode { if !c.testMode {
if err := c.cache.Put(pvrCacheBucket, cacheKey, []byte(c.name), 0); err != nil { if err := c.cache.Put(cacheBucket, cacheKey, []byte(c.name), 0); err != nil {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Msg("Failed storing item in perm cache") Msg("Failed storing item in perm cache")

View File

@@ -39,7 +39,7 @@ func (j *rssJob) queueItemWithPvrs(item *media.FeedItem) {
case item.TvdbId != "" && pvr.Type() == "sonarr": case item.TvdbId != "" && pvr.Type() == "sonarr":
// tvdbId is present, queue with sonarr // tvdbId is present, queue with sonarr
pvr.QueueFeedItem(item) pvr.QueueFeedItem(item)
case item.ImdbId != "" && pvr.Type() == "radarr": case (item.ImdbId != "" || item.TmdbId != "") && pvr.Type() == "radarr":
// imdbId is present, queue with radarr // imdbId is present, queue with radarr
pvr.QueueFeedItem(item) pvr.QueueFeedItem(item)
} }
@@ -84,13 +84,13 @@ func (j *rssJob) getFeed() ([]media.FeedItem, error) {
continue continue
} }
// guid seen before? // item seen before?
if cacheValue, err := j.cache.Get(j.name, i.GUID); err == nil { if cacheValue, err := j.cache.Get(j.name, i.GUID); err == nil {
if string(cacheValue) == j.cacheFiltersHash { if string(cacheValue) == j.cacheFiltersHash {
// item has been seen before and the filters have not changed // item has been seen before and the filter hash has not changed since
continue continue
} }
// item has been seen, however the filters have changed since it was last seen, re-process // item has been seen, however the filter hash has changed, re-process
} }
// process feed item attributes // process feed item attributes
@@ -106,11 +106,24 @@ func (j *rssJob) getFeed() ([]media.FeedItem, error) {
} else { } else {
b.Channel.Items[p].ImdbId = fmt.Sprintf("tt%s", a.Value) b.Channel.Items[p].ImdbId = fmt.Sprintf("tt%s", a.Value)
} }
case "tmdb", "tmdbid":
b.Channel.Items[p].TmdbId = a.Value
} }
} }
// validate item // validate item
if (b.Channel.Items[p].TvdbId == "" || b.Channel.Items[p].TvdbId == "0") && b.Channel.Items[p].ImdbId == "" { switch {
case b.Channel.Items[p].TvdbId != "" && b.Channel.Items[p].TvdbId != "0":
// tvdb id is present, allow processing
break
case b.Channel.Items[p].ImdbId != "":
// imdb id present, allow processing
break
case b.Channel.Items[p].TmdbId != "" && b.Channel.Items[p].TmdbId != "0":
// tmdb id present, allow processing
break
default:
// skip item as an expected media provider id was not present
continue continue
} }

View File

@@ -69,9 +69,15 @@ func (c *Client) getQualityProfileId(profileName string) (int, error) {
} }
func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) { func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) {
// retrieve and validate media provider data
mdp, mdi := item.GetProviderData()
if mdp == "" || mdi == "" {
return nil, fmt.Errorf("no media provider details found")
}
// prepare request // prepare request
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "series", "lookup"), reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "series", "lookup"),
url.Values{"term": []string{fmt.Sprintf("tvdb:%s", item.TvdbId)}}) url.Values{"term": []string{fmt.Sprintf("%s:%s", mdp, mdi)}})
if err != nil { if err != nil {
return nil, fmt.Errorf("generate series lookup request url: %w", err) return nil, fmt.Errorf("generate series lookup request url: %w", err)
} }
@@ -96,12 +102,12 @@ func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) {
// find series // find series
for _, s := range *b { for _, s := range *b {
if strconv.Itoa(s.TvdbId) == item.TvdbId { if strconv.Itoa(s.TvdbId) == mdi {
return &s, nil return &s, nil
} }
} }
return nil, fmt.Errorf("series lookup tvdbId: %v: %w", item.TvdbId, ErrItemNotFound) return nil, fmt.Errorf("series lookup %sId: %v: %w", mdp, mdi, ErrItemNotFound)
} }
func (c *Client) AddMediaItem(item *media.Item, opts ...nabarr.PvrOption) error { func (c *Client) AddMediaItem(item *media.Item, opts ...nabarr.PvrOption) error {

View File

@@ -34,17 +34,18 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
return return
} }
// validate item has required id(s) // retrieve and validate media provider data
if feedItem.TvdbId == "" { mdp, mdi := feedItem.GetProviderData()
if mdp == "" || mdi == "" {
continue continue
} }
// check cache / add item to cache // check cache / add item to cache
pvrCacheBucket := fmt.Sprintf("pvr_%s_%s", c.Type(), c.name) cacheBucket := fmt.Sprintf("pvr_%s_%s", c.Type(), c.name)
cacheKey := fmt.Sprintf("tvdb_%s", feedItem.TvdbId) cacheKey := fmt.Sprintf("%s_%s", mdp, mdi)
if !c.testMode { if !c.testMode {
// not running in test mode, so use cache // not running in test mode, so use cache
if cacheValue, err := c.cache.Get(pvrCacheBucket, cacheKey); err == nil { if cacheValue, err := c.cache.Get(cacheBucket, cacheKey); err == nil {
// item already exists in the cache // item already exists in the cache
switch string(cacheValue) { switch string(cacheValue) {
case c.name: case c.name:
@@ -57,7 +58,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
} }
// insert temp cache entry // insert temp cache entry
if err := c.cache.Put(pvrCacheBucket, cacheKey, []byte(c.cacheFiltersHash), c.cacheTempDuration); err != nil { if err := c.cache.Put(cacheBucket, cacheKey, []byte(c.cacheFiltersHash), c.cacheTempDuration); err != nil {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Msg("Failed storing item in temp cache") Msg("Failed storing item in temp cache")
@@ -71,7 +72,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Debug(). c.log.Debug().
Err(err). Err(err).
Str("feed_title", feedItem.Title). Str("feed_title", feedItem.Title).
Str("feed_tvdb_id", feedItem.TvdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Item was not found on trakt") Msg("Item was not found on trakt")
continue continue
@@ -80,7 +81,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Str("feed_title", feedItem.Title). Str("feed_title", feedItem.Title).
Str("feed_tvdb_id", feedItem.TvdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Failed finding item on trakt") Msg("Failed finding item on trakt")
continue continue
@@ -125,7 +126,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Warn(). c.log.Warn().
Err(err). Err(err).
Str("feed_title", mediaItem.FeedTitle). Str("feed_title", mediaItem.FeedTitle).
Str("feed_tvdb_id", feedItem.TvdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Item was not found via pvr lookup") Msg("Item was not found via pvr lookup")
continue continue
@@ -134,7 +135,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Str("feed_title", mediaItem.FeedTitle). Str("feed_title", mediaItem.FeedTitle).
Str("feed_tvdb_id", feedItem.TvdbId). Str(fmt.Sprintf("feed_%s_id", mdp), mdi).
Str("feed_name", feedItem.Feed). Str("feed_name", feedItem.Feed).
Msg("Failed finding item via pvr lookup") Msg("Failed finding item via pvr lookup")
continue continue
@@ -151,7 +152,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
// add item to perm cache (items already in pvr) // add item to perm cache (items already in pvr)
if !c.testMode { if !c.testMode {
if err := c.cache.Put(pvrCacheBucket, cacheKey, []byte(c.name), 0); err != nil { if err := c.cache.Put(cacheBucket, cacheKey, []byte(c.name), 0); err != nil {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Msg("Failed storing item in perm cache") Msg("Failed storing item in perm cache")
@@ -221,7 +222,7 @@ func (c *Client) queueProcessor(tail state.ShutdownTail) {
// add item to perm cache (item was added to pvr) // add item to perm cache (item was added to pvr)
if !c.testMode { if !c.testMode {
if err := c.cache.Put(pvrCacheBucket, cacheKey, []byte(c.name), 0); err != nil { if err := c.cache.Put(cacheBucket, cacheKey, []byte(c.name), 0); err != nil {
c.log.Error(). c.log.Error().
Err(err). Err(err).
Msg("Failed storing item in perm cache") Msg("Failed storing item in perm cache")