forked from platypush/platypush
[media.jellyfin] Playlists support (backend implementation).
This commit is contained in:
parent
7c7b80c942
commit
b967cb1969
2 changed files with 78 additions and 3 deletions
|
@ -1,4 +1,4 @@
|
||||||
from typing import Iterable, List, Optional, Type
|
from typing import Collection, Iterable, List, Optional, Type
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from marshmallow import Schema
|
from marshmallow import Schema
|
||||||
|
@ -12,6 +12,7 @@ from platypush.schemas.media.jellyfin import (
|
||||||
JellyfinEpisodeSchema,
|
JellyfinEpisodeSchema,
|
||||||
JellyfinMovieSchema,
|
JellyfinMovieSchema,
|
||||||
JellyfinPhotoSchema,
|
JellyfinPhotoSchema,
|
||||||
|
JellyfinPlaylistSchema,
|
||||||
JellyfinTrackSchema,
|
JellyfinTrackSchema,
|
||||||
JellyfinVideoSchema,
|
JellyfinVideoSchema,
|
||||||
)
|
)
|
||||||
|
@ -46,7 +47,9 @@ class MediaJellyfinPlugin(Plugin):
|
||||||
self._api_key = api_key
|
self._api_key = api_key
|
||||||
self.__user_id = None
|
self.__user_id = None
|
||||||
|
|
||||||
def _execute(self, method: str, url: str, *args, **kwargs) -> dict:
|
def _execute(
|
||||||
|
self, method: str, url: str, *args, return_json: bool = True, **kwargs
|
||||||
|
) -> dict:
|
||||||
url = '/' + url.lstrip('/')
|
url = '/' + url.lstrip('/')
|
||||||
url = self.server + url
|
url = self.server + url
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ class MediaJellyfinPlugin(Plugin):
|
||||||
rs = getattr(requests, method.lower())(url, *args, **kwargs)
|
rs = getattr(requests, method.lower())(url, *args, **kwargs)
|
||||||
rs.raise_for_status()
|
rs.raise_for_status()
|
||||||
|
|
||||||
return rs.json()
|
return rs.json() if return_json else {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _user_id(self) -> str:
|
def _user_id(self) -> str:
|
||||||
|
@ -165,6 +168,8 @@ class MediaJellyfinPlugin(Plugin):
|
||||||
result = JellyfinEpisodeSchema().dump(result)
|
result = JellyfinEpisodeSchema().dump(result)
|
||||||
elif result['Type'] == 'Audio':
|
elif result['Type'] == 'Audio':
|
||||||
result = JellyfinTrackSchema().dump(result)
|
result = JellyfinTrackSchema().dump(result)
|
||||||
|
elif result['Type'] == 'Playlist':
|
||||||
|
result = JellyfinPlaylistSchema().dump(result)
|
||||||
elif result['Type'] == 'MusicArtist':
|
elif result['Type'] == 'MusicArtist':
|
||||||
result = JellyfinArtistSchema().dump(result)
|
result = JellyfinArtistSchema().dump(result)
|
||||||
elif result['Type'] == 'MusicAlbum':
|
elif result['Type'] == 'MusicAlbum':
|
||||||
|
@ -379,3 +384,58 @@ class MediaJellyfinPlugin(Plugin):
|
||||||
)
|
)
|
||||||
|
|
||||||
return self._serialize_search_results(results)
|
return self._serialize_search_results(results)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def create_playlist(
|
||||||
|
self, name: str, public: bool = True, item_ids: Optional[Collection[str]] = None
|
||||||
|
) -> dict:
|
||||||
|
"""
|
||||||
|
Create a new playlist.
|
||||||
|
|
||||||
|
:param name: Name of the playlist.
|
||||||
|
:param public: Whether the playlist should be visible to any logged-in user.
|
||||||
|
:param item_ids: List of item IDs to add to the playlist.
|
||||||
|
"""
|
||||||
|
playlist = self._execute(
|
||||||
|
'POST',
|
||||||
|
'/Playlists',
|
||||||
|
json={
|
||||||
|
'Name': name,
|
||||||
|
'UserId': self._user_id,
|
||||||
|
'IsPublic': public,
|
||||||
|
'Items': item_ids or [],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return dict(
|
||||||
|
JellyfinPlaylistSchema().dump(
|
||||||
|
{
|
||||||
|
'Name': name,
|
||||||
|
'IsPublic': public,
|
||||||
|
**playlist,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def delete_item(self, item_id: str) -> dict:
|
||||||
|
"""
|
||||||
|
Delete an item from the server.
|
||||||
|
|
||||||
|
:param item_id: ID of the item to delete.
|
||||||
|
"""
|
||||||
|
return self._execute('DELETE', f'/Items/{item_id}', return_json=False)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def add_to_playlist(self, playlist_id: str, item_ids: Collection[str]) -> dict:
|
||||||
|
"""
|
||||||
|
Add items to a playlist.
|
||||||
|
|
||||||
|
:param playlist_id: ID of the playlist.
|
||||||
|
:param item_ids: List of item IDs to add to the playlist.
|
||||||
|
"""
|
||||||
|
return self._execute(
|
||||||
|
'POST',
|
||||||
|
f'/Playlists/{playlist_id}/Items',
|
||||||
|
params={'ids': ','.join(item_ids)},
|
||||||
|
)
|
||||||
|
|
|
@ -313,3 +313,18 @@ class JellyfinBookSchema(JellyfinSchema):
|
||||||
] = f'{self._server}/Items/{data["Id"]}/Download?api_key={self._api_key}'
|
] = f'{self._server}/Items/{data["Id"]}/Download?api_key={self._api_key}'
|
||||||
data['embed_url'] = f'{self._server}/web/#/details?id={data["Id"]}'
|
data['embed_url'] = f'{self._server}/web/#/details?id={data["Id"]}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class JellyfinPlaylistSchema(JellyfinSchema, MediaCollectionSchema):
|
||||||
|
id = fields.String(attribute='Id')
|
||||||
|
type = fields.Constant('playlist')
|
||||||
|
item_type = fields.Constant('playlist')
|
||||||
|
collection_type = fields.Constant('music')
|
||||||
|
name = fields.String(attribute='Name')
|
||||||
|
image = fields.String()
|
||||||
|
public = fields.Boolean(attribute='IsPublic')
|
||||||
|
duration = fields.Number(attribute='RunTimeTicks')
|
||||||
|
n_items = fields.Number(attribute='ChildCount')
|
||||||
|
genres = fields.List(fields.String, attribute='Genres')
|
||||||
|
tags = fields.List(fields.String, attribute='Tags')
|
||||||
|
created_at = DateTime(attribute='DateCreated')
|
||||||
|
|
Loading…
Reference in a new issue