forked from DebaucheryLibrarian/traxxx
Updated Radical to support Top Web Models.
This commit is contained in:
parent
46c514f530
commit
c94dcdd9e6
|
@ -645,7 +645,9 @@ const networks = [
|
||||||
url: 'https://tour.topwebmodels.com',
|
url: 'https://tour.topwebmodels.com',
|
||||||
parent: 'radical',
|
parent: 'radical',
|
||||||
parameters: {
|
parameters: {
|
||||||
apiKey: '5b637cd8c4bc59cd13686f1c38dcb780',
|
layout: 'api',
|
||||||
|
endpoint: '7D_7bQ7peaFQgjlOR42GH',
|
||||||
|
videos: 'scenes',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -12630,12 +12630,18 @@ const sites = [
|
||||||
url: 'https://tour.2girls1camera.com',
|
url: 'https://tour.2girls1camera.com',
|
||||||
tags: ['mff'],
|
tags: ['mff'],
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: '_r8q_DPFFq1t6g2An0LUa',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Big Gulp Girls',
|
name: 'Big Gulp Girls',
|
||||||
slug: 'biggulpgirls',
|
slug: 'biggulpgirls',
|
||||||
url: 'https://tour.biggulpgirls.com',
|
url: 'https://tour.biggulpgirls.com',
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: '1giYR59O0Hj_gBpbtJ1NW',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Cougar Season',
|
name: 'Cougar Season',
|
||||||
|
@ -12643,6 +12649,9 @@ const sites = [
|
||||||
url: 'https://tour.cougarseason.com',
|
url: 'https://tour.cougarseason.com',
|
||||||
tags: ['milf'],
|
tags: ['milf'],
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: 'zSv_brH-xMuozSL2lXAwx',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Deepthroat Sirens',
|
name: 'Deepthroat Sirens',
|
||||||
|
@ -12650,6 +12659,9 @@ const sites = [
|
||||||
url: 'https://tour.deepthroatsirens.com',
|
url: 'https://tour.deepthroatsirens.com',
|
||||||
tags: ['blowjob', 'deepthroat'],
|
tags: ['blowjob', 'deepthroat'],
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: 'JhRuO-OyNdYL3lE4XnnTS',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Facials Forever',
|
name: 'Facials Forever',
|
||||||
|
@ -12657,43 +12669,55 @@ const sites = [
|
||||||
url: 'https://tour.facialsforever.com',
|
url: 'https://tour.facialsforever.com',
|
||||||
tags: ['facial'],
|
tags: ['facial'],
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: 'crF0a1UtcQq45zZA5qJhe',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Pounded Petite',
|
name: 'Pounded Petite',
|
||||||
slug: 'poundedpetite',
|
slug: 'poundedpetite',
|
||||||
url: 'https://tour.poundedpetite.com',
|
url: 'https://tour.poundedpetite.com',
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: '92M2TzHR4YFz5Qs_rZoFL',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'She\'s Brand New',
|
name: 'She\'s Brand New',
|
||||||
slug: 'shesbrandnew',
|
slug: 'shesbrandnew',
|
||||||
url: 'https://tour.shesbrandnew.com',
|
url: 'https://tour.shesbrandnew.com',
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
endpoint: 'VBqp_fYIkEWdVjfPyD_K0',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'TWM Classics',
|
name: 'TWM Classics',
|
||||||
slug: 'twmclassics',
|
slug: 'twmclassics',
|
||||||
url: 'https://tour.topwebmodels.com/sites/twmclassics',
|
url: 'https://tour.topwebmodels.com/sites/twmclassics.com',
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
|
parameters: {
|
||||||
|
site: 'twmclassics.com',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'TWM Interviews',
|
name: 'TWM Interviews',
|
||||||
slug: 'twminterviews',
|
slug: 'twminterviews',
|
||||||
url: 'https://tour.topwebmodels.com/sites/topwebmodels-interviews',
|
url: 'https://tour.topwebmodels.com/sites/topwebmodels-interviews.com',
|
||||||
tags: ['bts'],
|
tags: ['bts'],
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
hasLogo: false,
|
hasLogo: false,
|
||||||
parameters: {
|
parameters: {
|
||||||
slug: 'topwebmodels-interviews',
|
site: 'topwebmodels-interviews.com',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'TWM Porn Vault',
|
name: 'TWM Porn Vault',
|
||||||
slug: 'twmpornvault',
|
slug: 'twmpornvault',
|
||||||
url: 'https://tour.topwebmodels.com/sites/twm-porn-vault',
|
url: 'https://tour.topwebmodels.com/sites/twm-porn-vault.com',
|
||||||
parent: 'topwebmodels',
|
parent: 'topwebmodels',
|
||||||
parameters: {
|
parameters: {
|
||||||
slug: 'twm-porn-vault',
|
site: 'twm-porn-vault.com',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// TRANS BELLA
|
// TRANS BELLA
|
||||||
|
|
|
@ -54,11 +54,11 @@ function scrapeAllMetadata(scenes, channel) {
|
||||||
return scenes.map((data) => scrapeSceneMetadata(data, channel));
|
return scenes.map((data) => scrapeSceneMetadata(data, channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeSceneApi(data, channel) {
|
function scrapeSceneApi(data, channel, parameters) {
|
||||||
const release = {};
|
const release = {};
|
||||||
|
|
||||||
release.entryId = data.id;
|
release.entryId = data.id;
|
||||||
release.url = `${channel.url}/videos/${data.slug}`;
|
release.url = `${channel.url}/${parameters.videos || 'videos'}/${data.slug}`;
|
||||||
|
|
||||||
release.title = data.title;
|
release.title = data.title;
|
||||||
release.description = data.description;
|
release.description = data.description;
|
||||||
|
@ -71,19 +71,22 @@ function scrapeSceneApi(data, channel) {
|
||||||
avatar: actor.thumb,
|
avatar: actor.thumb,
|
||||||
})) || data.models;
|
})) || data.models;
|
||||||
|
|
||||||
release.poster = data.trailer_screencap;
|
release.poster = data.trailer_screencap || data.thumb;
|
||||||
|
|
||||||
release.photos = [
|
release.photos = [
|
||||||
...data.previews?.full || [],
|
...data.previews?.full || [],
|
||||||
...data.extra_thumbnails?.filter((thumbnail) => !thumbnail.includes('mobile') // mobile is the cropped photo of a photo already in the set
|
...data.extra_thumbnails?.filter((thumbnail) => !thumbnail.includes('mobile') // mobile is the cropped photo of a photo already in the set
|
||||||
&& !(thumbnail.includes('_scene') && release.poster?.includes('_scene')) // likely the same photo, filename may differ so cannot compare full path
|
&& !(thumbnail.includes('_scene') && release.poster?.includes('_scene')) // likely the same photo, filename may differ so cannot compare full path
|
||||||
&& !(thumbnail.includes('_player') && release.poster?.includes('_player'))) || [],
|
&& !(thumbnail.includes('_player') && release.poster?.includes('_player'))
|
||||||
|
&& !(thumbnail.includes('1920') && release.poster?.includes('1920'))) || [],
|
||||||
];
|
];
|
||||||
|
|
||||||
release.caps = data.thumbs;
|
release.caps = data.thumbs;
|
||||||
|
|
||||||
release.trailer = data.trailer_url;
|
release.trailer = data.trailer_url;
|
||||||
release.teaser = data.special_thumbnails.sort((teaserA, teaserB) => teaserOrder.findIndex((label) => teaserA.includes(label)) - teaserOrder.findIndex((label) => teaserB.includes(label)));
|
release.teaser = data.special_thumbnails
|
||||||
|
?.filter((teaserUrl) => new URL(teaserUrl).pathname !== '/') // on Top Web Models, https://z7n5n3m8.ssl.hwcdn.net/ is listed as a teaser
|
||||||
|
.sort((teaserA, teaserB) => teaserOrder.findIndex((label) => teaserA.includes(label)) - teaserOrder.findIndex((label) => teaserB.includes(label)));
|
||||||
|
|
||||||
release.tags = data.tags;
|
release.tags = data.tags;
|
||||||
|
|
||||||
|
@ -95,8 +98,8 @@ function scrapeSceneApi(data, channel) {
|
||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeAllApi(scenes, channel) {
|
function scrapeAllApi(scenes, channel, parameters) {
|
||||||
return scenes.map((data) => scrapeSceneApi(data, channel));
|
return scenes.map((data) => scrapeSceneApi(data, channel, parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeProfileMetadata(data, channel) {
|
function scrapeProfileMetadata(data, channel) {
|
||||||
|
@ -124,7 +127,7 @@ function scrapeProfileMetadata(data, channel) {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeProfileApi(data, channel, scenes) {
|
function scrapeProfileApi(data, channel, scenes, parameters) {
|
||||||
const profile = {};
|
const profile = {};
|
||||||
const bio = Object.fromEntries(Object.entries(data).map(([key, value]) => [key.toLowerCase(), value])); // keys are mixed upper and lowercase
|
const bio = Object.fromEntries(Object.entries(data).map(([key, value]) => [key.toLowerCase(), value])); // keys are mixed upper and lowercase
|
||||||
|
|
||||||
|
@ -149,17 +152,21 @@ function scrapeProfileApi(data, channel, scenes) {
|
||||||
profile.avatar = data.thumb;
|
profile.avatar = data.thumb;
|
||||||
|
|
||||||
if (scenes) {
|
if (scenes) {
|
||||||
profile.scenes = scrapeAllApi(scenes, channel);
|
profile.scenes = scrapeAllApi(scenes, channel, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchLatestApi(channel, page, { parameters }) {
|
async function fetchLatestApi(channel, page, { parameters }) {
|
||||||
const res = await http.get(`${channel.url}/_next/data/${parameters.endpoint}/videos.json?order_by=publish_date&sort_by=desc&per_page=8&page=${page}`);
|
const url = parameters.site
|
||||||
|
? `${channel.parent.url}/_next/data/${parameters.endpoint}/sites/${parameters.site}.json?sitename=${parameters.site}&order_by=publish_date&sort_by=desc&per_page=30&page=${page}`
|
||||||
|
: `${channel.url}/_next/data/${parameters.endpoint}/${parameters.videos || 'videos'}.json?order_by=publish_date&sort_by=desc&per_page=30&page=${page}`;
|
||||||
|
|
||||||
|
const res = await http.get(url);
|
||||||
|
|
||||||
if (res.ok && res.body.pageProps?.contents?.data) {
|
if (res.ok && res.body.pageProps?.contents?.data) {
|
||||||
return scrapeAllApi(res.body.pageProps.contents.data, channel);
|
return scrapeAllApi(res.body.pageProps.contents.data, channel, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status;
|
return res.status;
|
||||||
|
@ -167,10 +174,10 @@ async function fetchLatestApi(channel, page, { parameters }) {
|
||||||
|
|
||||||
async function fetchSceneApi(url, channel, baseScene, { parameters }) {
|
async function fetchSceneApi(url, channel, baseScene, { parameters }) {
|
||||||
const slug = new URL(url).pathname.split('/').at(-1);
|
const slug = new URL(url).pathname.split('/').at(-1);
|
||||||
const res = await http.get(`${channel.url}/_next/data/${parameters.endpoint}/videos/${slug}.json?slug=${slug}`);
|
const res = await http.get(`${channel.url}/_next/data/${parameters.endpoint}/${parameters.videos || 'videos'}/${slug}.json?slug=${slug}`);
|
||||||
|
|
||||||
if (res.ok && res.body.pageProps?.content) {
|
if (res.ok && res.body.pageProps?.content) {
|
||||||
return scrapeSceneApi(res.body.pageProps.content, channel);
|
return scrapeSceneApi(res.body.pageProps.content, channel, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status;
|
return res.status;
|
||||||
|
@ -180,7 +187,7 @@ async function fetchProfileApi(actor, { channel, parameters }) {
|
||||||
const res = await http.get(`${channel.url}/_next/data/${parameters.endpoint}/models/${actor.slug}.json?slug=${actor.slug}`);
|
const res = await http.get(`${channel.url}/_next/data/${parameters.endpoint}/models/${actor.slug}.json?slug=${actor.slug}`);
|
||||||
|
|
||||||
if (res.ok && res.body.pageProps?.model) {
|
if (res.ok && res.body.pageProps?.model) {
|
||||||
return scrapeProfileApi(res.body.pageProps.model, channel, res.body.pageProps.model_contents);
|
return scrapeProfileApi(res.body.pageProps.model, channel, res.body.pageProps.model_contents, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status;
|
return res.status;
|
||||||
|
|
|
@ -63,7 +63,7 @@ const teencoreclub = require('./teencoreclub');
|
||||||
const teenmegaworld = require('./teenmegaworld');
|
const teenmegaworld = require('./teenmegaworld');
|
||||||
const testedefudelidade = require('./testedefudelidade');
|
const testedefudelidade = require('./testedefudelidade');
|
||||||
const tokyohot = require('./tokyohot');
|
const tokyohot = require('./tokyohot');
|
||||||
const topwebmodels = require('./topwebmodels');
|
// const topwebmodels = require('./topwebmodels');
|
||||||
const traxxx = require('./traxxx');
|
const traxxx = require('./traxxx');
|
||||||
const vivid = require('./vivid');
|
const vivid = require('./vivid');
|
||||||
const vixen = require('./vixen');
|
const vixen = require('./vixen');
|
||||||
|
@ -158,7 +158,6 @@ const scrapers = {
|
||||||
teamskeet,
|
teamskeet,
|
||||||
testedefudelidade,
|
testedefudelidade,
|
||||||
tokyohot,
|
tokyohot,
|
||||||
topwebmodels,
|
|
||||||
transbella: porndoe,
|
transbella: porndoe,
|
||||||
traxxx,
|
traxxx,
|
||||||
vipsexvault: porndoe,
|
vipsexvault: porndoe,
|
||||||
|
@ -301,7 +300,6 @@ const scrapers = {
|
||||||
testedefudelidade,
|
testedefudelidade,
|
||||||
thatsitcomshow: nubiles,
|
thatsitcomshow: nubiles,
|
||||||
tokyohot,
|
tokyohot,
|
||||||
topwebmodels,
|
|
||||||
transangels: mindgeek,
|
transangels: mindgeek,
|
||||||
transbella: porndoe,
|
transbella: porndoe,
|
||||||
tranzvr: wankzvr,
|
tranzvr: wankzvr,
|
||||||
|
|
Loading…
Reference in New Issue