@@ -712,7 +712,7 @@ discoverRoutes.get('/trending', async (req, res, next) => {
712712 } catch ( e ) {
713713 logger . debug ( 'Something went wrong retrieving trending items' , {
714714 label : 'API' ,
715- errorMessage : e . message ,
715+ errorMessage : ( e as Error ) . message ,
716716 } ) ;
717717 return next ( {
718718 status : 500 ,
@@ -917,4 +917,145 @@ discoverRoutes.get<Record<string, unknown>, WatchlistResponse>(
917917 }
918918) ;
919919
920+ // TMDB list slider: return items from a TMDB list by id
921+ discoverRoutes . get < { listId : string } > (
922+ '/list/:listId' ,
923+ async ( req , res , next ) => {
924+ const listId = Number ( req . params . listId ) ;
925+ if ( ! listId || Number . isNaN ( listId ) ) {
926+ return next ( { status : 400 , message : 'Invalid list ID.' } ) ;
927+ }
928+
929+ // same helper as in /trending etc.
930+ const tmdb = createTmdbWithRegionLanguage ( req . user ) ;
931+ const language = ( req . query . language as string ) ?? req . locale ;
932+ const page = req . query . page ? Number ( req . query . page ) || 1 : 1 ;
933+
934+ try {
935+ let data : { results : any [ ] } | null = null ;
936+
937+ // 1) v3: all items come without pagination
938+ try {
939+ const v3 = await tmdb . getList ( { listId, language } ) ;
940+ data = v3 ;
941+ } catch {
942+ data = null ;
943+ }
944+
945+ // 2) fallback to v4 if v3 is empty or failed
946+ if ( ! data || ! Array . isArray ( data . results ) || data . results . length === 0 ) {
947+ // use the existing Axios instance of the TMDB client (proxy/timeouts are preserved)
948+ const axiosInstance : any = ( tmdb as any ) . axios ;
949+ const v4Url = `https://api.themoviedb.org/4/list/${ listId } ` ;
950+
951+ try {
952+ const resp = await axiosInstance . get ( v4Url , {
953+ params : { page, language } ,
954+ } ) ;
955+
956+ const v4 = resp . data as {
957+ page ?: number ;
958+ total_pages ?: number ;
959+ total_results ?: number ;
960+ results ?: { id : number ; media_type : string } [ ] ;
961+ } ;
962+
963+ const media = await Media . getRelatedMedia (
964+ req . user ,
965+ ( v4 . results ?? [ ] ) . map ( ( r ) => r . id )
966+ ) ;
967+
968+ const mappedResults = ( v4 . results ?? [ ] ) . map ( ( r ) => {
969+ switch ( r . media_type ) {
970+ case 'movie' :
971+ return mapMovieResult (
972+ r as any ,
973+ media . find (
974+ ( m ) => m . tmdbId === r . id && m . mediaType === MediaType . MOVIE
975+ )
976+ ) ;
977+ case 'tv' :
978+ return mapTvResult (
979+ r as any ,
980+ media . find (
981+ ( m ) => m . tmdbId === r . id && m . mediaType === MediaType . TV
982+ )
983+ ) ;
984+ case 'person' :
985+ return mapPersonResult ( r as any ) ;
986+ default :
987+ return mapCollectionResult ( r as any ) ;
988+ }
989+ } ) ;
990+
991+ return res . status ( 200 ) . json ( {
992+ page : v4 . page ?? 1 ,
993+ totalPages : v4 . total_pages ?? 1 ,
994+ totalResults : mappedResults . length ,
995+ results : mappedResults ,
996+ } ) ;
997+ } catch {
998+ // if v4 also fails → continue to empty response below
999+ }
1000+ }
1001+
1002+ // 3) return v3 data if available
1003+ if ( data && Array . isArray ( data . results ) && data . results . length > 0 ) {
1004+ const media = await Media . getRelatedMedia (
1005+ req . user ,
1006+ data . results . map ( ( r ) => r . id )
1007+ ) ;
1008+
1009+ const mappedResults = data . results . map ( ( result ) =>
1010+ isMovie ( result )
1011+ ? mapMovieResult (
1012+ result ,
1013+ media . find (
1014+ ( m ) =>
1015+ m . tmdbId === result . id && m . mediaType === MediaType . MOVIE
1016+ )
1017+ )
1018+ : isPerson ( result )
1019+ ? mapPersonResult ( result )
1020+ : isCollection ( result )
1021+ ? mapCollectionResult ( result )
1022+ : mapTvResult (
1023+ result ,
1024+ media . find (
1025+ ( m ) => m . tmdbId === result . id && m . mediaType === MediaType . TV
1026+ )
1027+ )
1028+ ) ;
1029+
1030+ return res . status ( 200 ) . json ( {
1031+ page : 1 ,
1032+ totalPages : 1 ,
1033+ totalResults : mappedResults . length ,
1034+ results : mappedResults ,
1035+ } ) ;
1036+ }
1037+
1038+ // 4) both paths empty → return empty response
1039+ return res . status ( 200 ) . json ( {
1040+ page : 1 ,
1041+ totalPages : 1 ,
1042+ totalResults : 0 ,
1043+ results : [ ] ,
1044+ } ) ;
1045+ } catch ( err ) {
1046+ logger . debug ( 'TMDB list slider failed' , {
1047+ label : 'API' ,
1048+ errorMessage : ( err as Error ) . message ,
1049+ listId : req . params . listId ,
1050+ } ) ;
1051+ return res . status ( 200 ) . json ( {
1052+ page : 1 ,
1053+ totalPages : 1 ,
1054+ totalResults : 0 ,
1055+ results : [ ] ,
1056+ } ) ;
1057+ }
1058+ }
1059+ ) ;
1060+
9201061export default discoverRoutes ;
0 commit comments