const axios = require('axios');
const cheerio = require('cheerio');
async function getSeriesDetail(url) {
try {
const baseUrl = 'https://xbato.com';
const response = await axios.get(url);
const $ = cheerio.load(response.data);
const container = $('.container-max-width-xl');
const title = container.find('.title-set h3.item-title a').text().trim();
const aliases = container.find('.alias-set').text().trim()
.split('/').map(a => a.trim()).filter(Boolean);
const thumbnail = container.find('.attr-cover img').attr('src');
const authors = [];
container.find('.attr-item b:contains("Authors:")').next().find('a').each((i, el) => {
authors.push($(el).text().trim());
});
const artists = [];
container.find('.attr-item b:contains("Artists:")').next().find('a').each((i, el) => {
artists.push($(el).text().trim());
});
const genres = [];
container.find('.attr-item b:contains("Genres:")').next().children().each((i, el) => {
genres.push($(el).text().trim());
});
const language = container.find('.attr-item b:contains("Original language:")').next().text().trim();
const translated = container.find('.attr-item b:contains("Translated language:")').next().text().trim();
const status = container.find('.attr-item b:contains("Original work:")').next().text().trim();
const uploadStatus = container.find('.attr-item b:contains("Upload status:")').next().text().trim();
const year = container.find('.attr-item b:contains("Year of Release:")').next().text().trim();
const summary = container.find('.limit-html').text().trim();
const chapters = [];
$('.item').each((i, el) => {
const chapterEl = $(el);
const chapterPath = chapterEl.find('a.visited.chapt').attr('href');
const chapterUrl = baseUrl + chapterPath;
const chapterTitle = chapterEl.find('a.visited.chapt b').text().trim();
const uploaderEl = chapterEl.find('.extra a.ps-3');
const uploaderName = uploaderEl.find('span').text().trim();
const uploaderPath = uploaderEl.attr('href');
const uploaderUrl = baseUrl + uploaderPath;
const uploaderAvatar = uploaderEl.find('img').attr('src');
const viewsRaw = chapterEl.find('.extra span.ps-3 i').map((i, el) => $(el).text().trim()).get();
const views = viewsRaw.join(' ');
const uploadDate = chapterEl.find('.extra i.ps-3').text().trim();
chapters.push({
title: chapterTitle,
url: chapterUrl,
views,
uploadDate
});
});
return {
title,
aliases,
thumbnail,
authors,
artists,
genres,
language,
translated,
status,
uploadStatus,
year,
summary,
chapters
};
} catch (err) {
console.error('Error saat mengambil detail seri:', err.message);
return null;
}
}
async function getChapterImages(url) {
try {
const response = await axios.get(url);
const $ = cheerio.load(response.data);
const scriptContent = $('script')
.map((_, el) => $(el).html())
.get()
.find(text => text.includes('const imgHttps'));
const imgRegex = /const imgHttps\s*=\s*(\[[^\]]+\])/;
const match = imgRegex.exec(scriptContent);
if (!match) throw new Error('imgHttps not found');
const imageArray = eval(match[1]);
return imageArray;
} catch (err) {
console.error('Gagal scrape:', err.message);
return [];
}
}
// contoh getSeriesDetail detail
getSeriesDetail("https://xbato.com/series/99300/can-we-become-family-official")
// contoh penggunaan getChapterImages
getChapterImages("https://xbato.com/chapter/3259300")