mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-22 03:33:08 +00:00
Add properties to return the Plex Media Server data metadata paths (#1207)
* Add property to return the Plex Media Server data metadata path * Add property to return the filepath for a resource * Add tests for metadataDirectory and resourceFilepath
This commit is contained in:
parent
0679816201
commit
b98b6050fe
9 changed files with 112 additions and 1 deletions
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from plexapi import media, utils
|
||||
|
@ -240,6 +241,12 @@ class Artist(
|
|||
key = f'{self.key}?includeStations=1'
|
||||
return next(iter(self.fetchItems(key, cls=Playlist, rtag="Stations")), None)
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Artists' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Album(
|
||||
|
@ -359,6 +366,12 @@ class Album(
|
|||
""" Returns str, default title for a new syncItem. """
|
||||
return f'{self.parentTitle} - {self.title}'
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Albums' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Track(
|
||||
|
@ -470,6 +483,12 @@ class Track(
|
|||
""" Get the Plex Web URL with the correct parameters. """
|
||||
return self._server._buildWebURL(base=base, endpoint='details', key=self.parentKey)
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.parentGuid)
|
||||
return str(Path('Metadata') / 'Albums' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class TrackSession(PlexSession, Track):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from plexapi import media, utils
|
||||
|
@ -560,3 +561,9 @@ class Collection(
|
|||
raise Unsupported('Unsupported collection content')
|
||||
|
||||
return myplex.sync(sync_item, client=client, clientId=clientId)
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Collections' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import xml
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from plexapi import log, settings, utils
|
||||
|
@ -1024,6 +1024,20 @@ class BaseResource(PlexObject):
|
|||
except xml.etree.ElementTree.ParseError:
|
||||
pass
|
||||
|
||||
@property
|
||||
def resourceFilepath(self):
|
||||
""" Returns the file path to the resource in the Plex Media Server data directory.
|
||||
Note: Returns the URL if the resource is not stored locally.
|
||||
"""
|
||||
if self.ratingKey.startswith('media://'):
|
||||
return str(Path('Media') / 'localhost' / self.ratingKey.split('://')[-1])
|
||||
elif self.ratingKey.startswith('metadata://'):
|
||||
return str(Path(self._parent().metadataDirectory) / 'Contents' / '_combined' / self.ratingKey.split('://')[-1])
|
||||
elif self.ratingKey.startswith('upload://'):
|
||||
return str(Path(self._parent().metadataDirectory) / 'Uploads' / self.ratingKey.split('://')[-1])
|
||||
else:
|
||||
return self.ratingKey
|
||||
|
||||
|
||||
class Art(BaseResource):
|
||||
""" Represents a single Art object. """
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from plexapi import media, utils, video
|
||||
|
@ -139,6 +140,12 @@ class Photoalbum(
|
|||
""" Get the Plex Web URL with the correct parameters. """
|
||||
return self._server._buildWebURL(base=base, endpoint='details', key=self.key, legacy=1)
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Photos' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Photo(
|
||||
|
@ -290,6 +297,12 @@ class Photo(
|
|||
""" Get the Plex Web URL with the correct parameters. """
|
||||
return self._server._buildWebURL(base=base, endpoint='details', key=self.parentKey, legacy=1)
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.parentGuid)
|
||||
return str(Path('Metadata') / 'Photos' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class PhotoSession(PlexSession, Photo):
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus, unquote
|
||||
|
||||
from plexapi import media, utils
|
||||
|
@ -496,3 +497,9 @@ class Playlist(
|
|||
def _getWebURL(self, base=None):
|
||||
""" Get the Plex Web URL with the correct parameters. """
|
||||
return self._server._buildWebURL(base=base, endpoint='playlist', key=self.key)
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Playlists' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
|
|
@ -13,6 +13,7 @@ import zipfile
|
|||
from collections import deque
|
||||
from datetime import datetime, timedelta
|
||||
from getpass import getpass
|
||||
from hashlib import sha1
|
||||
from threading import Event, Thread
|
||||
from urllib.parse import quote
|
||||
|
||||
|
@ -650,3 +651,8 @@ def openOrRead(file):
|
|||
return file.read()
|
||||
with open(file, 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def sha1hash(guid):
|
||||
""" Return the SHA1 hash of a guid. """
|
||||
return sha1(guid.encode('utf-8')).hexdigest()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from plexapi import media, utils
|
||||
|
@ -445,6 +446,12 @@ class Movie(
|
|||
self._server.query(key, params=params, method=self._server._session.put)
|
||||
return self
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Movies' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Show(
|
||||
|
@ -655,6 +662,12 @@ class Show(
|
|||
filepaths += episode.download(_savepath, keep_original_name, **kwargs)
|
||||
return filepaths
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'TV Shows' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Season(
|
||||
|
@ -808,6 +821,12 @@ class Season(
|
|||
""" Returns str, default title for a new syncItem. """
|
||||
return f'{self.parentTitle} - {self.title}'
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.parentGuid)
|
||||
return str(Path('Metadata') / 'TV Shows' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Episode(
|
||||
|
@ -1000,6 +1019,12 @@ class Episode(
|
|||
self._server.query(key, params=params, method=self._server._session.put)
|
||||
return self
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.grandparentGuid)
|
||||
return str(Path('Metadata') / 'TV Shows' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
@utils.registerPlexObject
|
||||
class Clip(
|
||||
|
@ -1058,6 +1083,12 @@ class Clip(
|
|||
""" Returns a filename for use in download. """
|
||||
return self.title
|
||||
|
||||
@property
|
||||
def metadataDirectory(self):
|
||||
""" Returns the Plex Media Server data directory where the metadata is stored. """
|
||||
guid_hash = utils.sha1hash(self.guid)
|
||||
return str(Path('Metadata') / 'Movies' / guid_hash[0] / f'{guid_hash[1:]}.bundle')
|
||||
|
||||
|
||||
class Extra(Clip):
|
||||
""" Represents a single Extra (trailer, behindTheScenes, etc). """
|
||||
|
|
|
@ -72,6 +72,8 @@ BASE_DIR_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||
STUB_MOVIE_PATH = os.path.join(BASE_DIR_PATH, "tests", "data", "video_stub.mp4")
|
||||
STUB_MP3_PATH = os.path.join(BASE_DIR_PATH, "tests", "data", "audio_stub.mp3")
|
||||
STUB_IMAGE_PATH = os.path.join(BASE_DIR_PATH, "tests", "data", "cute_cat.jpg")
|
||||
# For the default Docker bootstrap test Plex Media Server data directory
|
||||
BOOTSTRAP_DATA_PATH = os.path.join(BASE_DIR_PATH, "plex", "db", "Library", "Application Support", "Plex Media Server")
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
|
|
|
@ -1459,3 +1459,15 @@ def test_video_optimize(plex, movie, tvshows, show):
|
|||
movie.optimize()
|
||||
with pytest.raises(BadRequest):
|
||||
movie.optimize(target="mobile", locationID=-100)
|
||||
|
||||
|
||||
def test_video_Movie_matadataDirectory(movie):
|
||||
assert os.path.exists(os.path.join(utils.BOOTSTRAP_DATA_PATH, movie.metadataDirectory))
|
||||
|
||||
for poster in movie.posters():
|
||||
if not poster.ratingKey.startswith('http'):
|
||||
assert os.path.exists(os.path.join(utils.BOOTSTRAP_DATA_PATH, poster.resourceFilepath))
|
||||
|
||||
for art in movie.arts():
|
||||
if not art.ratingKey.startswith('http'):
|
||||
assert os.path.exists(os.path.join(utils.BOOTSTRAP_DATA_PATH, art.resourceFilepath))
|
||||
|
|
Loading…
Reference in a new issue