124 lines
3.4 KiB
JavaScript
Executable File
124 lines
3.4 KiB
JavaScript
Executable File
'use strict';
|
|
|
|
const unprint = require('unprint');
|
|
|
|
const slugify = require('../utils/slugify');
|
|
|
|
function scrapeLatest(scenes) {
|
|
return scenes.map(({ query }) => {
|
|
const release = {};
|
|
const url = query.url('a');
|
|
|
|
release.url = url;
|
|
release.entryId = query.attribute('a', 'data-scene-id') || (url && new URL(url).pathname.match(/-(\d+)$/)?.[1]) || null;
|
|
|
|
release.date = query.date('.entry-date', 'MMM D, YYYY');
|
|
release.duration = query.duration('.scene-runtime');
|
|
|
|
release.actors = query.all('.contain-actors a').map((actorEl) => ({
|
|
name: unprint.query.content(actorEl),
|
|
url: unprint.query.url(actorEl, null),
|
|
}));
|
|
|
|
release.poster = [
|
|
...(query.sourceSet('source[data-srcset*="scenes/"][type="image/jpeg"]', 'data-srcset') || []),
|
|
query.img('.main-scene-img', { attribute: 'data-srcset' }),
|
|
];
|
|
|
|
release.tags = query.contents('.flag-bg');
|
|
|
|
release.qualities = [
|
|
query.exists('//a[contains(@class, "label-four-k") and contains(text(), "4K")]') && 2160, // label-four-k is also used for non-4K tags
|
|
query.exists('//a[contains(@class, "label-hd") and contains(text(), "HD")]') && 720,
|
|
].filter(Boolean);
|
|
|
|
release.channel = slugify(query.content('.site-title'), '');
|
|
|
|
return release;
|
|
});
|
|
}
|
|
|
|
function scrapeScene({ query }, { url }) {
|
|
const release = {};
|
|
release.entryId = new URL(url).pathname.match(/-(\d+)$/)?.[1];
|
|
|
|
release.title = query.content('.scene-title');
|
|
release.description = query.text('.synopsis');
|
|
|
|
release.date = query.date('.entry-date', 'MMM D, YYYY');
|
|
release.duration = query.duration('.duration');
|
|
|
|
release.actors = query.all('.performer-list a').map((actorEl) => ({
|
|
name: unprint.query.content(actorEl),
|
|
url: unprint.query.url(actorEl, null),
|
|
}));
|
|
|
|
release.poster = [
|
|
...(query.sourceSet('source[data-srcset*="scenes/"][type="image/jpeg"]', 'data-srcset') || []),
|
|
query.img('.play-trailer img[data-srcset*="scenes/"]', { attribute: 'data-srcset' }),
|
|
];
|
|
|
|
release.photos = query.els('.contain-scene-images.desktop-only .scene-image').map((imgEl) => [
|
|
unprint.query.url(imgEl, null),
|
|
unprint.query.img(imgEl, 'img', { attribute: 'srcset' }),
|
|
]);
|
|
|
|
const trailer = query.video('video source');
|
|
|
|
if (trailer) {
|
|
release.trailer = [
|
|
{
|
|
source: trailer.replace(/_\d+\.mp4/, '_1080.mp4'),
|
|
quality: 1080,
|
|
},
|
|
trailer,
|
|
];
|
|
}
|
|
|
|
release.channel = slugify(query.content('.site-title'), '');
|
|
|
|
release.tags = query.contents('.categories a');
|
|
|
|
release.qualities = [
|
|
query.exists('//a[contains(@class, "label-four-k") and contains(text(), "4K")]') && 2160, // label-four-k is also used for non-4K tags
|
|
query.exists('img.icon-1080') && 1080,
|
|
query.exists('//a[contains(@class, "label-hd") and contains(text(), "HD")]') && 720,
|
|
].filter(Boolean);
|
|
|
|
return release;
|
|
}
|
|
|
|
async function scrapeProfile({ query }) {
|
|
const profile = {};
|
|
|
|
profile.description = query.content('.bio_about_text');
|
|
profile.avatar = query.img('img.performer-pic');
|
|
|
|
return profile;
|
|
}
|
|
|
|
async function fetchLatest(site, page = 1) {
|
|
const res = await unprint.get(`${site.url}?page=${page}`, { selectAll: '.site-list .scene-item' });
|
|
|
|
return scrapeLatest(res.context, site);
|
|
}
|
|
|
|
async function fetchProfile({ slug }) {
|
|
const res = await unprint.get(`https://www.naughtyamerica.com/pornstar/${slug}`, { select: '.bio-info' });
|
|
|
|
if (res.ok) {
|
|
return scrapeProfile(res.context);
|
|
}
|
|
|
|
return res.status;
|
|
}
|
|
|
|
module.exports = {
|
|
fetchLatest,
|
|
fetchProfile,
|
|
scrapeScene: {
|
|
scraper: scrapeScene,
|
|
unprint: true,
|
|
},
|
|
};
|