Added Jay's POV scraper.
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 61 KiB |
|
@ -50,6 +50,11 @@ const networks = [
|
|||
url: 'https://evilangel.com',
|
||||
description: 'Welcome to the award winning Evil Angel website, home to the most popular pornstars of today, yesterday and tomorrow in their most extreme and hardcore porn scenes to date. We feature almost 30 years of rough sex videos and hardcore anal porn like you\'ve never seen before, and have won countless AVN and XBiz awards including \'Best Site\' and \'Best Studio\'.',
|
||||
},
|
||||
{
|
||||
slug: 'jayrock',
|
||||
name: 'JayRock Productions',
|
||||
url: 'https://www.jayrockcontent.com',
|
||||
},
|
||||
{
|
||||
slug: 'julesjordan',
|
||||
name: 'Jules Jordan',
|
||||
|
|
|
@ -1142,6 +1142,13 @@ function getSites(networksMap) {
|
|||
parameters: JSON.stringify({ independent: true }),
|
||||
network_id: networksMap.evilangel,
|
||||
},
|
||||
// JAYS POV
|
||||
{
|
||||
slug: 'jayspov',
|
||||
name: 'Jay\'s POV',
|
||||
url: 'https://www.jayspov.net',
|
||||
network_id: networksMap.jayrock,
|
||||
},
|
||||
// JULES JORDAN
|
||||
{
|
||||
slug: 'julesjordan',
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"strict": 0,
|
||||
"no-unused-vars": ["error", {"argsIgnorePattern": "^_"}],
|
||||
"no-console": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"indent": "off",
|
||||
"template-curly-spacing": "off",
|
||||
"max-len": [2, {"code": 300, "tabWidth": 4, "ignoreUrls": true}],
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
'use strict';
|
||||
|
||||
const Promise = require('bluebird');
|
||||
const bhttp = require('bhttp');
|
||||
|
||||
const slugify = require('../utils/slugify');
|
||||
|
||||
async function fetchToken() {
|
||||
const res = await bhttp.get('https://jayspov.net/activity');
|
||||
const html = res.body.toString();
|
||||
|
||||
const time = html.match(/"aet":\d+/)[0].split(':')[1];
|
||||
const ah = html.match(/"ah":"[\w-]+"/)[0].split(':')[1].slice(1, -1);
|
||||
const token = ah.split('').reverse().join('');
|
||||
|
||||
return { time, token };
|
||||
}
|
||||
|
||||
async function fetchActors(entryId, { token, time }) {
|
||||
const url = `https://jayspov.net/sapi/${token}/${time}/model.getModelContent?_method=model.getModelContent&tz=1&fields[0]=modelId.stageName&fields[1]=_last&fields[2]=modelId.upsellLink&fields[3]=modelId.upsellText&limit=25&transitParameters[contentId]=${entryId}`;
|
||||
const res = await bhttp.get(url);
|
||||
|
||||
if (res.statusCode === 200 && res.body.status === true) {
|
||||
return Object.values(res.body.response.collection).map(actor => Object.values(actor.modelId.collection)[0].stageName);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
async function fetchTrailerLocation(entryId) {
|
||||
const url = `https://jayspov.net/api/download/${entryId}/hd1080/stream`;
|
||||
const res = await bhttp.get(url, {
|
||||
followRedirects: false,
|
||||
});
|
||||
|
||||
if (res.statusCode === 302) {
|
||||
return res.headers.location;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function scrapeScene(scene, site, tokens) {
|
||||
const release = {
|
||||
entryId: scene.id,
|
||||
title: scene.title,
|
||||
duration: scene.length,
|
||||
tokens, // attach tokens to reduce number of requests required for deep fetching
|
||||
site,
|
||||
};
|
||||
|
||||
release.url = `https://jayspov.net/scene/${release.entryId}/${slugify(release.title, true)}`;
|
||||
release.date = new Date(scene.sites.collection[scene.id].publishDate);
|
||||
release.poster = scene._resources.primary[0].url;
|
||||
|
||||
if (scene.tags) release.tags = Object.values(scene.tags.collection).map(tag => tag.alias);
|
||||
if (scene._resources.base) release.photos = scene._resources.base.map(resource => resource.url);
|
||||
|
||||
const [actors, trailer] = await Promise.all([
|
||||
fetchActors(release.entryId, tokens),
|
||||
fetchTrailerLocation(release.entryId),
|
||||
]);
|
||||
|
||||
release.actors = actors;
|
||||
if (trailer) release.trailer = { src: trailer, quality: 1080 };
|
||||
|
||||
return release;
|
||||
}
|
||||
|
||||
function scrapeLatest(scenes, site, tokens) {
|
||||
return Promise.map(scenes, async scene => scrapeScene(scene, site, tokens), { concurrency: 10 });
|
||||
}
|
||||
|
||||
async function fetchLatest(site) {
|
||||
const { time, token } = await fetchToken();
|
||||
|
||||
const url = `https://jayspov.net/sapi/${token}/${time}/content.load?fields[0]=generatedContentLink&fields[1]=cName&fields[2]=title&fields[3]=_resources.primary.url&fields[4]=sites.publishDate&fields[5]=type&fields[6]=_resources.base.url&fields[7]=_resources.base&fields[8]=length&limit=7&metaFields[resources][thumb]=baseline.sprite.w225i&transitParameters[showOnHome]=true&transitParameters[v1]=OhUOlmasXD&transitParameters[v2]=OhUOlmasXD&transitParameters[preset]=videos`;
|
||||
const res = await bhttp.get(url);
|
||||
|
||||
if (res.statusCode === 200 && res.body.status) {
|
||||
return scrapeLatest(res.body.response.collection, site, { time, token });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function fetchScene(url, site, release) {
|
||||
const { time, token } = release?.tokens || await fetchToken(); // use attached tokens when deep fetching
|
||||
const { pathname } = new URL(url);
|
||||
const entryId = pathname.split('/')[2];
|
||||
|
||||
const res = await bhttp.get(`https://jayspov.net/sapi/${token}/${time}/content.load?_method=content.load&tz=1&filter[id][fields][0]=id&filter[id][values][0]=${entryId}&fields[0]=type&fields[1]=title&fields[2]=sites.publishDate&fields[3]=member&fields[4]=id&fields[5]=tags._last&fields[6]=tags.alias&fields[7]=tags&fields[8]=description&fields[9]=related.relatedContentId.id&fields[10]=related.relatedContentId.title&fields[11]=siteProps.ubs.joinUrl&fields[12]=extender.contentId&fields[13]=vr&fields[14]=backLinkProp.value&fields[15]=backLinkProp.public&limit=1&transitParameters[v1]=ykYa8ALmUD&transitParameters[preset]=scene`);
|
||||
|
||||
if (res.statusCode === 200 && res.body.status) {
|
||||
return scrapeScene(res.body.response.collection[0], site, { time, token });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fetchLatest,
|
||||
fetchScene,
|
||||
};
|
|
@ -7,6 +7,7 @@ const bangbros = require('./bangbros');
|
|||
const blowpass = require('./blowpass');
|
||||
const dogfart = require('./dogfart');
|
||||
const evilangel = require('./evilangel');
|
||||
const jayspov = require('./jayspov');
|
||||
const kink = require('./kink');
|
||||
const mikeadriano = require('./mikeadriano');
|
||||
const mofos = require('./mofos');
|
||||
|
@ -40,6 +41,7 @@ module.exports = {
|
|||
dogfart,
|
||||
dogfartnetwork: dogfart,
|
||||
evilangel,
|
||||
jayspov,
|
||||
julesjordan,
|
||||
kellymadison,
|
||||
kink,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
function slugify(string) {
|
||||
return string.trim().toLowerCase().match(/\w+/g).join('-');
|
||||
function slugify(string, encode = false) {
|
||||
const slug = string.trim().toLowerCase().match(/\w+/g).join('-');
|
||||
|
||||
return encode ? encodeURI(slug) : slug;
|
||||
}
|
||||
|
||||
module.exports = slugify;
|
||||
|
|