From 9eca44795ff4fa47a397ffbc151c74734a2eeab2 Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Sun, 3 Nov 2024 01:52:49 +0100 Subject: [PATCH] Added PornBox scraper for AnalVids. --- seeds/02_sites.js | 74 ++++++++++++++++- src/scrapers/pornbox.js | 172 +++++++++++++++++++++++++++++++++++++++ src/scrapers/scrapers.js | 9 +- 3 files changed, 251 insertions(+), 4 deletions(-) create mode 100755 src/scrapers/pornbox.js diff --git a/seeds/02_sites.js b/seeds/02_sites.js index e4c193b4..68824ff0 100755 --- a/seeds/02_sites.js +++ b/seeds/02_sites.js @@ -5875,6 +5875,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 29, + }, }, { name: 'Gonzo.com', @@ -5887,6 +5890,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 22, + }, }, { name: 'Porn World', @@ -5896,6 +5902,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 39, + }, }, { name: 'Angelo Godshack Original', @@ -5905,6 +5914,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 251, + }, }, { name: 'NRX-Studio', @@ -5917,6 +5929,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 94, + }, }, { name: "Giorgio's Lab", @@ -5929,6 +5944,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 33, + }, }, { name: 'Yummy estudio', @@ -5941,15 +5959,21 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 111, + }, }, { - name: 'XfreaX', + name: 'XFREAXX', slug: 'xfreax', url: 'https://www.analvids.com/studios/xfreax', parent: 'analvids', showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 200, + }, }, { name: 'Natasha Teen Films', @@ -5962,6 +5986,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 74, + }, }, { name: 'Bang Bros', @@ -5982,6 +6009,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 120, + }, }, { name: 'Toby Dick Studio', @@ -6006,6 +6036,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 91, + }, }, { name: 'TheWonderToys Training Studio', @@ -6026,6 +6059,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 76, + }, }, { name: 'Vira Gold Films', @@ -6051,6 +6087,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 305, + }, }, { name: 'Stalker Prodz', @@ -6068,6 +6107,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 247, + }, }, { name: 'PISSING E ANAL FANTASY', @@ -6097,6 +6139,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 28, + }, }, { name: 'Kinky Sex', @@ -6109,6 +6154,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 64, + }, }, { name: 'Mambo Perv', @@ -6118,6 +6166,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 197, + }, }, { name: 'Studio PL', @@ -6127,6 +6178,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 311, + }, }, { name: 'Interracial Vision', @@ -6139,6 +6193,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 35, + }, }, { name: 'Argendana Official', @@ -6167,6 +6224,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 30, + }, }, { name: 'X-TV Studio', @@ -6240,6 +6300,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 41, + }, }, { name: 'Lydia Black Studio', @@ -6281,6 +6344,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 212, + }, }, { name: 'Black In White', @@ -6293,6 +6359,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 195, + }, }, { name: 'vilevixen Studio', @@ -6541,6 +6610,9 @@ const sites = [ showcased: true, hasLogo: false, visible: true, + parameters: { + studioId: 3, + }, }, { name: 'Porn Force', diff --git a/src/scrapers/pornbox.js b/src/scrapers/pornbox.js new file mode 100755 index 00000000..3897cf8a --- /dev/null +++ b/src/scrapers/pornbox.js @@ -0,0 +1,172 @@ +'use strict'; + +const unprint = require('unprint'); + +const slugify = require('../utils/slugify'); +const { stripQuery } = require('../utils/url'); + +async function getTrailer(data) { + const mediaId = data.medias?.find((media) => media.type === 'free')?.media_id; + + if (!mediaId) { + return null; + } + + const res = await unprint.get(`https://pornbox.com/media/${mediaId}/stream`); + + if (res.ok) { + return res.data.qualities?.map((video) => ({ + src: video.src, + type: video.type, + quality: parseInt(video.size, 10), + })); + } + + return null; +} + +async function scrapeScene(data, channel, include) { + const release = {}; + const entityUrl = new URL(channel.url).origin; + + release.title = data.scene_name || data.custom_name; + + release.entryId = data.id; + release.url = `${entityUrl}/watch/${data.id}/${slugify(release.title, '_')}`; + + release.date = new Date(data.release_date || data.publish_date); + release.duration = unprint.extractDuration(data.runtime); + + release.actors = [...data.models, ...(data.male_models || [])].map((model) => ({ + name: model.model_name, + gender: model.sex, + entryId: model.model_id, + url: `${entityUrl}/model/${model.model_id}/${slugify(model.model_name, '_')}`, + })); + + release.tags = data.niches.map((niche) => niche.niche); + + release.poster = [ + data.player_poster, + data.thumbnail.mosaic, + data.thumbnail.list, + data.thumbnail.large, // squared + data.thumbnail.small, + ]; + + release.photos = data.gallery?.map((photo) => [ + stripQuery(photo.large_thumbnail), + photo.large_thumbnail, + photo.small_thumbnail, + ]); + + release.caps = data.screenshots?.map((screenshot) => [ + screenshot.xga_size, + screenshot.small_thumbnail, + ]); + + release.teaser = data.video_preview; + + if (include?.includeTrailers) { + release.trailer = await getTrailer(data); + release.qualities = release.trailer?.map((src) => src.quality); + } + + if (data.has_4k_full_video && !release.qualities) { + release.qualities = [2160]; + } + + release.studio = slugify(data.studio, ''); + + return release; +} + +function scrapeAll(scenes, channel) { + return Promise.all(scenes.map(async (data) => scrapeScene(data, channel))); +} + +async function fetchLatest(channel, page = 1) { + if (!channel.parameters.studioId) { + return null; + } + + const url = `https://pornbox.com/studio/${channel.parameters.studioId}/?sort=latest&skip=${page}`; // sort=recent is 'sold recently', not latest chronologically + const res = await unprint.get(url); + + if (res.ok && res.data?.contents) { + return scrapeAll(res.data.contents, channel); + } + + return res.status; +} + +async function fetchScene(url, entity, baseRelease, include) { + const entryId = new URL(url).pathname.match(/\/watch(?:-page)?\/(\d+)/)[1]; + const res = await unprint.get(`https://pornbox.com/contents/${entryId}`); + + if (res.ok) { + return scrapeScene(res.data, entity, include); + } + + return res.status; +} + +function scrapeProfile(data) { + const profile = {}; + + profile.age = data.age; + profile.gender = data.sex; + + profile.birthCountry = data.nationality?.[0]?.name; + profile.nationality = data.nationality?.[0]?.nationality; + + profile.aliases = data.stage_name; + + profile.avatar = [ + stripQuery(data.headshot), + data.headshot, + ]; + + return profile; +} + +async function getActorUrl(actor, entity) { + if (actor.url) { + return actor.url; + } + + const res = await unprint.get(`https://pornbox.com/autocomplete/${actor.name}`); + + if (res.ok && Array.isArray(res.data)) { + const model = res.data.find((item) => item.type === 'model' && item.name === actor.name); + + if (model) { + return `${entity.url}/model/${model.id}/${slugify(model.name, '_')}`; + } + } + + return null; +} + +async function fetchProfile(actor, entity) { + const url = await getActorUrl(actor, entity); + + if (!url) { + return null; + } + + const actorId = new URL(url).pathname.match(/\/model\/(\d+)/)[1]; + const res = await unprint.get(`https://pornbox.com/model/info/${actorId}`); + + if (res.ok) { + return scrapeProfile(res.data, entity); + } + + return res.status; +} + +module.exports = { + fetchLatest, + fetchProfile, + fetchScene, +}; diff --git a/src/scrapers/scrapers.js b/src/scrapers/scrapers.js index 4c233767..0e8ce818 100755 --- a/src/scrapers/scrapers.js +++ b/src/scrapers/scrapers.js @@ -38,7 +38,8 @@ const kellymadison = require('./kellymadison'); const killergram = require('./killergram'); const kink = require('./kink'); const mariskax = require('./mariskax'); -const analvids = require('./analvids'); +// const analvids = require('./analvids'); +const pornbox = require('./pornbox'); const littlecapricedreams = require('./littlecapricedreams'); const loveherfilms = require('./loveherfilms'); const bluedonkeymedia = require('./bluedonkeymedia'); @@ -134,7 +135,8 @@ const scrapers = { killergram, kink, kinkvr: badoink, - analvids, + // analvids, + analvids: pornbox, letsdoeit: porndoe, littlecapricedreams, loveherfilms, @@ -266,7 +268,8 @@ const scrapers = { loveherfilms, loveherfeet: loveherfilms, shelovesblack: loveherfilms, - analvids, + // analvids, + analvids: pornbox, letsdoeit: porndoe, littlecapricedreams, mamacitaz: porndoe,