@@ -170,14 +170,53 @@ async def get_library_items(self) -> dict[str, list[dict]]:
170170 ]
171171 logger .info (f"Filtered { len (watched_items )} watched library items" )
172172
173- # Check if user has loved the movie or series in parallel
174- loved_statuses = await asyncio .gather (
175- * [self .is_loved (auth_key , item .get ("_id" ), item .get ("type" )) for item in watched_items ]
176- )
173+ # Sort watched items by modification time (most recent first)
174+ watched_items .sort (key = lambda x : x .get ("_mtime" , "" ), reverse = True )
175+
176+ # is_loved only until we find 10 movies and 10 series
177+ loved_items = []
178+ movies_found = 0
179+ series_found = 0
180+ target_count = settings .RECOMMENDATION_SOURCE_ITEMS_LIMIT
181+ batch_size = 20
182+
183+ # Process in batches to stop early
184+ for i in range (0 , len (watched_items ), batch_size ):
185+ if movies_found >= target_count and series_found >= target_count :
186+ logger .info ("Found enough loved items, stopping check" )
187+ break
177188
178- # Separate loved and watched items
179- loved_items = [item for item , loved in zip (watched_items , loved_statuses ) if loved ]
180- logger .info (f"Found { len (loved_items )} loved library items" )
189+ batch = watched_items [i : i + batch_size ] # noqa: E203
190+
191+ # Filter batch to only check types we still need
192+ check_candidates = []
193+ for item in batch :
194+ itype = item .get ("type" )
195+ if itype == "movie" and movies_found < target_count :
196+ check_candidates .append (item )
197+ elif itype == "series" and series_found < target_count :
198+ check_candidates .append (item )
199+
200+ if not check_candidates :
201+ continue
202+
203+ # Check loved status for candidates in parallel
204+ loved_statuses = await asyncio .gather (
205+ * [self .is_loved (auth_key , item .get ("_id" ), item .get ("type" )) for item in check_candidates ]
206+ )
207+
208+ # Process results
209+ for item , is_loved_status in zip (check_candidates , loved_statuses ):
210+ if is_loved_status :
211+ loved_items .append (item )
212+ if item .get ("type" ) == "movie" :
213+ movies_found += 1
214+ elif item .get ("type" ) == "series" :
215+ series_found += 1
216+
217+ logger .info (
218+ f"Found { len (loved_items )} loved library items (Movies: { movies_found } , Series: { series_found } )"
219+ )
181220
182221 # Format watched items
183222 formatted_watched = []
@@ -191,7 +230,7 @@ async def get_library_items(self) -> dict[str, list[dict]]:
191230 }
192231 )
193232
194- # Format and sort loved items
233+ # Format loved items (they are already somewhat sorted by discovery order, which aligns with mtime)
195234 formatted_loved = []
196235 for item in loved_items :
197236 formatted_loved .append (
@@ -203,9 +242,6 @@ async def get_library_items(self) -> dict[str, list[dict]]:
203242 }
204243 )
205244
206- # Sort loved items by modification time (most recent first)
207- formatted_loved .sort (key = lambda x : x .get ("_mtime" , "" ), reverse = True )
208-
209245 return {"watched" : formatted_watched , "loved" : formatted_loved }
210246 except Exception as e :
211247 logger .error (f"Error fetching library items: { e } " , exc_info = True )
@@ -233,7 +269,7 @@ async def get_addons(self, auth_key: str | None = None) -> list[dict]:
233269 message = error_payload .get ("message" ) or message
234270 elif isinstance (error_payload , str ):
235271 message = error_payload or message
236- logger .warning ("Addon collection request failed: {}" , error_payload )
272+ logger .warning (f "Addon collection request failed: { error_payload } " )
237273 raise ValueError (f"Stremio: { message } " )
238274 addons = data .get ("result" , {}).get ("addons" , [])
239275 logger .info (f"Found { len (addons )} addons" )
0 commit comments