From c94dcdd9e677383cae6b3dd45b3932000e02770c Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Wed, 16 Aug 2023 06:31:49 +0200 Subject: [PATCH] Updated Radical to support Top Web Models. --- seeds/01_networks.js | 4 +++- seeds/02_sites.js | 34 +++++++++++++++++++++++++++++----- src/scrapers/radical.js | 35 +++++++++++++++++++++-------------- src/scrapers/scrapers.js | 4 +--- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/seeds/01_networks.js b/seeds/01_networks.js index 3757cb4d..8678d26d 100755 --- a/seeds/01_networks.js +++ b/seeds/01_networks.js @@ -645,7 +645,9 @@ const networks = [ url: 'https://tour.topwebmodels.com', parent: 'radical', parameters: { - apiKey: '5b637cd8c4bc59cd13686f1c38dcb780', + layout: 'api', + endpoint: '7D_7bQ7peaFQgjlOR42GH', + videos: 'scenes', }, }, { diff --git a/seeds/02_sites.js b/seeds/02_sites.js index c154b98a..dc5829c1 100755 --- a/seeds/02_sites.js +++ b/seeds/02_sites.js @@ -12630,12 +12630,18 @@ const sites = [ url: 'https://tour.2girls1camera.com', tags: ['mff'], parent: 'topwebmodels', + parameters: { + endpoint: '_r8q_DPFFq1t6g2An0LUa', + }, }, { name: 'Big Gulp Girls', slug: 'biggulpgirls', url: 'https://tour.biggulpgirls.com', parent: 'topwebmodels', + parameters: { + endpoint: '1giYR59O0Hj_gBpbtJ1NW', + }, }, { name: 'Cougar Season', @@ -12643,6 +12649,9 @@ const sites = [ url: 'https://tour.cougarseason.com', tags: ['milf'], parent: 'topwebmodels', + parameters: { + endpoint: 'zSv_brH-xMuozSL2lXAwx', + }, }, { name: 'Deepthroat Sirens', @@ -12650,6 +12659,9 @@ const sites = [ url: 'https://tour.deepthroatsirens.com', tags: ['blowjob', 'deepthroat'], parent: 'topwebmodels', + parameters: { + endpoint: 'JhRuO-OyNdYL3lE4XnnTS', + }, }, { name: 'Facials Forever', @@ -12657,43 +12669,55 @@ const sites = [ url: 'https://tour.facialsforever.com', tags: ['facial'], parent: 'topwebmodels', + parameters: { + endpoint: 'crF0a1UtcQq45zZA5qJhe', + }, }, { name: 'Pounded Petite', slug: 'poundedpetite', url: 'https://tour.poundedpetite.com', parent: 'topwebmodels', + parameters: { + endpoint: '92M2TzHR4YFz5Qs_rZoFL', + }, }, { name: 'She\'s Brand New', slug: 'shesbrandnew', url: 'https://tour.shesbrandnew.com', parent: 'topwebmodels', + parameters: { + endpoint: 'VBqp_fYIkEWdVjfPyD_K0', + }, }, { name: 'TWM Classics', slug: 'twmclassics', - url: 'https://tour.topwebmodels.com/sites/twmclassics', + url: 'https://tour.topwebmodels.com/sites/twmclassics.com', parent: 'topwebmodels', + parameters: { + site: 'twmclassics.com', + }, }, { name: 'TWM Interviews', slug: 'twminterviews', - url: 'https://tour.topwebmodels.com/sites/topwebmodels-interviews', + url: 'https://tour.topwebmodels.com/sites/topwebmodels-interviews.com', tags: ['bts'], parent: 'topwebmodels', hasLogo: false, parameters: { - slug: 'topwebmodels-interviews', + site: 'topwebmodels-interviews.com', }, }, { name: 'TWM Porn Vault', slug: 'twmpornvault', - url: 'https://tour.topwebmodels.com/sites/twm-porn-vault', + url: 'https://tour.topwebmodels.com/sites/twm-porn-vault.com', parent: 'topwebmodels', parameters: { - slug: 'twm-porn-vault', + site: 'twm-porn-vault.com', }, }, // TRANS BELLA diff --git a/src/scrapers/radical.js b/src/scrapers/radical.js index d5a5b883..ea12d4bb 100755 --- a/src/scrapers/radical.js +++ b/src/scrapers/radical.js @@ -54,11 +54,11 @@ function scrapeAllMetadata(scenes, channel) { return scenes.map((data) => scrapeSceneMetadata(data, channel)); } -function scrapeSceneApi(data, channel) { +function scrapeSceneApi(data, channel, parameters) { const release = {}; 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.description = data.description; @@ -71,19 +71,22 @@ function scrapeSceneApi(data, channel) { avatar: actor.thumb, })) || data.models; - release.poster = data.trailer_screencap; + release.poster = data.trailer_screencap || data.thumb; release.photos = [ ...data.previews?.full || [], ...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('_player') && release.poster?.includes('_player'))) || [], + && !(thumbnail.includes('_player') && release.poster?.includes('_player')) + && !(thumbnail.includes('1920') && release.poster?.includes('1920'))) || [], ]; release.caps = data.thumbs; 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; @@ -95,8 +98,8 @@ function scrapeSceneApi(data, channel) { return release; } -function scrapeAllApi(scenes, channel) { - return scenes.map((data) => scrapeSceneApi(data, channel)); +function scrapeAllApi(scenes, channel, parameters) { + return scenes.map((data) => scrapeSceneApi(data, channel, parameters)); } function scrapeProfileMetadata(data, channel) { @@ -124,7 +127,7 @@ function scrapeProfileMetadata(data, channel) { return profile; } -function scrapeProfileApi(data, channel, scenes) { +function scrapeProfileApi(data, channel, scenes, parameters) { const profile = {}; 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; if (scenes) { - profile.scenes = scrapeAllApi(scenes, channel); + profile.scenes = scrapeAllApi(scenes, channel, parameters); } return profile; } 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) { - return scrapeAllApi(res.body.pageProps.contents.data, channel); + return scrapeAllApi(res.body.pageProps.contents.data, channel, parameters); } return res.status; @@ -167,10 +174,10 @@ async function fetchLatestApi(channel, page, { parameters }) { async function fetchSceneApi(url, channel, baseScene, { parameters }) { 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) { - return scrapeSceneApi(res.body.pageProps.content, channel); + return scrapeSceneApi(res.body.pageProps.content, channel, parameters); } 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}`); 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; diff --git a/src/scrapers/scrapers.js b/src/scrapers/scrapers.js index 624d6175..f266a8df 100755 --- a/src/scrapers/scrapers.js +++ b/src/scrapers/scrapers.js @@ -63,7 +63,7 @@ const teencoreclub = require('./teencoreclub'); const teenmegaworld = require('./teenmegaworld'); const testedefudelidade = require('./testedefudelidade'); const tokyohot = require('./tokyohot'); -const topwebmodels = require('./topwebmodels'); +// const topwebmodels = require('./topwebmodels'); const traxxx = require('./traxxx'); const vivid = require('./vivid'); const vixen = require('./vixen'); @@ -158,7 +158,6 @@ const scrapers = { teamskeet, testedefudelidade, tokyohot, - topwebmodels, transbella: porndoe, traxxx, vipsexvault: porndoe, @@ -301,7 +300,6 @@ const scrapers = { testedefudelidade, thatsitcomshow: nubiles, tokyohot, - topwebmodels, transangels: mindgeek, transbella: porndoe, tranzvr: wankzvr,