Added basic Pascals Subsluts scraper.
| After Width: | Height: | Size: 1.8 KiB | 
| After Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 12 KiB | 
| After Width: | Height: | Size: 12 KiB | 
| After Width: | Height: | Size: 12 KiB | 
| After Width: | Height: | Size: 12 KiB | 
|  | @ -5399,6 +5399,13 @@ const sites = [ | ||||||
| 		tags: ['parody'], | 		tags: ['parody'], | ||||||
| 		parent: 'nubiles', | 		parent: 'nubiles', | ||||||
| 	}, | 	}, | ||||||
|  | 	// PASCALS SUBSLUTS
 | ||||||
|  | 	{ | ||||||
|  | 		slug: 'pascalssubsluts', | ||||||
|  | 		name: 'Pascal\'s Sub Sluts', | ||||||
|  | 		url: 'https://www.pascalssubsluts.com', | ||||||
|  | 		tags: ['rough', 'bdsm'], | ||||||
|  | 	}, | ||||||
| 	// PERFECT GONZO
 | 	// PERFECT GONZO
 | ||||||
| 	{ | 	{ | ||||||
| 		slug: 'allinternal', | 		slug: 'allinternal', | ||||||
|  |  | ||||||
|  | @ -0,0 +1,101 @@ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | const qu = require('../utils/q'); | ||||||
|  | const capitalize = require('../utils/capitalize'); | ||||||
|  | 
 | ||||||
|  | function scrapeAll(months, channel, year) { | ||||||
|  | 	return months.map(({ query: queryMonth, el }) => { | ||||||
|  | 		const month = queryMonth.cnt('h3'); | ||||||
|  | 		const scenes = queryMonth.all(el.nextElementSibling, 'li:nth-child(2n)'); | ||||||
|  | 
 | ||||||
|  | 		return qu.initAll(scenes).map(({ query }) => { | ||||||
|  | 			const release = {}; | ||||||
|  | 
 | ||||||
|  | 			release.url = query.url('a.video-pop-up', 'href', { origin: `${channel.url}/submissive` }); | ||||||
|  | 			release.entryId = new URL(release.url).searchParams.get('id'); | ||||||
|  | 
 | ||||||
|  | 			release.title = query.cnt('.updates-item-title h4'); | ||||||
|  | 
 | ||||||
|  | 			release.date = qu.parseDate(`${month} ${year}`, 'MMMM/YYYY'); | ||||||
|  | 			release.datePrecision = 'month'; | ||||||
|  | 
 | ||||||
|  | 			release.actors = [{ | ||||||
|  | 				name: capitalize(query.q('a.video-pop-up', 'data-modelname'), { uncapitalize: true }), | ||||||
|  | 				url: query.url('a.video-pop-up', 'data-modellink', { origin: `${channel.url}/submissive` }), | ||||||
|  | 			}]; | ||||||
|  | 
 | ||||||
|  | 			release.poster = query.img('img'); | ||||||
|  | 
 | ||||||
|  | 			return release; | ||||||
|  | 		}); | ||||||
|  | 	}).flat(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function scrapeScene({ html }, url) { | ||||||
|  | 	const release = {}; | ||||||
|  | 
 | ||||||
|  | 	release.entryId = new URL(url).searchParams.get('id'); | ||||||
|  | 	release.trailer = html.match(/file: '(.*)'/)[1]; | ||||||
|  | 
 | ||||||
|  | 	return release; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | function scrapeProfile({ query, el }, actorName, entity, include) { | ||||||
|  | 	const profile = {}; | ||||||
|  | 
 | ||||||
|  | 	profile.description = query.cnt('.bio-text'); | ||||||
|  | 	profile.birthPlace = query.cnt('.birth-place span'); | ||||||
|  | 
 | ||||||
|  | 	profile.avatar = query.img('.actor-photo img'); | ||||||
|  | 
 | ||||||
|  | 	if (include.releases) { | ||||||
|  | 		return scrapeAll(qu.initAll(el, '.scene')); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	console.log(profile); | ||||||
|  | 	return profile; | ||||||
|  | } | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | async function fetchLatest(channel, page = 1) { | ||||||
|  | 	const year = new Date().getFullYear() - (page - 1); | ||||||
|  | 
 | ||||||
|  | 	const url = `${channel.url}/submissive/updates.php?y=${year}`; | ||||||
|  | 	const res = await qu.getAll(url, '.month'); | ||||||
|  | 
 | ||||||
|  | 	if (res.ok) { | ||||||
|  | 		return scrapeAll(res.items, channel, year); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return res.status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | async function fetchScene(url, channel) { | ||||||
|  | 	const res = await qu.get(url); | ||||||
|  | 
 | ||||||
|  | 	if (res.ok) { | ||||||
|  | 		return scrapeScene(res.item, url, channel); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return res.status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | async function fetchProfile({ name: actorName }, entity, include) { | ||||||
|  | 	const url = `${entity.url}/actors/${slugify(actorName, '_')}`; | ||||||
|  | 	const res = await qu.get(url); | ||||||
|  | 
 | ||||||
|  | 	if (res.ok) { | ||||||
|  | 		return scrapeProfile(res.item, actorName, entity, include); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return res.status; | ||||||
|  | } | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | module.exports = { | ||||||
|  | 	fetchLatest, | ||||||
|  | 	fetchScene, | ||||||
|  | 	fetchProfile, | ||||||
|  | }; | ||||||
|  | @ -53,6 +53,7 @@ const pervcity = require('./pervcity'); | ||||||
| const porncz = require('./porncz'); | const porncz = require('./porncz'); | ||||||
| const pornhub = require('./pornhub'); | const pornhub = require('./pornhub'); | ||||||
| const whalemember = require('./whalemember'); | const whalemember = require('./whalemember'); | ||||||
|  | const pascalssubsluts = require('./pascalssubsluts'); // reserved keyword
 | ||||||
| const privateNetwork = require('./private'); // reserved keyword
 | const privateNetwork = require('./private'); // reserved keyword
 | ||||||
| const puretaboo = require('./puretaboo'); | const puretaboo = require('./puretaboo'); | ||||||
| const realitykings = require('./realitykings'); | const realitykings = require('./realitykings'); | ||||||
|  | @ -134,6 +135,7 @@ module.exports = { | ||||||
| 		naughtyamerica, | 		naughtyamerica, | ||||||
| 		newsensations, | 		newsensations, | ||||||
| 		nubiles, | 		nubiles, | ||||||
|  | 		pascalssubsluts, | ||||||
| 		perfectgonzo, | 		perfectgonzo, | ||||||
| 		pervcity, | 		pervcity, | ||||||
| 		pimpxxx: cherrypimps, | 		pimpxxx: cherrypimps, | ||||||
|  |  | ||||||
|  | @ -56,6 +56,10 @@ function prefixUrl(urlValue, origin, protocol = 'https') { | ||||||
| 		return `${origin}${urlValue}`; | 		return `${origin}${urlValue}`; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (origin && /^\.\//.test(urlValue)) { | ||||||
|  | 		return `${origin}${urlValue.slice(1)}`; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (origin) { | 	if (origin) { | ||||||
| 		return `${origin}/${urlValue}`; | 		return `${origin}/${urlValue}`; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||