diff --git a/README.md b/README.md index 3bc02f5..2535bc4 100644 --- a/README.md +++ b/README.md @@ -28,16 +28,13 @@ env CGO_ENABLED=0 go install -trimpath -ldflags="-s -w" github.com/RoyXiang/plex 1. Configure environment variables in your preferred way - `PLEX_BASEURL` (Required, e.g. `http://127.0.0.1:32400`) - - `PLEX_TOKEN` (Optional, if you need it, see [here](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/)) - * It is used to receive notifications from Plex Media Server - * Notifications are used to flush the cache of metadata - `REDIS_URL` (Optional, e.g. `redis://127.0.0.1:6379`) * If you need a cache layer, set a value for it - * `PLEX_TOKEN` is required - `PLAXT_URL` (Optional, e.g. `https://plaxt.astandke.com/api?id=generate-your-own-silly`) * `PLEX_TOKEN` is required * Set it if you run an instance of [Plaxt](https://github.com/XanderStrike/goplaxt) * Or, you can set it to [the official one](https://plaxt.astandke.com/) + - `PLEX_TOKEN` (Optional, if you need it, see [here](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/)) - `REDIRECT_WEB_APP` (Optional, default: `true`) - `DISABLE_TRANSCODE` (Optional, default: `true`) - `NO_REQUEST_LOGS` (Optional, default: `false`) diff --git a/handler/const.go b/handler/const.go index e6d8976..e4b008c 100644 --- a/handler/const.go +++ b/handler/const.go @@ -22,14 +22,12 @@ const ( headerRealIP = "X-Real-IP" headerVary = "Vary" - cachePrefixDynamic = "dynamic" - cachePrefixMetadata = "metadata" - cachePrefixStatic = "static" - cachePrefixPlex = "plex" - - cacheTtlDynamic = time.Second * 5 - cacheTtlMetadata = time.Hour * 24 - cacheTtlStatic = time.Hour + cachePrefixDynamic = "dynamic" + cachePrefixStatic = "static" + cachePrefixPlex = "plex" + + cacheTtlDynamic = time.Second * 5 + cacheTtlStatic = time.Hour contentTypeAny = "*/*" contentTypeXml = "xml" diff --git a/handler/main.go b/handler/main.go index ceb046f..58d705f 100644 --- a/handler/main.go +++ b/handler/main.go @@ -4,7 +4,6 @@ import ( "log" "net/http" "os" - "sync" "github.com/go-chi/chi/v5/middleware" "github.com/go-redis/redis/v8" @@ -16,8 +15,6 @@ var ( redisClient *redis.Client emptyStruct = struct{}{} - - mu sync.RWMutex ) func init() { @@ -34,7 +31,7 @@ func init() { } redisUrl := os.Getenv("REDIS_URL") - if redisUrl != "" && plexClient.IsTokenSet() { + if redisUrl != "" { options, err := redis.ParseURL(redisUrl) if err == nil { redisClient = redis.NewClient(options) @@ -62,12 +59,6 @@ func NewRouter() http.Handler { staticRouter.Path("/library/metadata/{key}/thumb/{id}").Handler(plexClient) staticRouter.Path("/photo/:/transcode").Handler(plexClient) - metadataRouter := r.Methods(http.MethodGet).PathPrefix("/library").Subrouter() - metadataRouter.Use(metadataMiddleware) - metadataRouter.PathPrefix("/collections/").Handler(plexClient) - metadataRouter.PathPrefix("/metadata/").Handler(plexClient) - metadataRouter.PathPrefix("/sections/").Handler(plexClient) - dynamicRouter := r.Methods(http.MethodGet).Subrouter() dynamicRouter.Use(dynamicMiddleware) dynamicRouter.PathPrefix("/").Handler(plexClient) diff --git a/handler/middleware.go b/handler/middleware.go index bf6b378..ef216c0 100644 --- a/handler/middleware.go +++ b/handler/middleware.go @@ -114,17 +114,6 @@ func staticMiddleware(next http.Handler) http.Handler { }) } -func metadataMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithValue(r.Context(), cacheInfoCtxKey, &cacheInfo{ - Prefix: cachePrefixMetadata, - Ttl: cacheTtlMetadata, - }) - r = r.WithContext(ctx) - cacheMiddleware(next).ServeHTTP(w, r) - }) -} - func dynamicMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), cacheInfoCtxKey, &cacheInfo{ @@ -141,10 +130,6 @@ func cacheMiddleware(next http.Handler) http.Handler { var cacheKey string ctx := context.Background() info := r.Context().Value(cacheInfoCtxKey).(*cacheInfo) - if info.Prefix == cachePrefixMetadata { - mu.RLock() - defer mu.RUnlock() - } defer func() { if cacheKey == "" { @@ -190,7 +175,7 @@ func cacheMiddleware(next http.Handler) http.Handler { switch info.Prefix { case cachePrefixStatic: break - case cachePrefixDynamic, cachePrefixMetadata: + case cachePrefixDynamic: user := r.Context().Value(userCtxKey) if user != nil { params.Set(headerUserId, strconv.Itoa(user.(*plexUser).Id)) diff --git a/handler/plex.go b/handler/plex.go index 0062dd6..79fa0c3 100644 --- a/handler/plex.go +++ b/handler/plex.go @@ -1,7 +1,6 @@ package handler import ( - "bufio" "bytes" "context" "encoding/json" @@ -140,11 +139,6 @@ func (c *PlexClient) ServeHTTP(w http.ResponseWriter, r *http.Request) { // If it is an authorized request if user := r.Context().Value(userCtxKey); user != nil { switch path { - case "/:/scrobble", "/:/unscrobble": - ratingKey := r.URL.Query().Get("key") - if ratingKey != "" { - go clearCachedMetadata(ratingKey, user.(*plexUser).Id) - } case "/:/timeline": go c.syncTimelineWithPlaxt(r, user.(*plexUser)) case "/video/:/transcode/universal/decision": @@ -360,7 +354,6 @@ func (c *PlexClient) syncTimelineWithPlaxt(r *http.Request, user *plexUser) { session.status = sessionPaused case webhookEventStop, webhookEventScrobble: session.status = sessionStopped - go clearCachedMetadata(ratingKey, user.Id) } session.lastEvent = event session.progress = progress @@ -519,55 +512,12 @@ func (c *PlexClient) getMetadata(ratingKey string) *plex.MediaMetadata { c.mu.RLock() defer c.mu.RUnlock() - user := c.GetUser(c.client.Token) - if user == nil { - return nil - } - - path := fmt.Sprintf("/library/metadata/%s", ratingKey) - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s%s", c.client.URL, path), nil) - if err != nil { - return nil - } - req.Header.Set(headerToken, c.client.Token) - req.Header.Set(headerAccept, "application/json") - - var resp *http.Response - cacheKey := fmt.Sprintf("%s:%s?%s=%s&%s=%d", cachePrefixMetadata, path, headerAccept, "json", headerUserId, user.Id) - isFromCache := false - if redisClient != nil { - b, err := redisClient.Get(context.Background(), cacheKey).Bytes() - if err == nil { - reader := bufio.NewReader(bytes.NewReader(b)) - resp, _ = http.ReadResponse(reader, req) - isFromCache = true - } - } - if resp == nil { - resp, err = c.client.HTTPClient.Do(req) - if err != nil { - common.GetLogger().Printf("Failed to parse metadata of item %s: %s", ratingKey, err.Error()) - return nil - } - } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(resp.Body) - - if resp.StatusCode != http.StatusOK { - common.GetLogger().Printf("Failed to get metadata of item %s (status: %d)", ratingKey, resp.StatusCode) - return nil - } else if !isFromCache { - writeToCache(cacheKey, resp, cacheTtlMetadata) - } - - var result plex.MediaMetadata - err = json.NewDecoder(resp.Body).Decode(&result) + metadata, err := c.client.GetMetadata(ratingKey) if err != nil { common.GetLogger().Printf("Failed to parse metadata of item %s: %s", ratingKey, err.Error()) return nil } - return &result + return &metadata } func (c *PlexClient) disableTranscoding(r *http.Request) *http.Request { diff --git a/handler/utils.go b/handler/utils.go index 0832ddb..8b64e40 100644 --- a/handler/utils.go +++ b/handler/utils.go @@ -2,7 +2,6 @@ package handler import ( "context" - "fmt" "net/http" "net/http/httputil" "net/url" @@ -124,27 +123,3 @@ func writeToCache(key string, resp *http.Response, ttl time.Duration) { } redisClient.Set(context.Background(), key, b, ttl) } - -func clearCachedMetadata(ratingKey string, userId int) { - if redisClient == nil { - return - } - - mu.Lock() - defer mu.Unlock() - - pattern := cachePrefixMetadata + ":" - if ratingKey != "" { - pattern += fmt.Sprintf("/library/metadata/%s", ratingKey) - } - if userId > 0 { - pattern += fmt.Sprintf("*%s=%d", headerUserId, userId) - } - pattern += "*" - - ctx := context.Background() - keys := redisClient.Keys(ctx, pattern).Val() - if len(keys) > 0 { - redisClient.Del(ctx, keys...).Val() - } -} diff --git a/handler/websocket.go b/handler/websocket.go deleted file mode 100644 index 2611b27..0000000 --- a/handler/websocket.go +++ /dev/null @@ -1,74 +0,0 @@ -package handler - -import ( - "os" - "sync" - "time" - - "github.com/RoyXiang/plexproxy/common" - "github.com/gorilla/websocket" - "github.com/jrudio/go-plex-client" -) - -func ListenToWebsocket(interrupt <-chan os.Signal) { - if !plexClient.IsTokenSet() { - <-interrupt - return - } - events := plex.NewNotificationEvents() - events.OnActivity(wsOnActivity) - - var wsWaitGroup sync.WaitGroup - logger := common.GetLogger() - closeWebsocket := make(chan os.Signal, 1) - reconnect := make(chan struct{}, 1) - reconnect <- struct{}{} - logger.Println("Connecting to Plex server through websocket...") - -socket: - for { - select { - case <-reconnect: - // wait for Plex server until it is online - if !plexClient.TestReachability() { - time.Sleep(time.Second) - reconnect <- struct{}{} - break - } - - wsWaitGroup.Add(1) - plexClient.SubscribeToNotifications(events, closeWebsocket, func(err error) { - switch err.(type) { - case *websocket.CloseError: - wsWaitGroup.Done() - } - }) - logger.Println("Receiving notifications from Plex server through websocket...") - go func() { - wsWaitGroup.Wait() - logger.Println("Websocket closed unexpectedly, reconnecting...") - time.Sleep(time.Second) - reconnect <- struct{}{} - }() - case signal := <-interrupt: - closeWebsocket <- signal - break socket - } - } -} - -func wsOnActivity(n plex.NotificationContainer) { - isMetadataChanged := false - for _, a := range n.ActivityNotification { - if a.Event != "ended" { - continue - } - switch a.Activity.Type { - case "library.update.section", "library.refresh.items", "media.generate.intros": - isMetadataChanged = true - } - } - if isMetadataChanged { - clearCachedMetadata("", 0) - } -} diff --git a/main.go b/main.go index 4104bf5..1bad4cb 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ func main() { c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - handler.ListenToWebsocket(c) + <-c ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) defer cancel()