wip: content: returning watched along with tv response

This commit is contained in:
IRHM
2025-02-18 21:40:24 +00:00
parent b70ae5d3c7
commit 18c0882650
3 changed files with 58 additions and 6 deletions
+13
View File
@@ -22,6 +22,7 @@ const (
SHOW_EPISODE ContentType = "tv_episode"
)
// TODO This should probably be replaced at some point (direct use of https://github.com/patrickmn/go-cache or with https://github.com/eko/gocache ?).
var ContentStore = persistence.NewInMemoryStore(time.Hour * 24)
// For storing cached content, so we can serve the basic local data for watched list to work
@@ -356,7 +357,16 @@ func movieCredits(id string) (TMDBContentCredits, error) {
}
func tvDetails(db *gorm.DB, id string, country string, rParams map[string]string) (TMDBShowDetails, error) {
var cacheKey = "contentstore-tvDetails-" + id + "-" + country
resp := new(TMDBShowDetails)
if err := ContentStore.Get(cacheKey, &resp); err != nil {
if err != persistence.ErrCacheMiss {
slog.Error("tvDetails: Cache failed for some reason", "error", err)
}
} else {
slog.Debug("tvDetails: Returning cache.")
return *resp, nil
}
err := tmdbRequest("/tv/"+id, rParams, &resp)
if err != nil {
slog.Error("Failed to complete tv details request!", "error", err.Error())
@@ -364,6 +374,9 @@ func tvDetails(db *gorm.DB, id string, country string, rParams map[string]string
}
transformProviders(&resp.WatchProviders, country)
go cacheContentTv(db, *resp, true)
if err := ContentStore.Set(cacheKey, resp, time.Hour*24); err != nil {
slog.Error("tvDetails: Failed to set cache!", "error", err)
}
return *resp, nil
}
+31 -6
View File
@@ -222,18 +222,43 @@ func (b *BaseRouter) addContentRoutes() {
}))
// Get tv details (for tv page)
content.GET("/tv/:id", WhereaboutsRequired(), cache.CachePage(b.ms, exp, func(c *gin.Context) {
if c.Param("id") == "" {
c.Status(400)
content.GET("/tv/:id", WhereaboutsRequired(), func(c *gin.Context) {
tmdbIdStr := c.Param("id")
if tmdbIdStr == "" {
c.JSON(http.StatusBadRequest, ErrorResponse{Error: "must provide an 'id' parameter"})
return
}
content, err := tvDetails(b.db, c.Param("id"), c.MustGet("userCountry").(string), map[string]string{"append_to_response": "videos,watch/providers,similar,external_ids,keywords"})
tmdbId, err := strconv.ParseUint(tmdbIdStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, ErrorResponse{Error: "'id' parameter must be a number"})
return
}
userId := c.MustGet("userId").(uint)
resp := DataWithWatched[TMDBShowDetails]{}
// 1. Get details
content, err := tvDetails(
b.db,
c.Param("id"),
c.MustGet("userCountry").(string),
map[string]string{
"append_to_response": "videos,watch/providers,similar,external_ids,keywords",
},
)
if err != nil {
c.JSON(http.StatusBadRequest, ErrorResponse{Error: err.Error()})
return
}
c.JSON(http.StatusOK, content)
}))
resp.Data = &content
// 2. append watched list entry if exists
if watchedEntry, err := getWatchedItemByTmdbId(b.db, userId, uint(tmdbId), SHOW); err != nil {
if err != gorm.ErrRecordNotFound {
resp.FailedToGetWatched = true
}
} else {
resp.Watched = &watchedEntry
}
c.JSON(http.StatusOK, resp)
})
// Get tv cast
content.GET("/tv/:id/credits", cache.CachePage(b.ms, exp, func(c *gin.Context) {
+14
View File
@@ -75,6 +75,20 @@ type WatchedRemoveResponse struct {
NewActivity Activity `json:"newActivity"`
}
// Generic for returning data of (T)ype along with any
// related watched entry data.
type DataWithWatched[T any] struct {
// The related watched entry.
Watched *Watched `json:"watched,omitempty"`
// If we failed to get the watched entry,
// set this to true, so the frontend can
// notify the user of why there is possibly
// missing watched list data.
FailedToGetWatched bool `json:"failedToGetWatched,omitempty"`
// The data going along with response.
Data *T `json:"data,omitempty"`
}
// Get entire watched list
func getWatched(db *gorm.DB, userId uint) []Watched {
watched := new([]Watched)