/***
@ 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
};
}
};