Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 41 additions & 43 deletions src/client/jellyfin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ import (
)

type Paths []struct {
Name string `json:"Name"`
Locations []string `json:"Locations"`
CollectionType string `json:"CollectionType"`
ItemID string `json:"ItemId"`
RefreshStatus string `json:"RefreshStatus"`
Name string `json:"Name"`
Locations []string `json:"Locations"`
CollectionType string `json:"CollectionType"`
ItemID string `json:"ItemId"`
RefreshStatus string `json:"RefreshStatus"`
}

type Search struct {
SearchHints []SearchHints `json:"SearchHints"`
TotalRecordCount int `json:"TotalRecordCount"`
}
type SearchHints struct {
ItemID string `json:"ItemId"`
ID string `json:"Id"`
Name string `json:"Name"`
Album string `json:"Album"`
AlbumID string `json:"AlbumId"`
AlbumArtist string `json:"AlbumArtist"`
ItemID string `json:"ItemId"`
ID string `json:"Id"`
Name string `json:"Name"`
Album string `json:"Album"`
AlbumID string `json:"AlbumId"`
AlbumArtist string `json:"AlbumArtist"`
}

type Audios struct {
Expand All @@ -41,27 +41,27 @@ type Audios struct {
}

type Items struct {
Name string `json:"Name"`
ServerID string `json:"ServerId"`
ID string `json:"Id"`
Path string `json:"Path"`
Album string `json:"Album,omitempty"`
AlbumArtist string `json:"AlbumArtist,omitempty"`
Name string `json:"Name"`
ServerID string `json:"ServerId"`
ID string `json:"Id"`
Path string `json:"Path"`
Album string `json:"Album,omitempty"`
AlbumArtist string `json:"AlbumArtist,omitempty"`
}

type JFPlaylist struct {
ID string `json:"Id"`
}

type Jellyfin struct {
LibraryID string
LibraryID string
HttpClient *util.HttpClient
Cfg config.ClientConfig
Cfg config.ClientConfig
}

func NewJellyfin(cfg config.ClientConfig, httpClient *util.HttpClient) *Jellyfin {
return &Jellyfin{Cfg: cfg,
HttpClient: httpClient}
HttpClient: httpClient}
}

func (c *Jellyfin) AddHeader() error {
Expand All @@ -70,8 +70,8 @@ func (c *Jellyfin) AddHeader() error {
}

if c.Cfg.Creds.APIKey != "" {
c.Cfg.Creds.Headers["Authorization"] = fmt.Sprintf("MediaBrowser Token=%s, Client=%s", c.Cfg.Creds.APIKey, c.Cfg.ClientID)
return nil
c.Cfg.Creds.Headers["Authorization"] = fmt.Sprintf("MediaBrowser Token=%s, Client=%s", c.Cfg.Creds.APIKey, c.Cfg.ClientID)
return nil
}
return fmt.Errorf("API_KEY not set")
}
Expand All @@ -82,7 +82,7 @@ func (c *Jellyfin) GetAuth() error {

func (c *Jellyfin) GetLibrary() error {
reqParam := "/Library/VirtualFolders"

body, err := c.HttpClient.MakeRequest("GET", c.Cfg.URL+reqParam, nil, c.Cfg.Creds.Headers)
if err != nil {
return err
Expand All @@ -92,7 +92,7 @@ func (c *Jellyfin) GetLibrary() error {
if err = util.ParseResp(body, &paths); err != nil {
return err
}

for _, path := range paths {
if path.Name == c.Cfg.LibraryName {
c.LibraryID = path.ItemID
Expand Down Expand Up @@ -120,7 +120,7 @@ func (c *Jellyfin) AddLibrary() error {
}

func (c *Jellyfin) RefreshLibrary() error {
reqParam := fmt.Sprintf("/Items/%s/Refresh", c.LibraryID)
reqParam := fmt.Sprintf("/Items/%s/Refresh?metadataRefreshMode=FullRefresh", c.LibraryID)

if _, err := c.HttpClient.MakeRequest("POST", c.Cfg.URL+reqParam, nil, c.Cfg.Creds.Headers); err != nil {
return err
Expand All @@ -129,37 +129,35 @@ func (c *Jellyfin) RefreshLibrary() error {
}

func (c *Jellyfin) SearchSongs(tracks []*models.Track) error {
queryParams := fmt.Sprintf("/Items?parentId=%s&fields=Path&mediaTypes=Audio&sortBy=DateCreated&sortOrder=Descending&limit=200", c.LibraryID) // limit 200 recently added audio tracks to search from

body, err := c.HttpClient.MakeRequest("GET", c.Cfg.URL+queryParams, nil, c.Cfg.Creds.Headers)
if err != nil {
return fmt.Errorf("request failed to get songs from %s library: %s", c.Cfg.LibraryName, err.Error())
}
for _, track := range tracks {
queryParams := fmt.Sprintf("/Items?parentId=%s&fields=Path&mediaTypes=Audio&searchTerm=%s&recursive=true", c.LibraryID, url.QueryEscape(track.CleanTitle))

var results Audios
if err = util.ParseResp(body, &results); err != nil {
return err
}
body, err := c.HttpClient.MakeRequest("GET", c.Cfg.URL+queryParams, nil, c.Cfg.Creds.Headers)
if err != nil {
return fmt.Errorf("request failed to get songs from %s library: %s", c.Cfg.LibraryName, err.Error())
}

for _, track := range tracks {
var results Audios
if err = util.ParseResp(body, &results); err != nil {
return err
}

for _, item := range results.Items {
if strings.Contains(item.Path, track.File) {
if track.MainArtist == item.AlbumArtist && strings.Contains(item.Path, track.CleanTitle) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for requesting changes 2 times, this completely slipped my mind. I think strings.Contains(item.Path, track.CleanTitle) can be replaced with item.Name == track.CleanTitle.

Path isn't needed at all anymore (since we're not comparing it with the track.File that was done previously). CleanTitle and Path can differ from each other (special symbols can be in CleanTitle, but are removed in Path), so using item.Name should have a higher match rate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i somehow missed this so opened #25 to address it--sorry!

track.ID = item.ID
track.Present = true
break
}
}
if !track.Present {
debug.Debug(fmt.Sprintf("failed to find '%s' by '%s' in %s album", track.Title, track.Artist, track.Album))
debug.Debug(fmt.Sprintf("failed to find '%s' by '%s' in %s album", track.Title, track.Artist, track.Album))
}
}
return nil
}

func (c *Jellyfin) SearchPlaylist() error {
queryParams := fmt.Sprintf("/Search/Hints?searchTerm=%s&mediaTypes=Playlist", c.Cfg.PlaylistName)

queryParams := fmt.Sprintf("/Items?mediaTypes=Playlist&searchTerm=%s&recursive=true", c.Cfg.PlaylistName)
body, err := c.HttpClient.MakeRequest("GET", c.Cfg.URL+queryParams, nil, c.Cfg.Creds.Headers)
if err != nil {
return err
Expand All @@ -169,7 +167,7 @@ func (c *Jellyfin) SearchPlaylist() error {
if err = util.ParseResp(body, &results); err != nil {
return err
}

if len(results.SearchHints) != 0 {
c.Cfg.PlaylistID = results.SearchHints[0].ID
return nil
Expand Down Expand Up @@ -237,12 +235,12 @@ func formatJFSongs(tracks []*models.Track) ([]byte, error) { // marshal track ID
songIDs := make([]string, 0, len(tracks))
for _, track := range tracks {
if track.Present {
songIDs = append(songIDs,track.ID)
songIDs = append(songIDs, track.ID)
}
}
songs, err := json.Marshal(songIDs)
if err != nil {
return nil, err
}
return songs, nil
}
}