p-4 / lib /buddy.js
Kyouka's picture
Create buddy.js
e501333 verified
const { Source, RunnerScraper, Hoster } = require("source-scraper-core");
const { PuppeteerRunner } = require("source-scraper-puppeteer-runner");
const cheerio = require("cheerio");
const u = require("url");
class NinexbuddySource extends Source {
constructor(source) {
super(source);
this.quality = source.quality;
}
}
function parseSourceQuality(raw) {
const ar1 = /^([a-zA-Z\d]+)\s*-\s*(\d+)([a-zA-Z]+)?$/i.exec(raw);
if (ar1 !== null && ar1.length >= 4)
return {
raw,
description: ar1[1],
value: Number(ar1[2]),
unit: ar1[3]
};
const ar2 = /^(\d+)([a-zA-Z]+)\s*\(?([a-zA-Z\s]+)\)?$/i.exec(raw);
if (ar2 !== null && ar2.length >= 3)
return {
raw,
description: ar2[3],
value: Number(ar2[1]),
unit: ar2[2]
};
}
function parseHosterName(raw) {
const ar = /^(?:embed\s*-)?\s*([a-zA-Z\d.]+)$/i.exec(raw.trim());
if (ar === null || ar.length < 2)
return;
return ar[ar.length - 1];
}
function isDefined(value) {
return typeof value !== 'undefined';
}
class NinexbuddyScraper extends RunnerScraper {
constructor() {
super();
this.name = 'ninexbuddy';
this.domains = [];
this.urlPattern = /.*/i;
this.runner = new PuppeteerRunner();
this.defaultOptions = {
runnerOptions: {
navigationOptions: {
waitUntil: 'networkidle0'
}
}
};
}
transformUrl(url) {
return `https://9xbuddy.com/process?url=${url}`;
}
async execWithArgs({ page, url: ninexbuddyUrl }) {
const isHoster = !!(await page.$('.playlist_el').catch(() => false));
if (isHoster) {
const items = await page.$$('.playlist_el .text-blue');
const hosters = (await Promise.all(items.map(async (item) => {
const urlPromise = item.getProperty('href').then(async (e) => e.jsonValue()).catch(() => undefined);
const namePromise = item.getProperty('textContent').then(async (e) => e.jsonValue()).catch(() => undefined);
const [url, name] = await Promise.all([urlPromise, namePromise]);
const hosterUrl = u.parse(url, true).query.url;
if (!hosterUrl)
return;
const parsed = name ? parseHosterName(name) : undefined;
if (!parsed)
return;
return new Hoster({
url: hosterUrl,
name: parsed,
});
}))).filter(isDefined);
return {
ninexbuddyUrl,
hosters
};
} else {
const selector = '.tracking-wide.items-center.night-white';
const items = await page.$$(selector);
const sources = (await Promise.all(items.map(async (item) => {
const formatPromise = item.$eval('.w-24.text-blue', e => e.textContent).catch(() => undefined);
const qualityPromise = item.$eval('.w-1\\/2', e => e.textContent).catch(() => undefined);
const urlPromise = item.$eval('.leading-normal.sm\\:leading-none', e => e.getAttribute('href')).catch(() => undefined);
const [format, quality, url] = await Promise.all([formatPromise, qualityPromise, urlPromise]);
if (!url)
return;
return new NinexbuddySource({
url,
quality: quality ? parseSourceQuality(quality) : undefined,
type: format || undefined,
codec: undefined
});
}))).filter(isDefined);
const poster = await page.$eval('img.shadow.border-2.border-grey-lighter.h-48', e => e.src).catch(() => undefined);
return {
ninexbuddyUrl,
title: await page.title(),
poster: poster && !poster.startsWith('data:image') ? poster : undefined,
sources
};
}
}
}
module.exports = {
NinexbuddySource,
NinexbuddyScraper
}