plexflow 0.0.125__py3-none-any.whl → 0.0.127__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plexflow/core/metadata/providers/plex/__pycache__/datatypes.cpython-312.pyc +0 -0
- plexflow/core/metadata/providers/plex/__pycache__/plex.cpython-312.pyc +0 -0
- plexflow/core/metadata/providers/plex/datatypes.py +27 -27
- plexflow/core/metadata/providers/plex/plex.py +11 -0
- plexflow/core/plex/library/__pycache__/show.cpython-312.pyc +0 -0
- plexflow/core/plex/library/show.py +67 -0
- {plexflow-0.0.125.dist-info → plexflow-0.0.127.dist-info}/METADATA +1 -1
- {plexflow-0.0.125.dist-info → plexflow-0.0.127.dist-info}/RECORD +10 -8
- {plexflow-0.0.125.dist-info → plexflow-0.0.127.dist-info}/WHEEL +0 -0
- {plexflow-0.0.125.dist-info → plexflow-0.0.127.dist-info}/entry_points.txt +0 -0
Binary file
|
Binary file
|
@@ -368,33 +368,33 @@ class PlexShowMetadata:
|
|
368
368
|
_catchall (dict): A catch-all dictionary for any additional attributes.
|
369
369
|
"""
|
370
370
|
|
371
|
-
art: Optional[str] = None
|
372
|
-
guid: Optional[str] = None
|
373
|
-
key: Optional[str] = None
|
374
|
-
primaryExtraKey: Optional[str] = None
|
375
|
-
rating: Optional[float] = None
|
376
|
-
ratingKey: Optional[str] = None
|
377
|
-
studio: Optional[str] = None
|
378
|
-
subtype: Optional[str] = None
|
379
|
-
summary: Optional[str] = None
|
380
|
-
tagline: Optional[str] = None
|
381
|
-
type: Optional[str] = None
|
382
|
-
thumb: Optional[str] = None
|
383
|
-
addedAt: Optional[int] = None
|
384
|
-
duration: Optional[int] = None
|
385
|
-
publicPagesURL: Optional[str] = None
|
386
|
-
slug: Optional[str] = None
|
387
|
-
userState: Optional[bool] = None
|
388
|
-
title: Optional[str] = None
|
389
|
-
leafCount: Optional[int] = None
|
390
|
-
childCount: Optional[int] = None
|
391
|
-
skipChildren: Optional[bool] = None
|
392
|
-
isContinuingSeries: Optional[bool] = None
|
393
|
-
contentRating: Optional[str] = None
|
394
|
-
originallyAvailableAt: Optional[str] = None
|
395
|
-
year: Optional[int] = None
|
396
|
-
ratingImage: Optional[str] = None
|
397
|
-
imdbRatingCount: Optional[int] = None
|
371
|
+
art: Optional[str] = None
|
372
|
+
guid: Optional[str] = None
|
373
|
+
key: Optional[str] = None
|
374
|
+
primaryExtraKey: Optional[str] = None
|
375
|
+
rating: Optional[float] = None
|
376
|
+
ratingKey: Optional[str] = None
|
377
|
+
studio: Optional[str] = None
|
378
|
+
subtype: Optional[str] = None
|
379
|
+
summary: Optional[str] = None
|
380
|
+
tagline: Optional[str] = None
|
381
|
+
type: Optional[str] = None
|
382
|
+
thumb: Optional[str] = None
|
383
|
+
addedAt: Optional[int] = None
|
384
|
+
duration: Optional[int] = None
|
385
|
+
publicPagesURL: Optional[str] = None
|
386
|
+
slug: Optional[str] = None
|
387
|
+
userState: Optional[bool] = None
|
388
|
+
title: Optional[str] = None
|
389
|
+
leafCount: Optional[int] = None
|
390
|
+
childCount: Optional[int] = None
|
391
|
+
skipChildren: Optional[bool] = None
|
392
|
+
isContinuingSeries: Optional[bool] = None
|
393
|
+
contentRating: Optional[str] = None
|
394
|
+
originallyAvailableAt: Optional[str] = None
|
395
|
+
year: Optional[int] = None
|
396
|
+
ratingImage: Optional[str] = None
|
397
|
+
imdbRatingCount: Optional[int] = None
|
398
398
|
source: Optional[str] = None
|
399
399
|
Image: Optional[List[PlexImage]] = None
|
400
400
|
Guid: Optional[List[PlexGuid]] = None
|
@@ -140,6 +140,17 @@ def get_all_episodes_by_show_rating_key(key: str) -> List[PlexEpisodeMetadata]:
|
|
140
140
|
episodes.append(x)
|
141
141
|
return episodes
|
142
142
|
|
143
|
+
def get_show_tags(key: str) -> set:
|
144
|
+
episodes = get_all_episodes_by_show_rating_key(key=key)
|
145
|
+
|
146
|
+
tags = set()
|
147
|
+
|
148
|
+
for episode in episodes:
|
149
|
+
tag = f"s{episode.parentIndex:02d}e{episode.index:02d}"
|
150
|
+
tags.add(tag)
|
151
|
+
|
152
|
+
return tags
|
153
|
+
|
143
154
|
def get_watch_state_by_rating_key(key: str) -> Union[PlexUserState, None]:
|
144
155
|
"""
|
145
156
|
Get the watch state of a movie or show using its rating key.
|
Binary file
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from plexapi.server import PlexServer
|
2
|
+
import os
|
3
|
+
|
4
|
+
class PlexLibraryShow:
|
5
|
+
def __init__(self, guid: str, plex_host: str = os.getenv('PLEX_HOST'),
|
6
|
+
plex_port: int = int(os.getenv('PLEX_PORT', 32400)),
|
7
|
+
plex_token: str = os.getenv('PLEX_TOKEN')):
|
8
|
+
self.BASEURL = f'http://{plex_host}:{plex_port}' # e.g., 'http://192.168.1.100:32400'
|
9
|
+
self.PLEX_TOKEN = plex_token
|
10
|
+
self.guid = guid
|
11
|
+
|
12
|
+
try:
|
13
|
+
self.plex = PlexServer(self.BASEURL, self.PLEX_TOKEN)
|
14
|
+
print("Successfully connected to Plex using direct URL and token.")
|
15
|
+
except Exception as e:
|
16
|
+
print(f"Error connecting to Plex with direct URL/token: {e}")
|
17
|
+
|
18
|
+
try:
|
19
|
+
# 1. Access the TV Shows library
|
20
|
+
tv_shows_library = self.plex.library.section('Series')
|
21
|
+
|
22
|
+
# 2. Search the library, filtering by the GUID
|
23
|
+
# The 'guid' parameter in search can be used to filter by the item's GUID.
|
24
|
+
# It returns a list, as theoretically multiple items could have the same GUID (though rare for primary GUIDs).
|
25
|
+
found_shows = tv_shows_library.search(guid=self.guid)
|
26
|
+
|
27
|
+
if found_shows:
|
28
|
+
# Assuming the first result is the one we want (often the case for unique GUIDs)
|
29
|
+
show = found_shows[0]
|
30
|
+
|
31
|
+
if show.TYPE == 'show':
|
32
|
+
self._show = show
|
33
|
+
print(f"\nFound show by GUID '{self.guid}': {show.title}")
|
34
|
+
print(f"Rating Key: {show.ratingKey}")
|
35
|
+
print(f"Summary: {show.summary[:100]}...")
|
36
|
+
else:
|
37
|
+
raise RuntimeError(f"Item with GUID '{self.guid}' is not a TV show (it's a {show.TYPE}).")
|
38
|
+
else:
|
39
|
+
raise RuntimeError(f"No show found with GUID: {self.guid}")
|
40
|
+
|
41
|
+
except Exception as e:
|
42
|
+
raise RuntimeError(f"An error occurred while fetching item by GUID {self.guid}: {e}")
|
43
|
+
|
44
|
+
@property
|
45
|
+
def show(self):
|
46
|
+
return self._show
|
47
|
+
|
48
|
+
@property
|
49
|
+
def tags(self):
|
50
|
+
show = self.show
|
51
|
+
|
52
|
+
tags = set()
|
53
|
+
|
54
|
+
seasons = show.seasons()
|
55
|
+
if seasons:
|
56
|
+
for season in seasons:
|
57
|
+
episodes = season.episodes()
|
58
|
+
if episodes:
|
59
|
+
for episode in episodes:
|
60
|
+
tag = f"s{season.index:02d}e{episode.index:02d}"
|
61
|
+
tags.add(tag)
|
62
|
+
else:
|
63
|
+
print(f" No episodes found for Season {season.index}.")
|
64
|
+
else:
|
65
|
+
print(f"No seasons found for '{show.title}'.")
|
66
|
+
|
67
|
+
return tags
|
@@ -222,14 +222,14 @@ plexflow/core/metadata/providers/plex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
222
222
|
plexflow/core/metadata/providers/plex/__pycache__/__init__.cpython-311.pyc,sha256=Dn0hfFPLViFaic_zPb69TzXE3CVgDayCBJbfj5GM6N8,187
|
223
223
|
plexflow/core/metadata/providers/plex/__pycache__/__init__.cpython-312.pyc,sha256=fwdj_MNjIInQSPXMhY9YiRSe9CJAwPElwbYa1fNbRvE,173
|
224
224
|
plexflow/core/metadata/providers/plex/__pycache__/datatypes.cpython-311.pyc,sha256=S6n0CREPam6rZ5qDl-iasX-yYLFAoQCwr3zAVU1OKMI,49762
|
225
|
-
plexflow/core/metadata/providers/plex/__pycache__/datatypes.cpython-312.pyc,sha256=
|
225
|
+
plexflow/core/metadata/providers/plex/__pycache__/datatypes.cpython-312.pyc,sha256=qdbF6-Lmt89gd2m-UuxRxvKU1RC0rmFd1cwpASikuFA,45954
|
226
226
|
plexflow/core/metadata/providers/plex/__pycache__/imdb.cpython-311.pyc,sha256=N_uu32ljM0xa1Nn8NK43QtU9tYRw_LyBblq7FgbfCg0,4342
|
227
227
|
plexflow/core/metadata/providers/plex/__pycache__/moviemeter.cpython-311.pyc,sha256=P78PwQIcVFzjwQqjHRGHhoWx6XtHRqJKIWeeX_jId4s,2551
|
228
228
|
plexflow/core/metadata/providers/plex/__pycache__/plex.cpython-311.pyc,sha256=FgbspEc3m5Vkm_m9Ry7gVAavs_2-4Er4FIREdJgaDIQ,8182
|
229
|
-
plexflow/core/metadata/providers/plex/__pycache__/plex.cpython-312.pyc,sha256=
|
229
|
+
plexflow/core/metadata/providers/plex/__pycache__/plex.cpython-312.pyc,sha256=wSeEa7IHHJ-sNdRJBNFI_mM49u6Cg7RGwUZvwI1Cx7I,7848
|
230
230
|
plexflow/core/metadata/providers/plex/__pycache__/tmdb.cpython-311.pyc,sha256=vWlpw_-ldSWwFvz67kTwxK9XxZPy7iExyLgD6rTOf10,4200
|
231
|
-
plexflow/core/metadata/providers/plex/datatypes.py,sha256
|
232
|
-
plexflow/core/metadata/providers/plex/plex.py,sha256=
|
231
|
+
plexflow/core/metadata/providers/plex/datatypes.py,sha256=NZaaAnBf_5BgPg07taQimk5Fj0nYhv1FBaVq2FlKOcc,34208
|
232
|
+
plexflow/core/metadata/providers/plex/plex.py,sha256=KbXwAXpoPypCYwcUVgbvQCzyFCnBU93-iurS9tEiuak,6170
|
233
233
|
plexflow/core/metadata/providers/tmdb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
234
234
|
plexflow/core/metadata/providers/tmdb/__pycache__/__init__.cpython-311.pyc,sha256=djXYmvhVt2MFuzdiZ7ojQCXMa9UffVv_j_hBl0bdIvM,187
|
235
235
|
plexflow/core/metadata/providers/tmdb/__pycache__/__init__.cpython-312.pyc,sha256=syh3BYXz8qBfAjyO9lVDlfl_Jf3VfkU--pywQ1ZeFG8,173
|
@@ -288,12 +288,14 @@ plexflow/core/plex/library/__pycache__/__init__.cpython-311.pyc,sha256=9m-aTcoSl
|
|
288
288
|
plexflow/core/plex/library/__pycache__/__init__.cpython-312.pyc,sha256=WbfQgOztEHUetNJ0maAX2U1eYLdTqIuivfoejtjoaIc,162
|
289
289
|
plexflow/core/plex/library/__pycache__/library.cpython-311.pyc,sha256=yL69reegO6xlOsd_QA2uLQU0Eo7By8gE4ldB_X-0IDc,4559
|
290
290
|
plexflow/core/plex/library/__pycache__/library.cpython-312.pyc,sha256=6-TJWeb3YFArriMpzfMswXsBrlp3antN7QvUxr4LBaM,4518
|
291
|
+
plexflow/core/plex/library/__pycache__/show.cpython-312.pyc,sha256=p0h8b6DtlcQak-HGZZeL31ToMsifkbNqQtbfDBT4tVM,3656
|
291
292
|
plexflow/core/plex/library/folders/assets/plex_asset.py,sha256=awY8vhg3KoU2uCB18y5MleE3aAUdVDTnN1OaTmm2oJc,530
|
292
293
|
plexflow/core/plex/library/folders/assets/plex_subtitle_asset.py,sha256=51itoIUbHco2HW0Mh9mGNddqwMrZA2ajwuyhVzPcXkI,521
|
293
294
|
plexflow/core/plex/library/folders/assets/plex_video_asset.py,sha256=F_7RtdtblYQJc_gp9nUVxIfS4BeHl0eZDgYmTMg2zos,208
|
294
295
|
plexflow/core/plex/library/folders/plex_folder.py,sha256=GZnyQO6bzcire-2mxPjIPJrq8J0S_4uVsOfVCiHo2E0,387
|
295
296
|
plexflow/core/plex/library/folders/plex_movie_folder.py,sha256=ns-3yf5VgikXc5IBeN8xPTtB9LHkPIQOZ4CsvcBZNU8,1672
|
296
297
|
plexflow/core/plex/library/library.py,sha256=taLi0e7iY0usZPDHXwPfLmxQI5vyMyo8eJtOSHNKtww,3644
|
298
|
+
plexflow/core/plex/library/show.py,sha256=jAZfrjxoF_E1v0sdTpLmyx3NGWC3Uzil0XjJ8NkbUvQ,2648
|
297
299
|
plexflow/core/plex/token/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
298
300
|
plexflow/core/plex/token/__pycache__/__init__.cpython-311.pyc,sha256=trdQUL3OxH5EHEmWYV9U1xf7PK9ig9RDpauyqI7uh34,174
|
299
301
|
plexflow/core/plex/token/__pycache__/__init__.cpython-312.pyc,sha256=rIQN9_UVduAPposcqZUJL1RZNmPZJ9MpTadq18aFAd4,160
|
@@ -711,7 +713,7 @@ plexflow/utils/video/__pycache__/audio.cpython-312.pyc,sha256=kmzGDCHSC1hWyHwRut
|
|
711
713
|
plexflow/utils/video/__pycache__/subtitle.cpython-312.pyc,sha256=PCjpCLydGXaRsQy6cikhgsEs8WlComfOoYPiLFqfVMA,2515
|
712
714
|
plexflow/utils/video/audio.py,sha256=Pd8OuQHX2QN-lc5iYkB0Vo1OEHmTcvDYH-uKud1f1q4,5262
|
713
715
|
plexflow/utils/video/subtitle.py,sha256=qPvvBjlPj0fynJJvGJgGeKt9ey26R-cF6EoLaYt9iXU,1333
|
714
|
-
plexflow-0.0.
|
715
|
-
plexflow-0.0.
|
716
|
-
plexflow-0.0.
|
717
|
-
plexflow-0.0.
|
716
|
+
plexflow-0.0.127.dist-info/METADATA,sha256=cyALDvg9Rb4cEwjTQEXVacg7q62rnXBcbM5LsWJ8k6w,2971
|
717
|
+
plexflow-0.0.127.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
718
|
+
plexflow-0.0.127.dist-info/entry_points.txt,sha256=9RJC3ikOQORHNOn573EdwJOBUnFU_4EGHbtNUM5pjjY,1557
|
719
|
+
plexflow-0.0.127.dist-info/RECORD,,
|
File without changes
|
File without changes
|