Compare commits
3 Commits
b719a166d2
...
24178e7b04
Author | SHA1 | Date |
---|---|---|
|
24178e7b04 | |
|
486dbc5613 | |
|
e9cbf5dab2 |
|
@ -6,7 +6,7 @@
|
||||||
<Scroll
|
<Scroll
|
||||||
v-slot="slotProps"
|
v-slot="slotProps"
|
||||||
class="scroll-light banner"
|
class="scroll-light banner"
|
||||||
:style="{ 'background-image': `url(/media/${release.poster.thumbnail})` }"
|
:style="{ 'background-image': release.poster && `url(/media/${release.poster.thumbnail})` }"
|
||||||
:expandable="false"
|
:expandable="false"
|
||||||
>
|
>
|
||||||
<Banner
|
<Banner
|
||||||
|
|
|
@ -179,7 +179,6 @@ module.exports = {
|
||||||
'gangbangcreampie',
|
'gangbangcreampie',
|
||||||
'gloryholesecrets',
|
'gloryholesecrets',
|
||||||
'aziani',
|
'aziani',
|
||||||
'legalporno',
|
|
||||||
[
|
[
|
||||||
'firstanalquest',
|
'firstanalquest',
|
||||||
'doubleviewcasting',
|
'doubleviewcasting',
|
||||||
|
@ -188,6 +187,8 @@ module.exports = {
|
||||||
'silverstonedvd',
|
'silverstonedvd',
|
||||||
'silviasaint',
|
'silviasaint',
|
||||||
],
|
],
|
||||||
|
'legalporno',
|
||||||
|
'pierrewoodman',
|
||||||
'score',
|
'score',
|
||||||
'boobpedia',
|
'boobpedia',
|
||||||
'pornhub',
|
'pornhub',
|
||||||
|
@ -215,6 +216,12 @@ module.exports = {
|
||||||
'sthw-trailer-blacked.ssl-cdn.com',
|
'sthw-trailer-blacked.ssl-cdn.com',
|
||||||
'sthw-trailer-blackedraw.ssl-cdn.com',
|
'sthw-trailer-blackedraw.ssl-cdn.com',
|
||||||
'sthw-trailer-deeper.ssl-cdn.com',
|
'sthw-trailer-deeper.ssl-cdn.com',
|
||||||
|
'streamhw-trailer-vixen.ssl-cdn.com',
|
||||||
|
'streamhw-trailer-tushy.ssl-cdn.com',
|
||||||
|
'streamhw-trailer-tushyraw.ssl-cdn.com',
|
||||||
|
'streamhw-trailer-blacked.ssl-cdn.com',
|
||||||
|
'streamhw-trailer-blackedraw.ssl-cdn.com',
|
||||||
|
'streamhw-trailer-deeper.ssl-cdn.com',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
limits: {
|
limits: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "traxxx",
|
"name": "traxxx",
|
||||||
"version": "1.159.5",
|
"version": "1.159.6",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "traxxx",
|
"name": "traxxx",
|
||||||
"version": "1.159.5",
|
"version": "1.159.6",
|
||||||
"description": "All the latest porn releases in one place",
|
"description": "All the latest porn releases in one place",
|
||||||
"main": "src/app.js",
|
"main": "src/app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 228 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 30 KiB |
|
@ -516,6 +516,11 @@ const networks = [
|
||||||
url: 'https://www.vixen.com',
|
url: 'https://www.vixen.com',
|
||||||
description: 'Vixen.com features the world’s finest cinematic adult films with 4K quality and high-end erotic photography.',
|
description: 'Vixen.com features the world’s finest cinematic adult films with 4K quality and high-end erotic photography.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: 'pierrewoodman',
|
||||||
|
name: 'Pierre Woodman',
|
||||||
|
url: 'http://www.woodmancastingx.com',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
slug: 'xempire',
|
slug: 'xempire',
|
||||||
name: 'XEmpire',
|
name: 'XEmpire',
|
||||||
|
|
|
@ -5833,6 +5833,26 @@ const sites = [
|
||||||
tourId: 9,
|
tourId: 9,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// PIERRE WOODMAN
|
||||||
|
{
|
||||||
|
slug: 'woodmancastingx',
|
||||||
|
name: 'Woodman Casting X',
|
||||||
|
url: 'https://www.woodmancastingx.com',
|
||||||
|
parent: 'pierrewoodman',
|
||||||
|
parameters: {
|
||||||
|
latest: 'https://www.woodmancastingx.com/videos/',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'wakeupnfuck',
|
||||||
|
name: 'Wake Up \'N Fuck',
|
||||||
|
url: 'https://www.wakeupnfuck.com',
|
||||||
|
alias: ['wunf'],
|
||||||
|
parent: 'pierrewoodman',
|
||||||
|
parameters: {
|
||||||
|
latest: 'https://www.wakeupnfuck.com/scene',
|
||||||
|
},
|
||||||
|
},
|
||||||
// PIMP XXX
|
// PIMP XXX
|
||||||
{
|
{
|
||||||
slug: 'drilledxxx',
|
slug: 'drilledxxx',
|
||||||
|
|
|
@ -138,12 +138,13 @@ async function scrapeRelease(baseRelease, entities, type = 'scene') {
|
||||||
logger.verbose(`Fetching ${type} ${baseRelease.url}`);
|
logger.verbose(`Fetching ${type} ${baseRelease.url}`);
|
||||||
|
|
||||||
const scrapedRelease = type === 'scene'
|
const scrapedRelease = type === 'scene'
|
||||||
? await fetchScene(scraper, baseRelease.url, entity, baseRelease, include, null)
|
? await fetchScene(layoutScraper, baseRelease.url, entity, baseRelease, include, null)
|
||||||
: await layoutScraper.fetchMovie(baseRelease.url, entity, baseRelease, include, null);
|
: await layoutScraper.fetchMovie(baseRelease.url, entity, baseRelease, include, null);
|
||||||
|
|
||||||
const mergedRelease = {
|
const mergedRelease = {
|
||||||
...merge(baseRelease, scrapedRelease, {
|
...merge(baseRelease, scrapedRelease, {
|
||||||
dedupeStringsInArrayValues: true,
|
dedupeStringsInArrayValues: true,
|
||||||
|
hardMergeKeys: ['actors', 'poster', 'trailer', 'teaser'],
|
||||||
}),
|
}),
|
||||||
deep: !!scrapedRelease,
|
deep: !!scrapedRelease,
|
||||||
entity,
|
entity,
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const qu = require('../utils/qu');
|
||||||
|
const slugify = require('../utils/slugify');
|
||||||
|
const capitalize = require('../utils/capitalize');
|
||||||
|
|
||||||
|
function removeImageBorder(source) {
|
||||||
|
if (!source) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceNoId = source.replace(/_[a-z0-9]+(_v\d)?\.jpg/, '.jpg');
|
||||||
|
|
||||||
|
return [
|
||||||
|
sourceNoId
|
||||||
|
.replace(/actoravatar_/, 'actoravatarnoborder_')
|
||||||
|
.replace(/scenedefault/, 'scenenoborder'),
|
||||||
|
sourceNoId,
|
||||||
|
source,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapActor(actorEl, query, entity) {
|
||||||
|
const avatar = query.img(actorEl);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: capitalize(query.cnt(actorEl, '.name, .informations p'), { uncapitalize: true }),
|
||||||
|
url: query.url(actorEl, null, 'href', { origin: entity.url }),
|
||||||
|
avatar: removeImageBorder(avatar),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeAll(scenes, channel, discard = true) {
|
||||||
|
return scenes.map(({ query, el }) => {
|
||||||
|
const release = {};
|
||||||
|
|
||||||
|
release.url = query.url(el, null, 'href', { origin: channel.url });
|
||||||
|
const { hostname, pathname } = new URL(release.url);
|
||||||
|
|
||||||
|
release.entryId = pathname.match(/_(\d+)/)?.[1];
|
||||||
|
release.channel = hostname.match(/(\w+)\.com/)?.[1];
|
||||||
|
|
||||||
|
if (discard && release.channel !== channel.slug) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
release.title = query.content('.title, .informations h3');
|
||||||
|
release.duration = query.duration('.duration, .timer');
|
||||||
|
|
||||||
|
release.actors = query.cnt('.sub')?.split(/,\s*/);
|
||||||
|
|
||||||
|
release.poster = removeImageBorder(query.img('.thumb, picture img'));
|
||||||
|
|
||||||
|
return release;
|
||||||
|
}).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeScene({ query, html }, url, entity) {
|
||||||
|
const release = {};
|
||||||
|
|
||||||
|
release.entryId = new URL(url).pathname.match(/_(\d+)/)?.[1];
|
||||||
|
|
||||||
|
const title = query.cnt('.page_title h1, h2');
|
||||||
|
const wunfTitle = title.match(/wunf \d+/i)?.[0];
|
||||||
|
|
||||||
|
release.title = wunfTitle ? wunfTitle.toUpperCase() : title;
|
||||||
|
release.description = query.cnt('.info_container .description');
|
||||||
|
|
||||||
|
release.date = query.date('.info_container .info_line:nth-child(1)', 'YYYY-MM-DD') || query.date('.description', 'DD MMMM YYYY', /\d{1,2} \w+ \d{4}/);
|
||||||
|
release.actors = query.all('.girl_item, .starring .item').map(actorEl => mapActor(actorEl, query, entity));
|
||||||
|
|
||||||
|
release.duration = query.duration('.infos .description');
|
||||||
|
|
||||||
|
if (!release.duration) {
|
||||||
|
const duration = query.cnt('.info_container .info_line:nth-child(2)');
|
||||||
|
|
||||||
|
release.duration = (duration.match(/(\d+) hour/)?.[1] || 0) * 3600
|
||||||
|
+ (duration.match(/(\d+) minutes/)?.[1] || 0) * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
release.tags = query.cnts('.tags a:not(.more_tag)');
|
||||||
|
release.poster = removeImageBorder(html.match(/image: "(.*)"/)?.[1]);
|
||||||
|
|
||||||
|
release.trailer = html.match(/url: "(.*mp4.*)"/g)?.map(src => ({
|
||||||
|
src: src.match(/"(.*)"/)?.[1],
|
||||||
|
quality: Number(src.match(/[-/](\d+)p/)?.[1]),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeProfile({ query }, entity) {
|
||||||
|
const profile = {};
|
||||||
|
|
||||||
|
profile.avatar = removeImageBorder(query.img('.actor img'));
|
||||||
|
profile.nationality = query.cnt('.nationality, .nationnality'); // sic
|
||||||
|
|
||||||
|
profile.scenes = scrapeAll(qu.initAll(query.all('.videos .item')), entity, false);
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchLatest(channel, page) {
|
||||||
|
const res = await qu.getAll(channel.parameters?.latest
|
||||||
|
? `${channel.parameters.latest}?page=${page}`
|
||||||
|
: `${channel.url}/videos?page=${page}`, '.items .scene');
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
return scrapeAll(res.items, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchProfile(baseActor, entity) {
|
||||||
|
const res = await qu.get('https://www.woodmancastingx.com');
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchUrl = qu.prefixUrl(res.html.match(/"(.*searchCompletion\.js)"/)?.[1], 'https://www.woodmancastingx.com');
|
||||||
|
|
||||||
|
if (!searchUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchRes = await qu.get(searchUrl, null, null, { decodeJSON: true });
|
||||||
|
|
||||||
|
if (!searchRes.ok) {
|
||||||
|
return searchRes.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [actorId] = searchRes.body.actors.find(([_actorId, actorName]) => slugify(actorName) === baseActor.slug) || [];
|
||||||
|
|
||||||
|
if (!actorId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actorRes = await qu.get(`https://www.woodmancastingx.com/search/redirection/actors/${actorId}`);
|
||||||
|
|
||||||
|
if (actorRes.ok) {
|
||||||
|
return scrapeProfile(actorRes.item, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return actorRes.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchLatest,
|
||||||
|
scrapeScene,
|
||||||
|
fetchProfile,
|
||||||
|
};
|
|
@ -57,6 +57,7 @@ const pervcity = require('./pervcity');
|
||||||
const porncz = require('./porncz');
|
const porncz = require('./porncz');
|
||||||
const pornhub = require('./pornhub');
|
const pornhub = require('./pornhub');
|
||||||
const pascalssubsluts = require('./pascalssubsluts'); // reserved keyword
|
const pascalssubsluts = require('./pascalssubsluts'); // reserved keyword
|
||||||
|
const pierrewoodman = require('./pierrewoodman');
|
||||||
const pinkyxxx = require('./pinkyxxx');
|
const pinkyxxx = require('./pinkyxxx');
|
||||||
const privateNetwork = require('./private'); // reserved keyword
|
const privateNetwork = require('./private'); // reserved keyword
|
||||||
const puretaboo = require('./puretaboo');
|
const puretaboo = require('./puretaboo');
|
||||||
|
@ -150,6 +151,7 @@ const scrapers = {
|
||||||
pascalssubsluts,
|
pascalssubsluts,
|
||||||
perfectgonzo,
|
perfectgonzo,
|
||||||
pervcity,
|
pervcity,
|
||||||
|
pierrewoodman,
|
||||||
pimpxxx: cherrypimps,
|
pimpxxx: cherrypimps,
|
||||||
pinkyxxx,
|
pinkyxxx,
|
||||||
porncz,
|
porncz,
|
||||||
|
@ -253,6 +255,7 @@ const scrapers = {
|
||||||
pervcity,
|
pervcity,
|
||||||
pervertgallery: fullpornnetwork,
|
pervertgallery: fullpornnetwork,
|
||||||
peternorth: famedigital,
|
peternorth: famedigital,
|
||||||
|
pierrewoodman,
|
||||||
pimpxxx: cherrypimps,
|
pimpxxx: cherrypimps,
|
||||||
letsdoeit: porndoe,
|
letsdoeit: porndoe,
|
||||||
mamacitaz: porndoe,
|
mamacitaz: porndoe,
|
||||||
|
|