// Author: fruit.com.cn const FALLBACK_IMAGE = '/assets/hero.jpg'; const MEDIA_BASE_URL = (import.meta.env.VITE_MEDIA_BASE_URL || '').replace(/\/$/, ''); const getText = (value, lang = 'id') => (typeof value === 'string' ? value : value?.[lang] || value?.en || value?.id || value?.zh || ''); const resolveMedia = (value) => value ? (/^https?:\/\//.test(value) ? value : `${MEDIA_BASE_URL}${value}`) : FALLBACK_IMAGE; const getImage = (item) => resolveMedia(item.coverLandscape || item.coverUrl || item.cover || item.posterUrl || item.imageUrl); export function normalizeDrama(item, lang = 'id') { const id = String(item.id ?? item.dramaId ?? item.code ?? ''); const episodes = item.episodes || item.episodeList || (item.preview ? [item.preview] : []); const preview = item.preview || episodes[0] || null; return { id, title: getText(item.titleLocales || item.locales || item.title, lang) || item.name || 'YMB Drama', channel: getText(item.channelLocales || item.channel, lang) || item.creatorName || 'YMB Originals', genre: getText(item.categoryLocales || item.genre, lang) || getText(item.types?.[0], lang), image: getImage(item), duration: item.duration || preview?.duration || '', views: item.views || item.viewCount || '', episodes: episodes.map((episode) => ({ ...episode, playUrl: resolveMedia(episode.playUrl) })), preview: preview ? { ...preview, playUrl: resolveMedia(preview.playUrl) } : null }; } export function normalizePage(payload) { if (Array.isArray(payload)) return { total: payload.length, list: payload }; return { total: payload?.total || 0, list: payload?.list || payload?.records || [] }; } export function resolvePlaybackUrl(value) { return resolveMedia(value); } export function uniqueDramas(items) { const seen = new Set(); return items.filter((item) => { if (seen.has(item.id)) return false; seen.add(item.id); return true; }); } export function selectPlaybackUrl(playback, fallback = '') { const tracks = playback?.tracks || []; const preferred = tracks.find((track) => track.quality === '360p') || tracks.find((track) => track.quality === 'AUTO') || tracks[0]; return resolveMedia(preferred?.playUrl || playback?.playUrl || fallback); }