package main import ( "bytes" "crypto/tls" "encoding/json" "fmt" "io" "net/http" ) type CurrentlyPlayingDetails struct { CurrentPlayingTitle string `json:"currentPlayingTitle"` IpAddress string `json:"ipAddress"` Platform string `json:"platform"` Product string `json:"product"` Title string `json:"title"` State string `json:"state"` } type plexStats struct { CurrentSessions float64 `json:"currentSessions"` NumMovies float64 `json:"numMovies"` NumTV float64 `json:"numTV"` NumTranscodes float64 `json:"numTranscodes"` NumAllSessions float64 `json:"numAllSessions"` CurrentlyPlayingDetails CurrentlyPlayingDetails `json:"currentlyPlayingDetails"` } type PlexClient struct { baseUrl string client *http.Client plexToken string } func setupClient(settings *serverSettings) PlexClient { transCfg := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } return PlexClient{ baseUrl: settings.plexAddr, client: &http.Client{Transport: transCfg}, plexToken: settings.plexToken, } } // sendRequest sends a request and resturns response (always assuming a get request) func (pc *PlexClient) sendRequest(url string, body []byte) (result []byte) { fullUrl := pc.baseUrl + url req, err := http.NewRequest("GET", fullUrl, bytes.NewBuffer(body)) if err != nil { fmt.Println("Error creating new request", err) return } req.Header.Add("Accept", "application/json") q := req.URL.Query() q.Add("X-Plex-Token", pc.plexToken) req.URL.RawQuery = q.Encode() res, err := pc.client.Do(req) if err != nil { fmt.Println("Error sending request", err) return } defer res.Body.Close() resBody, err := io.ReadAll(res.Body) if err != nil { fmt.Println("Unable to read response body: ", err) return } return resBody } func (pc *PlexClient) getActiveSessions() *ActiveSessions { result := pc.sendRequest("/status/sessions", nil) currentActiveSessions := ActiveSessions{} err := json.Unmarshal(result, ¤tActiveSessions) if err != nil { fmt.Println("Error unmarshalling current active sessions: ", err) } return ¤tActiveSessions } func (pc *PlexClient) getNumMovies() *RawPlexModel { result := pc.sendRequest("/library/sections/3/all", nil) //Hard code library ID for now TODO: Grab from library/sections call libraryAll := RawPlexModel{} err := json.Unmarshal(result, &libraryAll) if err != nil { fmt.Println("Error unmarshalling num movies: ", err) } return &libraryAll } func (pc *PlexClient) getNumTV() *ActiveSessions { result := pc.sendRequest("/library/sections/2/all", nil) //Hard code library ID for now TODO: Grab from library/sections call libraryAll := ActiveSessions{} err := json.Unmarshal(result, &libraryAll) if err != nil { fmt.Println("Error unmarshalling num tv: ", err) } return &libraryAll } func (pc *PlexClient) getNumTranscodes() *RawPlexModel { result := pc.sendRequest("/transcode/sessions", nil) transcodesAll := RawPlexModel{} err := json.Unmarshal(result, &transcodesAll) if err != nil { fmt.Println("Error unmarshalling num transcodes: ", err) } return &transcodesAll } // getServerHistory gets the entire history of plays on the plex server func (pc *PlexClient) getServerHistory() *RawPlexModel { result := pc.sendRequest("/status/sessions/history/all", nil) sessionsAll := RawPlexModel{} err := json.Unmarshal(result, &sessionsAll) if err != nil { fmt.Println("Error unmarshalling session server history: ", err) } return &sessionsAll } func (pc *PlexClient) gatherAllStats() *plexStats { allStats := plexStats{} sessionsData := pc.getActiveSessions() libraryDetails := pc.getNumMovies() tvshowDetails := pc.getNumTV() transcodeDetails := pc.getNumTranscodes() allSessionsData := pc.getServerHistory() allStats.CurrentSessions = float64(sessionsData.MediaContainer.Size) allStats.NumMovies = float64(libraryDetails.MediaContainer.Size) allStats.NumTV = float64(tvshowDetails.MediaContainer.Size) allStats.NumTranscodes = float64(transcodeDetails.MediaContainer.Size) allStats.NumAllSessions = float64(allSessionsData.MediaContainer.Size) if len(sessionsData.MediaContainer.Metadata) > 0 { allStats.CurrentlyPlayingDetails.CurrentPlayingTitle = sessionsData.MediaContainer.Metadata[0].Title allStats.CurrentlyPlayingDetails.IpAddress = sessionsData.MediaContainer.Metadata[0].Player.Address allStats.CurrentlyPlayingDetails.Platform = sessionsData.MediaContainer.Metadata[0].Player.Platform allStats.CurrentlyPlayingDetails.Product = sessionsData.MediaContainer.Metadata[0].Player.Product allStats.CurrentlyPlayingDetails.State = sessionsData.MediaContainer.Metadata[0].Player.State allStats.CurrentlyPlayingDetails.Title = sessionsData.MediaContainer.Metadata[0].Player.Title } return &allStats }