Spaces:
Sleeping
Sleeping
File size: 6,390 Bytes
e557560 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
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' });
}
};
|