mirror of
https://github.com/FJurmanovic/sugarr.git
synced 2026-11-11 15:51:09 +00:00
134 lines
3.6 KiB
Go
134 lines
3.6 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/fjurmanovic/sugarr/internal/model"
|
|
"github.com/fjurmanovic/sugarr/internal/utl/configs"
|
|
)
|
|
|
|
type JellyfinClient struct {
|
|
url string
|
|
apiKey string
|
|
userID string
|
|
http *http.Client
|
|
}
|
|
|
|
func NewJellyfinClient(cfg *configs.Config) *JellyfinClient {
|
|
return &JellyfinClient{
|
|
url: cfg.JellyfinURL,
|
|
apiKey: cfg.JellyfinAPIKey,
|
|
userID: cfg.JellyfinUserID,
|
|
http: &http.Client{},
|
|
}
|
|
}
|
|
|
|
type jellyfinItemsResponse struct {
|
|
Items []jellyfinItem `json:"Items"`
|
|
}
|
|
|
|
type jellyfinItem struct {
|
|
Name string `json:"Name"`
|
|
ProductionYear int `json:"ProductionYear"`
|
|
ProviderIds map[string]string `json:"ProviderIds"`
|
|
Genres []string `json:"Genres"`
|
|
CommunityRating float64 `json:"CommunityRating"`
|
|
UserData jellyfinUserData `json:"UserData"`
|
|
}
|
|
|
|
type jellyfinUserData struct {
|
|
IsFavorite bool `json:"IsFavorite"`
|
|
PlayCount int `json:"PlayCount"`
|
|
}
|
|
|
|
func (c *JellyfinClient) get(path string, params url.Values) (*jellyfinItemsResponse, error) {
|
|
u := fmt.Sprintf("%s%s?%s", c.url, path, params.Encode())
|
|
req, err := http.NewRequest(http.MethodGet, u, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Authorization", fmt.Sprintf("MediaBrowser Token=%q", c.apiKey))
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
resp, err := c.http.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("jellyfin request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("jellyfin returned status %d for %s", resp.StatusCode, path)
|
|
}
|
|
|
|
var result jellyfinItemsResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
return nil, fmt.Errorf("decoding jellyfin response: %w", err)
|
|
}
|
|
return &result, nil
|
|
}
|
|
|
|
func toMovies(items []jellyfinItem) []model.Movie {
|
|
movies := make([]model.Movie, 0, len(items))
|
|
for _, item := range items {
|
|
movies = append(movies, model.Movie{
|
|
Name: item.Name,
|
|
Year: item.ProductionYear,
|
|
IMDbID: item.ProviderIds["Imdb"],
|
|
TMDbID: item.ProviderIds["Tmdb"],
|
|
Genres: item.Genres,
|
|
CommunityRating: item.CommunityRating,
|
|
IsFavorite: item.UserData.IsFavorite,
|
|
PlayCount: item.UserData.PlayCount,
|
|
})
|
|
}
|
|
return movies
|
|
}
|
|
|
|
func (c *JellyfinClient) GetFavoriteMovies() ([]model.Movie, error) {
|
|
params := url.Values{
|
|
"IncludeItemTypes": {"Movie"},
|
|
"Recursive": {"true"},
|
|
"IsFavorite": {"true"},
|
|
"Fields": {"ProviderIds,Genres,CommunityRating,UserData"},
|
|
}
|
|
resp, err := c.get(fmt.Sprintf("/Users/%s/Items", c.userID), params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toMovies(resp.Items), nil
|
|
}
|
|
|
|
func (c *JellyfinClient) GetRecentlyWatched() ([]model.Movie, error) {
|
|
params := url.Values{
|
|
"IncludeItemTypes": {"Movie"},
|
|
"Recursive": {"true"},
|
|
"Filters": {"IsPlayed"},
|
|
"SortBy": {"DatePlayed"},
|
|
"SortOrder": {"Descending"},
|
|
"Limit": {"50"},
|
|
"Fields": {"ProviderIds,Genres,CommunityRating,UserData"},
|
|
}
|
|
resp, err := c.get(fmt.Sprintf("/Users/%s/Items", c.userID), params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toMovies(resp.Items), nil
|
|
}
|
|
|
|
func (c *JellyfinClient) GetAllMovies() ([]model.Movie, error) {
|
|
params := url.Values{
|
|
"IncludeItemTypes": {"Movie"},
|
|
"Recursive": {"true"},
|
|
"Fields": {"ProviderIds"},
|
|
"Limit": {"10000"},
|
|
}
|
|
resp, err := c.get(fmt.Sprintf("/Users/%s/Items", c.userID), params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toMovies(resp.Items), nil
|
|
}
|