0.2.82
This commit is contained in:
@@ -83,7 +83,7 @@ func (s *Server) handleHome(w http.ResponseWriter, r *http.Request, sess store.S
|
||||
// four cards. See heroRevision.
|
||||
heroRev := heroRevision(s.currentHeroPolicy(ctx), sess.EmbyUserID, now, s.heroLocation())
|
||||
key := cache.UserKey(
|
||||
sess.EmbyUserID,
|
||||
viewerKeyOf(ctx, sess),
|
||||
"home:v4:"+itoa(limit)+":s"+strconv.FormatBool(sonarrSchedule)+
|
||||
":r"+strconv.FormatBool(radarrSchedule)+":h"+strconv.FormatBool(hero)+
|
||||
":hr"+heroRev+":d"+sess.DeviceID,
|
||||
@@ -135,7 +135,19 @@ func (s *Server) handleHome(w http.ResponseWriter, r *http.Request, sess store.S
|
||||
}()
|
||||
}
|
||||
|
||||
// The three rows that are answers about a *person* rather than about the library.
|
||||
// For the account's own viewer they are Emby's, exactly as they always were; for a
|
||||
// shadow viewer they are built from that viewer's own state, and Emby is asked only to
|
||||
// describe the titles. The fan-out, the failure counting and the merge below are
|
||||
// unchanged either way — this is a substitution of one fetch for another, not a second
|
||||
// code path through the launcher.
|
||||
viewer := viewerOf(ctx, sess)
|
||||
shadow := !viewer.IsMain() && s.store != nil
|
||||
|
||||
run("resume", &out.ContinueWatching, func(ctx context.Context) (*emby.ItemsResult, error) {
|
||||
if shadow {
|
||||
return s.viewerContinueRow(ctx, cred, viewer.ID, limit)
|
||||
}
|
||||
return s.emby.ResumeItems(ctx, cred, rowParams(url.Values{
|
||||
"Recursive": {"true"},
|
||||
"MediaTypes": {"Video"},
|
||||
@@ -143,6 +155,9 @@ func (s *Server) handleHome(w http.ResponseWriter, r *http.Request, sess store.S
|
||||
}, fieldsContinue))
|
||||
})
|
||||
run("favourites", &out.Favorites, func(ctx context.Context) (*emby.ItemsResult, error) {
|
||||
if shadow {
|
||||
return s.viewerFavouritesRow(ctx, cred, viewer.ID, limit)
|
||||
}
|
||||
return s.emby.Items(ctx, cred, rowParams(url.Values{
|
||||
"Filters": {"IsFavorite"},
|
||||
"IncludeItemTypes": {"Movie,Series"},
|
||||
@@ -153,6 +168,9 @@ func (s *Server) handleHome(w http.ResponseWriter, r *http.Request, sess store.S
|
||||
}, fieldsRow))
|
||||
})
|
||||
run("nextup", &out.NextUp, func(ctx context.Context) (*emby.ItemsResult, error) {
|
||||
if shadow {
|
||||
return s.viewerNextUpRow(ctx, cred, viewer.ID, limit)
|
||||
}
|
||||
return s.emby.NextUp(ctx, cred, rowParams(url.Values{
|
||||
"Limit": {itoa(limit)},
|
||||
}, fieldsContinue))
|
||||
@@ -163,7 +181,16 @@ func (s *Server) handleHome(w http.ResponseWriter, r *http.Request, sess store.S
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
played, err := s.recentlyPlayedSeries(timing.WithLabel(ctx, "emby.recent"), cred)
|
||||
// What orders the two halves of the merge. For a shadow viewer it is one grouped
|
||||
// query over their own state rather than a lookback over the account's plays —
|
||||
// the same question, asked of the system that holds the answer.
|
||||
var played map[string]time.Time
|
||||
var err error
|
||||
if shadow {
|
||||
played, err = s.store.ViewerWatchedSeries(ctx, viewer.ID, continuePlayLookback)
|
||||
} else {
|
||||
played, err = s.recentlyPlayedSeries(timing.WithLabel(ctx, "emby.recent"), cred)
|
||||
}
|
||||
if err != nil {
|
||||
s.loggerFor(ctx).Warn("recently played lookup failed", "error", err)
|
||||
return
|
||||
@@ -578,7 +605,7 @@ func (s *Server) handleSearch(w http.ResponseWriter, r *http.Request, sess store
|
||||
return
|
||||
}
|
||||
limit := queryInt(r, "limit", 40, 100)
|
||||
key := cache.UserKey(sess.EmbyUserID, "search:"+itoa(limit)+":"+term+":d"+sess.DeviceID)
|
||||
key := cache.UserKey(viewerKeyOf(ctx, sess), "search:"+itoa(limit)+":"+term+":d"+sess.DeviceID)
|
||||
|
||||
// Every search the tab performs is recorded here, before the cache is consulted, so a
|
||||
// query answered from Redis counts the same as one that reached Emby. The client also
|
||||
@@ -606,7 +633,7 @@ func (s *Server) handleSearch(w http.ResponseWriter, r *http.Request, sess store
|
||||
return
|
||||
}
|
||||
items := s.personalizeSearch(ctx, sess, term, result.Items, limit)
|
||||
s.decorateItemRatings(ctx, items)
|
||||
s.decorateItems(ctx, items)
|
||||
// Instant search fires a request per keystroke past the second character, so this is
|
||||
// DEBUG: it is the record of what somebody was looking for when nothing was found,
|
||||
// not something to carry in the normal log.
|
||||
|
||||
Reference in New Issue
Block a user