1010
1111from httpx import Client , HTTPStatusError , RequestError , TimeoutException
1212from pydantic import TypeAdapter , ValidationError
13- from ratelimit import limits , sleep_and_retry
1413
1514from mediux_posters import __version__
1615from mediux_posters .console import CONSOLE
2625)
2726
2827LOGGER = logging .getLogger (__name__ )
29- MINUTE = 60
3028
3129
3230class Jellyfin (BaseService [Show , Season , Episode , Collection , Movie ]):
@@ -44,8 +42,6 @@ def __init__(self, base_url: str, token: str):
4442 def extract_id (cls , entry : dict , prefix : str = "Tmdb" ) -> str | None :
4543 return entry .get ("ProviderIds" , {}).get (prefix )
4644
47- @sleep_and_retry
48- @limits (calls = 30 , period = MINUTE )
4945 def _perform_get_request (
5046 self , endpoint : str , params : dict [str , str | list [str ]] | None = None
5147 ) -> dict :
@@ -71,8 +67,6 @@ def _perform_get_request(
7167 except TimeoutException as err :
7268 raise ServiceError ("Service took too long to respond" ) from err
7369
74- @sleep_and_retry
75- @limits (calls = 30 , period = MINUTE )
7670 def _perform_post_request (
7771 self , endpoint : str , body : bytes , headers : dict [str , str ] | None = None
7872 ) -> None :
@@ -114,15 +108,18 @@ def _list_libraries(
114108 except ValidationError as err :
115109 raise ServiceError (err ) from err
116110
117- def _parse_show (self , jellyfin_show : dict ) -> Show :
118- show = TypeAdapter (Show ).validate_python (jellyfin_show )
119- for jellyfin_season in self ._list_seasons (show_id = show .id ):
120- season = TypeAdapter (Season ).validate_python (jellyfin_season )
121- for jellyfin_episode in self ._list_episodes (show_id = show .id , season_id = season .id ):
122- episode = TypeAdapter (Episode ).validate_python (jellyfin_episode )
123- season .episodes .append (episode )
124- show .seasons .append (season )
125- return show
111+ def list_episodes (self , show_id : str , season_id : str ) -> list [Episode ]:
112+ results = self ._perform_get_request (
113+ endpoint = f"/Shows/{ show_id } /Episodes" ,
114+ params = {"seasonId" : season_id , "fields" : ["ProviderIds" ]},
115+ ).get ("Items" , [])
116+ return TypeAdapter (list [Episode ]).validate_python (results )
117+
118+ def list_seasons (self , show_id : str ) -> list [Season ]:
119+ results = self ._perform_get_request (
120+ endpoint = f"/Shows/{ show_id } /Seasons" , params = {"fields" : ["ProviderIds" ]}
121+ ).get ("Items" , [])
122+ return TypeAdapter (list [Season ]).validate_python (results )
126123
127124 def _list_shows (
128125 self ,
@@ -149,48 +146,26 @@ def _list_shows(
149146 if not tmdb or (tmdb_id is not None and int (tmdb ) != tmdb_id ):
150147 continue
151148 try :
152- output .append (self ._parse_show (jellyfin_show = result ))
149+ result = TypeAdapter (Show ).validate_python (result )
150+ output .append (result )
153151 except ValidationError as err :
154152 raise ServiceError (err ) from err
155153 return output
156154
157- def _list_seasons (self , show_id : str ) -> list [dict ]:
158- return self ._perform_get_request (
159- endpoint = f"/Shows/{ show_id } /Seasons" , params = {"fields" : ["ProviderIds" ]}
160- ).get ("Items" , [])
161-
162- def _list_episodes (self , show_id : str , season_id : str ) -> list [dict ]:
163- return self ._perform_get_request (
164- endpoint = f"/Shows/{ show_id } /Episodes" ,
165- params = {"seasonId" : season_id , "fields" : ["ProviderIds" ]},
166- ).get ("Items" , [])
167-
168155 def list_shows (self , skip_libraries : list [str ] | None = None ) -> list [Show ]:
169156 return self ._list_shows (skip_libraries = skip_libraries )
170157
171158 def get_show (self , tmdb_id : int ) -> Show | None :
172159 return next (iter (self ._list_shows (tmdb_id = tmdb_id )), None )
173160
174- def _list_collections (
175- self ,
176- skip_libraries : list [str ] | None = None ,
177- tmdb_id : int | None = None , # noqa: ARG002
178- collection_id : str | None = None , # noqa: ARG002
179- ) -> list [Collection ]:
180- libraries = self ._list_libraries (media_type = "unknown" , skip_libraries = skip_libraries )
181- output = []
182- for _library in libraries :
183- pass
184- return output
185-
186- def list_collections (self , skip_libraries : list [str ] | None = None ) -> list [Collection ]:
187- return self ._list_collections (skip_libraries = skip_libraries )
161+ def list_collections (self , skip_libraries : list [str ] | None = None ) -> list [Collection ]: # noqa: ARG002
162+ return []
188163
189- def get_collection (self , tmdb_id : int ) -> Collection | None :
190- return next ( iter ( self . _list_collections ( tmdb_id = tmdb_id )), None )
164+ def get_collection (self , tmdb_id : int ) -> Collection | None : # noqa: ARG002
165+ return None
191166
192- def _parse_movie (self , jellyfin_movie : dict ) -> Movie :
193- return TypeAdapter ( Movie ). validate_python ( jellyfin_movie )
167+ def list_collection_movies (self , collection_id : int | str ) -> list [ Movie ]: # noqa: ARG002
168+ return []
194169
195170 def _list_movies (
196171 self ,
@@ -217,7 +192,8 @@ def _list_movies(
217192 if not tmdb or (tmdb_id is not None and int (tmdb ) != tmdb_id ):
218193 continue
219194 try :
220- output .append (self ._parse_movie (jellyfin_movie = result ))
195+ result = TypeAdapter (Movie ).validate_python (result )
196+ output .append (result )
221197 except ValidationError as err :
222198 raise ServiceError (err ) from err
223199 return output
@@ -230,7 +206,7 @@ def get_movie(self, tmdb_id: int) -> Movie | None:
230206
231207 def upload_image (
232208 self ,
233- obj : Show | Season | Episode | Movie | Collection ,
209+ object_id : int | str ,
234210 image_file : Path ,
235211 kometa_integration : bool , # noqa: ARG002
236212 ) -> bool :
@@ -244,7 +220,7 @@ def upload_image(
244220 image_data = b64encode (stream .read ())
245221 try :
246222 self ._perform_post_request (
247- endpoint = f"/Items/{ obj . id } /Images/{ image_type } " ,
223+ endpoint = f"/Items/{ object_id } /Images/{ image_type } " ,
248224 headers = headers ,
249225 body = image_data ,
250226 )
0 commit comments