mirror of
https://github.com/p-stream/p-stream.git
synced 2026-04-21 14:52:18 +00:00
new trakt /discover endpoint for featured carousel
This commit is contained in:
parent
0f1ce2811f
commit
eaf2399539
2 changed files with 108 additions and 48 deletions
|
|
@ -29,6 +29,12 @@ export type TraktContentType = "movie" | "episode";
|
||||||
|
|
||||||
export const TRAKT_BASE_URL = "https://fed-airdate.pstream.org";
|
export const TRAKT_BASE_URL = "https://fed-airdate.pstream.org";
|
||||||
|
|
||||||
|
export interface TraktDiscoverResponse {
|
||||||
|
movie_tmdb_ids: number[];
|
||||||
|
tv_tmdb_ids: number[];
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
// Pagination utility
|
// Pagination utility
|
||||||
export function paginateResults(
|
export function paginateResults(
|
||||||
results: TraktLatestResponse,
|
results: TraktLatestResponse,
|
||||||
|
|
@ -47,7 +53,9 @@ export function paginateResults(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base function to fetch from Trakt API
|
// Base function to fetch from Trakt API
|
||||||
async function fetchFromTrakt(endpoint: string): Promise<TraktLatestResponse> {
|
async function fetchFromTrakt<T = TraktLatestResponse>(
|
||||||
|
endpoint: string,
|
||||||
|
): Promise<T> {
|
||||||
const response = await fetch(`${TRAKT_BASE_URL}${endpoint}`);
|
const response = await fetch(`${TRAKT_BASE_URL}${endpoint}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Failed to fetch from ${endpoint}: ${response.statusText}`);
|
throw new Error(`Failed to fetch from ${endpoint}: ${response.statusText}`);
|
||||||
|
|
@ -94,6 +102,10 @@ export const getDramaReleases = () => fetchFromTrakt("/drama");
|
||||||
export const getPopularTVShows = () => fetchFromTrakt("/populartv");
|
export const getPopularTVShows = () => fetchFromTrakt("/populartv");
|
||||||
export const getPopularMovies = () => fetchFromTrakt("/popularmovies");
|
export const getPopularMovies = () => fetchFromTrakt("/popularmovies");
|
||||||
|
|
||||||
|
// Discovery content
|
||||||
|
export const getDiscoverContent = () =>
|
||||||
|
fetchFromTrakt<TraktDiscoverResponse>("/discover");
|
||||||
|
|
||||||
// Type conversion utilities
|
// Type conversion utilities
|
||||||
export function convertToMediaType(type: TraktContentType): MWMediaType {
|
export function convertToMediaType(type: TraktContentType): MWMediaType {
|
||||||
return type === "movie" ? MWMediaType.MOVIE : MWMediaType.SERIES;
|
return type === "movie" ? MWMediaType.MOVIE : MWMediaType.SERIES;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { isExtensionActive } from "@/backend/extension/messaging";
|
||||||
import { get, getMediaLogo } from "@/backend/metadata/tmdb";
|
import { get, getMediaLogo } from "@/backend/metadata/tmdb";
|
||||||
import {
|
import {
|
||||||
TraktReleaseResponse,
|
TraktReleaseResponse,
|
||||||
|
getDiscoverContent,
|
||||||
getReleaseDetails,
|
getReleaseDetails,
|
||||||
} from "@/backend/metadata/traktApi";
|
} from "@/backend/metadata/traktApi";
|
||||||
import { TMDBContentTypes } from "@/backend/metadata/types/tmdb";
|
import { TMDBContentTypes } from "@/backend/metadata/types/tmdb";
|
||||||
|
|
@ -202,60 +203,107 @@ export function FeaturedCarousel({
|
||||||
logoFetchController.current.abort(); // Cancel any in-progress logo fetches
|
logoFetchController.current.abort(); // Cancel any in-progress logo fetches
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (effectiveCategory === "movies") {
|
if (effectiveCategory === "movies" || effectiveCategory === "tvshows") {
|
||||||
// First get the list of popular movies
|
// First try to get IDs from Trakt discover endpoint
|
||||||
const listData = await get<any>("/movie/popular", {
|
try {
|
||||||
api_key: conf().TMDB_READ_API_KEY,
|
const discoverData = await getDiscoverContent();
|
||||||
language: formattedLanguage,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Then fetch full details for each movie to get external_ids
|
let tmdbIds: number[] = [];
|
||||||
const moviePromises = listData.results
|
if (effectiveCategory === "movies") {
|
||||||
.slice(0, FETCH_QUANTITY)
|
tmdbIds = discoverData.movie_tmdb_ids;
|
||||||
.map((movie: any) =>
|
} else {
|
||||||
get<any>(`/movie/${movie.id}`, {
|
tmdbIds = discoverData.tv_tmdb_ids;
|
||||||
api_key: conf().TMDB_READ_API_KEY,
|
}
|
||||||
language: formattedLanguage,
|
|
||||||
append_to_response: "external_ids",
|
// Then fetch full details for each movie/show to get external_ids
|
||||||
}),
|
const detailPromises = tmdbIds.map((id) =>
|
||||||
|
get<any>(
|
||||||
|
`/${effectiveCategory === "movies" ? "movie" : "tv"}/${id}`,
|
||||||
|
{
|
||||||
|
api_key: conf().TMDB_READ_API_KEY,
|
||||||
|
language: formattedLanguage,
|
||||||
|
append_to_response: "external_ids",
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const movieDetails = await Promise.all(moviePromises);
|
const details = await Promise.all(detailPromises);
|
||||||
const allMovies = movieDetails.map((movie) => ({
|
const mediaItems = details.map((item) => ({
|
||||||
...movie,
|
...item,
|
||||||
type: "movie" as const,
|
type:
|
||||||
}));
|
effectiveCategory === "movies" ? "movie" : ("show" as const),
|
||||||
|
}));
|
||||||
|
|
||||||
// Shuffle
|
// Take the first SLIDE_QUANTITY items
|
||||||
const shuffledMovies = [...allMovies].sort(() => 0.5 - Math.random());
|
setMedia(mediaItems.slice(0, SLIDE_QUANTITY));
|
||||||
setMedia(shuffledMovies.slice(0, SLIDE_QUANTITY));
|
} catch (traktError) {
|
||||||
} else if (effectiveCategory === "tvshows") {
|
console.error(
|
||||||
// First get the list of popular shows
|
"Falling back to TMDB method",
|
||||||
const listData = await get<any>("/tv/popular", {
|
"Error fetching from Trakt discover:",
|
||||||
api_key: conf().TMDB_READ_API_KEY,
|
traktError,
|
||||||
language: formattedLanguage,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Then fetch full details for each show to get external_ids
|
|
||||||
const showPromises = listData.results
|
|
||||||
.slice(0, FETCH_QUANTITY)
|
|
||||||
.map((show: any) =>
|
|
||||||
get<any>(`/tv/${show.id}`, {
|
|
||||||
api_key: conf().TMDB_READ_API_KEY,
|
|
||||||
language: formattedLanguage,
|
|
||||||
append_to_response: "external_ids",
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const showDetails = await Promise.all(showPromises);
|
// Fallback to TMDB method
|
||||||
const allShows = showDetails.map((show) => ({
|
if (effectiveCategory === "movies") {
|
||||||
...show,
|
// First get the list of popular movies
|
||||||
type: "show" as const,
|
const listData = await get<any>("/movie/popular", {
|
||||||
}));
|
api_key: conf().TMDB_READ_API_KEY,
|
||||||
|
language: formattedLanguage,
|
||||||
|
});
|
||||||
|
|
||||||
// Shuffle
|
// Then fetch full details for each movie to get external_ids
|
||||||
const shuffledShows = [...allShows].sort(() => 0.5 - Math.random());
|
const moviePromises = listData.results
|
||||||
setMedia(shuffledShows.slice(0, SLIDE_QUANTITY));
|
.slice(0, FETCH_QUANTITY)
|
||||||
|
.map((movie: any) =>
|
||||||
|
get<any>(`/movie/${movie.id}`, {
|
||||||
|
api_key: conf().TMDB_READ_API_KEY,
|
||||||
|
language: formattedLanguage,
|
||||||
|
append_to_response: "external_ids",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const movieDetails = await Promise.all(moviePromises);
|
||||||
|
const allMovies = movieDetails.map((movie) => ({
|
||||||
|
...movie,
|
||||||
|
type: "movie" as const,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Shuffle
|
||||||
|
const shuffledMovies = [...allMovies].sort(
|
||||||
|
() => 0.5 - Math.random(),
|
||||||
|
);
|
||||||
|
setMedia(shuffledMovies.slice(0, SLIDE_QUANTITY));
|
||||||
|
} else if (effectiveCategory === "tvshows") {
|
||||||
|
// First get the list of popular shows
|
||||||
|
const listData = await get<any>("/tv/popular", {
|
||||||
|
api_key: conf().TMDB_READ_API_KEY,
|
||||||
|
language: formattedLanguage,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then fetch full details for each show to get external_ids
|
||||||
|
const showPromises = listData.results
|
||||||
|
.slice(0, FETCH_QUANTITY)
|
||||||
|
.map((show: any) =>
|
||||||
|
get<any>(`/tv/${show.id}`, {
|
||||||
|
api_key: conf().TMDB_READ_API_KEY,
|
||||||
|
language: formattedLanguage,
|
||||||
|
append_to_response: "external_ids",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const showDetails = await Promise.all(showPromises);
|
||||||
|
const allShows = showDetails.map((show) => ({
|
||||||
|
...show,
|
||||||
|
type: "show" as const,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Shuffle
|
||||||
|
const shuffledShows = [...allShows].sort(
|
||||||
|
() => 0.5 - Math.random(),
|
||||||
|
);
|
||||||
|
setMedia(shuffledShows.slice(0, SLIDE_QUANTITY));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (effectiveCategory === "editorpicks") {
|
} else if (effectiveCategory === "editorpicks") {
|
||||||
// Shuffle editor picks Ids
|
// Shuffle editor picks Ids
|
||||||
const allMovieIds = EDITOR_PICKS_MOVIES.map((item) => ({
|
const allMovieIds = EDITOR_PICKS_MOVIES.map((item) => ({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue