Spaces:
Sleeping
Sleeping
| const axios = require('axios'); | |
| const Media = require('../models/Media'); | |
| // 1. GET TRENDING (Lazy Sync: Fetch TMDB -> Save DB -> Return) | |
| exports.getTrending = async (req, res) => { | |
| try { | |
| // Fetch from TMDB | |
| const response = await axios.get(`https://api.themoviedb.org/3/trending/all/day`, { | |
| params: { | |
| api_key: process.env.TMDB_KEY, | |
| region: 'IN' | |
| } | |
| }); | |
| const trendingItems = []; | |
| // Process results | |
| for (const item of response.data.results) { | |
| // Skip incomplete data or people | |
| if (item.media_type === 'person') continue; | |
| const releaseDate = item.release_date || item.first_air_date; | |
| const tmdbId = item.id.toString(); | |
| // Prepare object for DB | |
| const mediaData = { | |
| tmdbId: tmdbId, | |
| title: item.title || item.name, | |
| type: item.media_type, | |
| posterPath: item.poster_path, | |
| backdropPath: item.backdrop_path, | |
| releaseDate: releaseDate ? new Date(releaseDate) : null, | |
| overview: item.overview, | |
| brutaleStats: {popularity : item.popularity, avgRating: item.vote_average, voteCount: item.vote_count}, | |
| }; | |
| // Upsert into DB (Update if exists, Insert if new) | |
| const updatedMedia = await Media.findOneAndUpdate( | |
| { tmdbId: tmdbId }, | |
| mediaData, | |
| { upsert: true, new: true, setDefaultsOnInsert: true } | |
| ); | |
| trendingItems.push(updatedMedia); | |
| } | |
| res.json(trendingItems); | |
| } catch (error) { | |
| console.error("Trending Error:", error.message); | |
| res.status(500).json({ error: 'Failed to fetch trending content' }); | |
| } | |
| }; | |
| exports.getPopular = async (req, res) => { | |
| try { | |
| const page = req.query.page || 1; | |
| // Fetch from TMDB | |
| const response = await axios.get(`https://api.themoviedb.org/3/movie/popular`, { | |
| params: { | |
| api_key: process.env.TMDB_KEY, | |
| page, | |
| region: "IN" | |
| } | |
| }); | |
| const popularItems = []; | |
| for (const item of response.data.results) { | |
| const tmdbId = item.id.toString(); | |
| const mediaData = { | |
| tmdbId: tmdbId, | |
| title: item.title, | |
| type: 'movie', | |
| posterPath: item.poster_path, | |
| backdropPath: item.backdrop_path, | |
| releaseDate: item.release_date ? new Date(item.release_date) : null, | |
| overview: item.overview, | |
| brutaleStats: { | |
| popularity: item.popularity, | |
| avgRating: item.vote_average?.toFixed(1) || "0.0", | |
| voteCount: item.vote_count | |
| } | |
| }; | |
| // Upsert into DB (Insert if new, update if existing) | |
| const updatedMedia = await Media.findOneAndUpdate( | |
| { tmdbId: tmdbId }, | |
| mediaData, | |
| { upsert: true, new: true, setDefaultsOnInsert: true } | |
| ); | |
| popularItems.push(updatedMedia); | |
| } | |
| res.json(popularItems); | |
| } catch (error) { | |
| console.error("Popular Error:", error.message); | |
| res.status(500).json({ error: "Failed to fetch popular movies" }); | |
| } | |
| }; | |
| // 2. GET DETAILS | |
| exports.getMediaDetails = async (req, res) => { | |
| try { | |
| const { id } = req.params; // This is the TMDB ID passed from URL | |
| // Try finding in DB first | |
| let media = await Media.findOne({ tmdbId: id }); | |
| // If not in DB, fetch from TMDB and save | |
| if (!media) { | |
| // We need to know if it's a movie or tv show. | |
| // For this simplified version, we might need to try both or rely on the query param. | |
| // BUT, usually the user clicks from the homepage where we already saved it. | |
| // Let's try fetching as movie first, then TV as fallback. | |
| try { | |
| const tmdbRes = await axios.get(`https://api.themoviedb.org/3/movie/${id}`, { | |
| params: { api_key: process.env.TMDB_KEY } | |
| }); | |
| const item = tmdbRes.data; | |
| media = await Media.create({ | |
| tmdbId: item.id.toString(), | |
| title: item.title, | |
| type: 'movie', | |
| posterPath: item.poster_path, | |
| backdropPath: item.backdrop_path, | |
| releaseDate: item.release_date, | |
| overview: item.overview | |
| }); | |
| } catch (err) { | |
| // Try TV | |
| const tmdbResTv = await axios.get(`https://api.themoviedb.org/3/tv/${id}`, { | |
| params: { api_key: process.env.TMDB_KEY } | |
| }); | |
| const item = tmdbResTv.data; | |
| media = await Media.create({ | |
| tmdbId: item.id.toString(), | |
| title: item.name, | |
| type: 'tv', | |
| posterPath: item.poster_path, | |
| backdropPath: item.backdrop_path, | |
| releaseDate: item.first_air_date, | |
| overview: item.overview | |
| }); | |
| } | |
| } | |
| if (!media) return res.status(404).json({ error: 'Media not found' }); | |
| res.json(media); | |
| } catch (error) { | |
| console.error("Details Error:", error.message); | |
| res.status(404).json({ error: 'Media not found on TMDB or DB' }); | |
| } | |
| }; | |
| // 3. SEARCH (Hybrid) | |
| exports.searchMedia = async (req, res) => { | |
| const query = req.query.q; | |
| if (!query) return res.json([]); | |
| try { | |
| // Search DB (using text index created in Schema) | |
| // Note: Ensure you created the index in MongoDB Atlas or via Schema: MediaSchema.index({ title: 'text' }); | |
| let results = await Media.find( | |
| { $text: { $search: query } }, | |
| { score: { $meta: "textScore" } } | |
| ).sort({ score: { $meta: "textScore" } }).limit(10); | |
| // If few results, fetch TMDB | |
| if (results.length < 5) { | |
| const tmdbRes = await axios.get(`https://api.themoviedb.org/3/search/multi`, { | |
| params: { api_key: process.env.TMDB_KEY, query: query } | |
| }); | |
| const tmdbItems = tmdbRes.data.results | |
| .filter(item => (item.media_type === 'movie' || item.media_type === 'tv') && item.poster_path) | |
| .map(item => ({ | |
| tmdbId: item.id.toString(), | |
| title: item.title || item.name, | |
| posterPath: item.poster_path, | |
| type: item.media_type, | |
| releaseDate: item.release_date || item.first_air_date, | |
| // Temporary object structure for frontend | |
| brutaleStats: { avgRating: 0 } | |
| })); | |
| // Merge results (prevent duplicates) | |
| const existingIds = new Set(results.map(r => r.tmdbId)); | |
| const newItems = tmdbItems.filter(i => !existingIds.has(i.tmdbId)); | |
| results = [...results, ...newItems]; | |
| } | |
| res.json(results); | |
| } catch (error) { | |
| res.status(500).json({ error: 'Search failed' }); | |
| } | |
| }; | |