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.
@@ -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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: plexflow
3
- Version: 0.0.125
3
+ Version: 0.0.127
4
4
  Summary: A short description of the package.
5
5
  License: MIT
6
6
  Keywords: keyword1,keyword2,keyword3
@@ -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=leELWfqr32G9VbGGawOESJYUtB2F_Ofd2__2wsIValA,45957
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=GKjYqAdmiDSuAQ3HlsQJMRAHfi65sbw7maeLcuq6rbs,7334
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=-EWmoJkitlNLSNpyvWDZX1qPw9vjXenMnQZVrwwazOk,34235
232
- plexflow/core/metadata/providers/plex/plex.py,sha256=KrOjSLzeZVIGDnLDC7dw87Yizq5h3Fbf9MtPv_tcET8,5918
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.125.dist-info/METADATA,sha256=qlsU91rtB-gtra9x8BhIJ8JSlDDuIBnC1NkuG0tr43c,2971
715
- plexflow-0.0.125.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
716
- plexflow-0.0.125.dist-info/entry_points.txt,sha256=9RJC3ikOQORHNOn573EdwJOBUnFU_4EGHbtNUM5pjjY,1557
717
- plexflow-0.0.125.dist-info/RECORD,,
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,,