211 lines
6.3 KiB
JavaScript
Executable File
211 lines
6.3 KiB
JavaScript
Executable File
'use strict';
|
|
|
|
const unprint = require('unprint');
|
|
|
|
const http = require('../utils/http');
|
|
const slugify = require('../utils/slugify');
|
|
const { feetInchesToCm, lbsToKg } = require('../utils/convert');
|
|
|
|
function scrapeAll(scenes, channel, _options) {
|
|
return scenes.map(({ query }) => {
|
|
const release = {};
|
|
|
|
release.url = query.url('a.scene-title, a.scene-img', { origin: channel.url });
|
|
release.entryId = query.attribute('article[data-scene-id]', 'data-scene-id') || new URL(release.url).pathname.match(/^\/(\d+)/)?.[1];
|
|
|
|
release.title = query.content('.scene-title')?.trim();
|
|
release.duration = query.duration('.scene-length');
|
|
|
|
release.actors = query.content('.scene-performer-names')?.split(/[,&]/).map((actor) => actor.trim());
|
|
|
|
release.poster = query.sourceSet('.screenshot', 'data-srcset');
|
|
|
|
const sceneId = query.attribute('article[data-scene-id]', 'data-scene-id');
|
|
const masterId = query.attribute('article[data-master-id]', 'data-master-id');
|
|
|
|
if (sceneId && masterId) {
|
|
release.teaser = `https://video.adultempire.com/hls/previewscene/${masterId}/${sceneId}/index-f1-v1.m3u8`;
|
|
}
|
|
|
|
return release;
|
|
});
|
|
}
|
|
|
|
const photoRegex = /(\/\w\/\d+\/)\d+/;
|
|
|
|
async function scrapeRelease({ query, html, element }, { url, entity, baseRelease, parameters }) {
|
|
const release = {};
|
|
const type = query.exists('.scene-list-header') ? 'movie' : 'scene';
|
|
|
|
release.entryId = new URL(url).pathname.match(/\/(\d+)/)[1];
|
|
|
|
const title = query.content('.scene-page .description, .video-page .description');
|
|
|
|
if (/^scene \d+$/i.test(title)) {
|
|
release.sceneIndex = unprint.extractNumber(title);
|
|
} else {
|
|
release.title = title;
|
|
}
|
|
|
|
release.date = query.date('.release-date:first-child', 'MMM DD, YYYY', /\w{3} \d{2}, \d{4}/);
|
|
release.duration = query.duration('.release-date:last-child');
|
|
|
|
release.actors = query.all('.video-performer').map((el) => {
|
|
const avatar = unprint.query.img(el, 'img', 'data-bgsrc');
|
|
|
|
return {
|
|
name: unprint.query.content(el, 'span').trim(),
|
|
url: unprint.query.url(el, 'a', { origin: entity.url }),
|
|
avatar: [
|
|
avatar.replace(/\/actor\/\d+/, '/actor/1600'),
|
|
avatar,
|
|
],
|
|
};
|
|
});
|
|
|
|
release.tags = query.contents('.tags a, .categories a');
|
|
release.studio = parameters?.studio === false ? null : slugify(query.content('.studio span:last-child, .studio a'), '');
|
|
|
|
if (type === 'scene') {
|
|
release.director = query.text('.director');
|
|
release.duration = query.number('.release-date:last-child') * 60;
|
|
release.poster = baseRelease?.poster || query.url('link[rel="image_src"]') || query.meta('property="og:image"');
|
|
}
|
|
|
|
if (type === 'movie') {
|
|
release.director = query.content('.director a');
|
|
release.covers = [query.sourceSet('.carousel-item .boxcover-image', 'data-srcset')];
|
|
|
|
release.scenes = scrapeAll(unprint.initAll(element, '#scenes .grid-item'), entity);
|
|
}
|
|
|
|
if (query.exists('.video-title .movie-title')) {
|
|
release.movie = {
|
|
title: query.content('#viewLargeBoxcover .modal-title a'),
|
|
url: query.url('#viewLargeBoxcover .modal-title a', 'href', { origin: entity.url }),
|
|
entryId: query.url('#viewLargeBoxcover .modal-title a')?.match(/(\d+)\//)[1],
|
|
covers: query.imgs('#viewLargeBoxcover #viewLargeBoxcoverCarousel .carousel-item > img'),
|
|
};
|
|
}
|
|
|
|
release.caps = query.imgs('#dv_frames a > img', { attribute: 'data-src' }).map((photo) => [
|
|
photo.replace(photoRegex, (match, path) => `${path}1920`),
|
|
photo.replace(photoRegex, (match, path) => `${path}1280`),
|
|
photo,
|
|
]);
|
|
|
|
const trailerId = html.match(/item: (\d+),/)?.[1];
|
|
|
|
if (trailerId) {
|
|
release.trailer = `https://trailer.adultempire.com/hls/trailer/${trailerId}/master.m3u8`;
|
|
}
|
|
|
|
if (query.exists('.user-actions .btn-4k')) {
|
|
release.qualities = [2160];
|
|
}
|
|
|
|
return release;
|
|
}
|
|
|
|
async function scrapeProfile({ query }) {
|
|
const profile = {};
|
|
|
|
const bio = query.contents('#profileModal .well li').reduce((acc, info) => {
|
|
const [key, value] = info.split(':');
|
|
|
|
return {
|
|
...acc,
|
|
[slugify(key, '_')]: value.trim(),
|
|
};
|
|
}, {});
|
|
|
|
const bioText = query.content('#profileModal .well');
|
|
|
|
profile.description = query.content('#profileModal .modal-body')
|
|
.slice(bioText.length)
|
|
.replace(/Biography Text ©Adult DVD Empire/i, '')
|
|
.trim();
|
|
|
|
profile.measurements = bio.measurements?.replace(/["\s]+/g, '');
|
|
|
|
profile.hair = bio.hair;
|
|
profile.eyes = bio.eyes;
|
|
profile.ethnicity = bio.ethnicity;
|
|
|
|
profile.height = feetInchesToCm(bio.height);
|
|
profile.weight = lbsToKg(bio.weight);
|
|
|
|
const avatar = query.img('picture img, .performer-image-container img');
|
|
|
|
if (avatar) {
|
|
profile.avatar = [
|
|
avatar
|
|
.replace('_bust', '_body')
|
|
.replace(/\/actor\/\d+\//i, '/actor/1000/'),
|
|
avatar,
|
|
];
|
|
}
|
|
|
|
return profile;
|
|
}
|
|
|
|
async function fetchLatest(channel, page, options) {
|
|
// const res = await qu.getAll(`${channel.url}/watch-newest-clips-and-scenes.html?page=${page}&hybridview=member`, '.item-grid-scene .grid-item');
|
|
const res = await unprint.get(options.parameters?.latest
|
|
? `${options.parameters.latest}?page=${page}&view=grid`
|
|
: `${channel.url}/watch-newest-clips-and-scenes.html?page=${page}&view=grid`, { selectAll: '.item-grid-scene .grid-item' });
|
|
|
|
if (res.ok) {
|
|
return scrapeAll(res.context, channel, options);
|
|
}
|
|
|
|
return res.status;
|
|
}
|
|
|
|
async function fetchProfilePage(actorUrl) {
|
|
const res = await unprint.get(actorUrl, {
|
|
select: '#content',
|
|
rejectUnauthorized: false,
|
|
});
|
|
|
|
if (res.ok) {
|
|
return scrapeProfile(res.context);
|
|
}
|
|
|
|
return res.status;
|
|
}
|
|
|
|
async function fetchProfile(baseActor, channel, include) {
|
|
if (baseActor.url) {
|
|
const profile = await fetchProfilePage(baseActor, channel, include);
|
|
|
|
if (typeof profile === 'object') {
|
|
return profile;
|
|
}
|
|
}
|
|
|
|
const searchRes = await http.get(`https://www.adultempire.com/search/SearchAutoComplete_Agg_EmpireDTRank?search_type=Pornstars&rows=9&name_startsWith=${slugify(baseActor.name, '+')}`);
|
|
|
|
if (searchRes.ok && searchRes.body.Results) {
|
|
const actorResult = searchRes.body.Results.find((result) => /performer/i.test(result.BasicResponseGroup?.displaytype) && new RegExp(baseActor.name, 'i').test(result.BasicResponseGroup?.description));
|
|
|
|
if (actorResult) {
|
|
const url = `https://www.adultempire.com/${actorResult.BasicResponseGroup.id}`;
|
|
|
|
return fetchProfilePage(url);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return searchRes.status;
|
|
}
|
|
|
|
module.exports = {
|
|
fetchLatest,
|
|
// fetchMovies,
|
|
fetchProfile,
|
|
scrapeScene: scrapeRelease,
|
|
scrapeMovie: scrapeRelease,
|
|
};
|