Spaces:
Sleeping
Sleeping
File size: 3,205 Bytes
4bea261 | 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 | import { getLocalMovies } from '../../../lib/localDb.js';
// Cấu hình timeout cho fetch
async function fetchWithTimeout(resource, options = {}) {
const { timeout = 8000 } = options;
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(resource, {
...options,
signal: controller.signal
});
return response;
} finally {
clearTimeout(id);
}
}
export async function GET({ request }) {
// Check quyền admin từ cookie auth_token
const cookies = request.headers.get('cookie') || '';
const hasToken = cookies.includes('auth_token=');
if (!hasToken) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
}
const url = new URL(request.url);
const keyword = url.searchParams.get('keyword') || '';
if (!keyword.trim()) {
return new Response(JSON.stringify({ items: [], APP_DOMAIN_CDN_IMAGE: '' }), {
headers: { 'Content-Type': 'application/json' }
});
}
try {
// 1. Gọi API tìm kiếm trực tuyến của KKPhim
const kkRes = await fetchWithTimeout(
`https://phimapi.com/v1/api/tim-kiem?keyword=${encodeURIComponent(keyword)}&limit=40`
);
if (!kkRes.ok) {
throw new Error(`API KKPhim trả về HTTP ${kkRes.status}`);
}
const searchData = await kkRes.json();
if (searchData.status !== 'success') {
throw new Error(searchData.message || 'Lỗi API KKPhim');
}
const items = searchData.data?.items || [];
const imageDomain = searchData.data?.APP_DOMAIN_CDN_IMAGE || 'https://phimimg.com';
// 2. Load phim cục bộ để đối chiếu
const localMovies = await getLocalMovies();
// 3. Map kết quả đối chiếu
const mappedItems = items.map(item => {
const existing = localMovies[item.slug];
let localEpCount = 0;
if (existing && Array.isArray(existing.episodes)) {
localEpCount = Math.max(...existing.episodes.map(s => s.server_data?.length || 0), 0);
}
return {
name: item.name,
origin_name: item.origin_name,
slug: item.slug,
type: item.type,
thumb_url: item.thumb_url.startsWith('http') ? item.thumb_url : `${imageDomain}/${item.thumb_url}`,
poster_url: item.poster_url.startsWith('http') ? item.poster_url : `${imageDomain}/${item.poster_url}`,
year: item.year || 'N/A',
episode_current: item.episode_current || 'N/A',
exists: !!existing,
local_episode_count: localEpCount,
existing_status: existing ? (existing.movie.status || 'N/A') : null,
existing_episodes: existing && Array.isArray(existing.episodes)
? existing.episodes.flatMap(s => s.server_data?.map(ep => ep.name) || [])
: []
};
});
return new Response(JSON.stringify({
items: mappedItems,
APP_DOMAIN_CDN_IMAGE: imageDomain
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (err) {
return new Response(JSON.stringify({ error: err.message }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
|