/*** @ Base: https://dramabox.web.id/ @ Author: Shannz @ Note: Short drama, directly using dramaboxdb api server ***/ import axios from 'axios'; import * as cheerio from 'cheerio'; const CONFIG = { BASE_URL: 'https://dramabox.web.id', HEADERS: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } }; const request = async (url) => { try { const response = await axios.get(url, { headers: CONFIG.HEADERS }); return cheerio.load(response.data); } catch (error) { throw new Error(`Network Error: ${error.message}`); } }; const resolveUrl = (link) => { if (link && !link.startsWith('http')) { return `${CONFIG.BASE_URL}/${link.replace(/^\//, '')}`; } return link; }; const getBookIdFromUrl = (url) => { try { const urlObj = new URL(url); return urlObj.searchParams.get('bookId'); } catch (e) { return null; } }; export const dramabox = { home: async () => { const $ = await request(CONFIG.BASE_URL); const latest = []; $('.drama-grid .drama-card').each((_, el) => { const link = resolveUrl($(el).find('.watch-button').attr('href')); latest.push({ title: $(el).find('.drama-title').text().trim(), book_id: getBookIdFromUrl(link), image: $(el).find('.drama-image img').attr('src'), views: $(el).find('.drama-meta span').first().text().trim().split(' ')[1], episodes: $(el).find('.drama-meta span[itemprop="numberOfEpisodes"]').text().trim().split(' ')[1] }); }); const trending = []; $('.sidebar-widget .rank-list .rank-item').each((_, el) => { const link = resolveUrl($(el).attr('href')); trending.push({ rank: $(el).find('.rank-number').text().trim(), title: $(el).find('.rank-title').text().trim(), book_id: getBookIdFromUrl(link), image: $(el).find('.rank-image img').attr('src'), views: $(el).find('.rank-meta span').eq(0).text().trim().split(' ')[1], episodes: $(el).find('.rank-meta span').eq(1).text().trim().split(' ')[1] }); }); return { latest, trending }; }, search: async (query) => { const targetUrl = `${CONFIG.BASE_URL}/search.php?lang=in&q=${encodeURIComponent(query)}`; const $ = await request(targetUrl); const results = []; $('.drama-grid .drama-card').each((_, el) => { const link = resolveUrl($(el).find('.watch-button').attr('href')); results.push({ title: $(el).find('.drama-title').text().trim(), book_id: getBookIdFromUrl(link), views: $(el).find('.drama-meta span').first().text().trim().split(' ')[1], image: $(el).find('.drama-image img').attr('src') }); }); return results; }, detail: async (bookId) => { if (!bookId) throw new Error("Book ID is required"); const targetUrl = `${CONFIG.BASE_URL}/watch.php?bookId=${bookId}&lang=in`; const $ = await request(targetUrl); const fullTitle = $('.video-title').text().trim(); const cleanTitle = fullTitle.split('- Episode')[0].trim(); const episodes = []; $('.episodes-grid .episode-btn').each((_, el) => { episodes.push({ episode: parseInt($(el).text().trim()), id: $(el).attr('data-episode') }); }); return { book_id: bookId, title: cleanTitle, description: $('.video-description').text().trim(), thumbnail: $('meta[itemprop="thumbnailUrl"]').attr('content'), upload_date: $('meta[itemprop="uploadDate"]').attr('content'), stats: { followers: $('.video-meta span').first().text().trim().split(' ')[1], total_episodes: $('span[itemprop="numberOfEpisodes"]').text().trim().split(' ')[1], }, episode_list: episodes }; }, stream: async (bookId, episode) => { if (!bookId || !episode) throw new Error("Book ID and Episode are required"); const targetUrl = `${CONFIG.BASE_URL}/watch.php?bookId=${bookId}&lang=in&episode=${episode}`; const $ = await request(targetUrl); let videoUrl = $('#mainVideo source').attr('src'); if (!videoUrl) videoUrl = $('#mainVideo').attr('src'); return { book_id: bookId, episode: episode, video_url: videoUrl }; } };