Cleaned up Team Skeet config, added missing Say Uncle channels.
This commit is contained in:
parent
a05928e399
commit
b01913690e
|
|
@ -112,6 +112,75 @@ const parentNetworks = [
|
|||
];
|
||||
|
||||
const networks = [
|
||||
// paper street media
|
||||
{
|
||||
slug: 'teamskeet',
|
||||
name: 'Team Skeet',
|
||||
url: 'https://www.teamskeet.com',
|
||||
description: 'Welcome to teamskeet.com, the largest collection of exclusive teen porn sites and videos on the web. Check out our TeamSkeet porn sites now.',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
endpoint: 'ts_network',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'mylf',
|
||||
name: 'MYLF',
|
||||
tags: ['milf'],
|
||||
url: 'https://www.mylf.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
endpoint: 'mylf_bundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'pervz',
|
||||
name: 'Pervz',
|
||||
url: 'https://www.pervz.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
endpoint: 'pervbundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'swappz',
|
||||
name: 'Swappz',
|
||||
url: 'https://www.swappz.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
endpoint: 'swap_bundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'freeuse',
|
||||
name: 'Free Use',
|
||||
url: 'https://www.freeuse.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
endpoint: 'freeusebundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'familystrokes',
|
||||
name: 'Family Strokes',
|
||||
url: 'https://www.familystrokes.com/',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
endpoint: 'familybundle',
|
||||
},
|
||||
},
|
||||
// charged, paper street media sister brand
|
||||
{
|
||||
slug: 'sayuncle',
|
||||
name: 'Say Uncle',
|
||||
url: 'https://www.sayuncle.com',
|
||||
parent: 'chargedmedia',
|
||||
tags: ['gay'],
|
||||
parameters: {
|
||||
endpoint: 'sau_network',
|
||||
},
|
||||
},
|
||||
// etc
|
||||
{
|
||||
slug: '21sextreme',
|
||||
name: '21Sextreme',
|
||||
|
|
@ -612,19 +681,6 @@ const networks = [
|
|||
description: 'Check out the Official Mofos Network of best amateur pornsites. Girlfriend – voyeur - college girls - first anal & more. Bonus Milf sites for wifey lovers.',
|
||||
parent: 'aylo',
|
||||
},
|
||||
{
|
||||
slug: 'mylf',
|
||||
name: 'MYLF',
|
||||
tags: ['milf'],
|
||||
url: 'https://www.mylf.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
layout: 'search',
|
||||
endpoint: 'mylf_bundle',
|
||||
// modelPrefix: 'model_',
|
||||
avatars: 'https://images.mylfcdn.net/tsv4/model/profiles',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'nebraskacoeds',
|
||||
name: 'Nebraska Coeds',
|
||||
|
|
@ -714,18 +770,6 @@ const networks = [
|
|||
parentSession: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'sayuncle',
|
||||
name: 'Say Uncle',
|
||||
url: 'https://www.sayuncle.com',
|
||||
parent: 'chargedmedia',
|
||||
tags: ['gay'],
|
||||
parameters: {
|
||||
// endpoint: 'sau-elastic-00gy5fg5ra',
|
||||
fullEndpoint: 'sau_network',
|
||||
modelPrefix: 'model_',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'score',
|
||||
name: 'SCORE',
|
||||
|
|
@ -750,58 +794,6 @@ const networks = [
|
|||
name: 'Spizoo',
|
||||
url: 'http://www.spizoo.com',
|
||||
},
|
||||
{
|
||||
slug: 'teamskeet',
|
||||
name: 'Team Skeet',
|
||||
url: 'https://www.teamskeet.com',
|
||||
description: 'Welcome to teamskeet.com, the largest collection of exclusive teen porn sites and videos on the web. Check out our TeamSkeet porn sites now.',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
layout: 'search',
|
||||
fullEndpoint: 'ts_network',
|
||||
modelPrefix: 'model_',
|
||||
avatars: 'https://images.mylfcdn.net/tsv4/model/profiles',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'pervz',
|
||||
name: 'Pervz',
|
||||
url: 'https://www.pervz.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
layout: 'search',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'swappz',
|
||||
name: 'Swappz',
|
||||
url: 'https://www.swappz.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
layout: 'search',
|
||||
endpoint: 'swap_bundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'freeuse',
|
||||
name: 'Free Use',
|
||||
url: 'https://www.freeuse.com',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
layout: 'search',
|
||||
endpoint: 'freeusebundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'familystrokes',
|
||||
name: 'Family Strokes',
|
||||
url: 'https://www.familystrokes.com/',
|
||||
parent: 'paperstreetmedia',
|
||||
parameters: {
|
||||
layout: 'search',
|
||||
endpoint: 'familybundle',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'teencoreclub',
|
||||
name: 'Teen Core Club',
|
||||
|
|
|
|||
2027
seeds/02_sites.js
2027
seeds/02_sites.js
File diff suppressed because it is too large
Load Diff
|
|
@ -41,7 +41,7 @@ async function fetchTrailerUrl(videoId, entity) {
|
|||
return null;
|
||||
}
|
||||
|
||||
async function scrapeScene(scene, channel, parameters, includeTrailers) {
|
||||
async function scrapeScene(scene, channel, _parameters, includeTrailers) {
|
||||
const release = {};
|
||||
|
||||
// release.entryId = scene.id; // legacy
|
||||
|
|
@ -53,10 +53,10 @@ async function scrapeScene(scene, channel, parameters, includeTrailers) {
|
|||
release.description = scene.description;
|
||||
release.date = unprint.extractDate(scene.publishedDate, 'YYYY-MM-DD');
|
||||
|
||||
// release.actors = scene.models?.map((model) => model.modelName) || [];
|
||||
release.actors = scene.models?.map((model) => ({
|
||||
name: model.modelName || model.name || model.title,
|
||||
avatar: model.img || (parameters.avatars && `${parameters.avatars}/${slugify(model.modelName || model.name || model.title, '_')}.jpg`),
|
||||
avatar: model.img,
|
||||
gender: model.gender,
|
||||
url: `${channel.url}/models/${model.modelId || model.id}`,
|
||||
}));
|
||||
|
||||
|
|
@ -92,38 +92,12 @@ function scrapeAll(scenes, channel, parameters) {
|
|||
}
|
||||
|
||||
async function fetchLatest(channel, page = 1, { parameters }) {
|
||||
const res = await http.get(`https://tours-store.psmcdn.net/${parameters.fullEndpoint || `${parameters.endpoint}-videoscontent`}/_search?q=site.seo.seoSlug:"${parameters.id}"&sort=publishedDate:desc&size=30&from=${(page - 1) * 30}`);
|
||||
// url: 'https://www.pervz.com/series/pervz-features',
|
||||
const seriesId = parameters.id || new URL(channel.url).pathname.match(/\/series\/([a-z-]+)/)?.[1];
|
||||
|
||||
if (res.ok) {
|
||||
return scrapeAll(res.body.hits.hits.map(({ _source: scene }) => scene), channel, parameters);
|
||||
}
|
||||
|
||||
return res.status;
|
||||
}
|
||||
|
||||
async function fetchLatestOrganic(channel, page, context) {
|
||||
const res = await http.get(`https://store.psmcdn.net/${context.parameters.endpoint}/newestMovies/items.json?orderBy="$key"&startAt="${context.cursor || 'aaaaaaaa'}"&limitToFirst=100`);
|
||||
|
||||
if (res.ok) {
|
||||
const scenes = scrapeAll(Object.values(res.body), channel, context.parameters);
|
||||
|
||||
return {
|
||||
// cursor implies page > 1 and first scene is last scene on previous page,
|
||||
// it probably won't trip up the pagination logic, but avoid the duplicate anyway
|
||||
scenes: context.cursor ? scenes.slice(1) : scenes,
|
||||
context: {
|
||||
cursor: Object.keys(res.body).at(-1), // official page seems to derive cursor from last scene, too
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return res.status;
|
||||
}
|
||||
|
||||
async function fetchLatestSearch(channel, page = 1, { parameters }) {
|
||||
const url = parameters.id
|
||||
? `https://tours-store.psmcdn.net/${parameters.fullEndpoint || parameters.endpoint}/_search?q=(site.seo.seoSlug:"${parameters.id}" AND type:video)&sort=publishedDate:desc&size=30&from=${(page - 1) * 30}`
|
||||
: `https://tours-store.psmcdn.net/${parameters.fullEndpoint || parameters.endpoint}/_search?sort=publishedDate:desc&q=(type:video AND isXSeries:false)&size=30&from=${(page - 1) * 30}`;
|
||||
const url = seriesId
|
||||
? `https://tours-store.psmcdn.net/${parameters.endpoint}/_search?q=(site.seo.seoSlug:"${seriesId}" AND type:video)&sort=publishedDate:desc&size=30&from=${(page - 1) * 30}`
|
||||
: `https://tours-store.psmcdn.net/${parameters.endpoint}/_search?sort=publishedDate:desc&q=(type:video AND isXSeries:false)&size=30&from=${(page - 1) * 30}`;
|
||||
|
||||
const res = await http.get(url);
|
||||
|
||||
|
|
@ -135,7 +109,7 @@ async function fetchLatestSearch(channel, page = 1, { parameters }) {
|
|||
}
|
||||
|
||||
async function fetchScene(url, channel, baseScene, { parameters, includeTrailers }) {
|
||||
if (parameters.layout !== 'organic' && baseScene?.entryId && !includeTrailers) {
|
||||
if (baseScene?.entryId && !includeTrailers) {
|
||||
// overview and deep data is the same in elastic API, don't hit server unnecessarily
|
||||
return baseScene;
|
||||
}
|
||||
|
|
@ -175,6 +149,7 @@ async function scrapeProfile(actor, entity, parameters) {
|
|||
profile.url = `${entity.url}/models/${actor.id}`;
|
||||
|
||||
profile.description = actor.modelBio;
|
||||
profile.gender = actor.gender;
|
||||
|
||||
if (actor.bio.about && !/\band\b/.test(actor.bio.about)) {
|
||||
const bio = actor.bio.about.split(/\n/).filter(Boolean).reduce((acc, item) => {
|
||||
|
|
@ -235,15 +210,11 @@ async function scrapeProfile(actor, entity, parameters) {
|
|||
}
|
||||
|
||||
async function fetchProfile(baseActor, { entity, parameters }) {
|
||||
// const url = format(parameters.profiles, { slug: baseActor.slug });
|
||||
const url = parameters.layout === 'organic'
|
||||
? `https://store.psmcdn.net/${parameters.endpoint}/modelsContent/${baseActor.slug}.json`
|
||||
: `https://tours-store.psmcdn.net/${parameters.fullEndpoint || `${parameters.endpoint}-modelscontent`}/_doc/${parameters.modelPrefix || ''}${baseActor.slug}`;
|
||||
|
||||
const url = `https://tours-store.psmcdn.net/${parameters.endpoint}/_doc/model_${baseActor.slug}`;
|
||||
const res = await unprint.get(url);
|
||||
|
||||
if (res.ok && res.data) {
|
||||
return scrapeProfile(parameters.layout === 'organic' ? res.data : res.data._source || res.body, entity, parameters);
|
||||
return scrapeProfile(res.data._source || res.body, entity, parameters);
|
||||
}
|
||||
|
||||
return res.status;
|
||||
|
|
@ -253,12 +224,4 @@ module.exports = {
|
|||
fetchLatest,
|
||||
fetchScene,
|
||||
fetchProfile,
|
||||
organic: {
|
||||
fetchLatest: fetchLatestOrganic,
|
||||
fetchScene,
|
||||
},
|
||||
search: {
|
||||
fetchLatest: fetchLatestSearch,
|
||||
fetchScene,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const config = require('config');
|
|||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const unprint = require('unprint');
|
||||
const omit = require('object.omit');
|
||||
|
||||
const argv = require('../src/argv');
|
||||
const include = require('../src/utils/argv-include')(argv);
|
||||
|
|
@ -43,9 +44,13 @@ const actors = [
|
|||
{ entity: 'milfy', name: 'Clea Gaultier', fields: ['gender', 'avatar', 'description'] },
|
||||
{ entity: 'wifey', name: 'Danielle Renae', fields: ['gender', 'avatar', 'description'] },
|
||||
// teamskeet
|
||||
{ entity: 'teamskeet', name: 'Abella Danger', fields: ['description', 'avatar', 'measurements', 'birthPlace', 'nationality', 'ethnicity', 'height', 'weight', 'hairColor', 'hasPiercings'] },
|
||||
{ entity: 'mylf', name: 'Eliza Ibarra', fields: ['avatar', 'measurements', 'nationality', 'hairColor', 'hasPiercings', 'hasTattoos'] },
|
||||
{ entity: 'sayuncle', name: 'Greg McKeon', fields: ['avatar', 'description'] },
|
||||
{ entity: 'teamskeet', name: 'Abella Danger', fields: ['description', 'gender', 'avatar', 'measurements', 'birthPlace', 'nationality', 'ethnicity', 'height', 'weight', 'hairColor', 'hasPiercings'] },
|
||||
{ entity: 'mylf', name: 'Eliza Ibarra', fields: ['avatar', 'gender', 'measurements', 'nationality', 'hairColor', 'hasPiercings', 'hasTattoos'] },
|
||||
{ entity: 'familystrokes', name: 'Eliza Ibarra', fields: ['avatar', 'gender', 'measurements', 'nationality', 'hairColor', 'hasPiercings', 'hasTattoos'] },
|
||||
{ entity: 'freeuse', name: 'Gabbie Carter', fields: ['avatar', 'gender'] },
|
||||
{ entity: 'swappz', name: 'Riley Reid', fields: ['avatar', 'gender', 'measurements', 'nationality', 'ethnicity', 'hairColor', 'hasPiercings', 'height', 'weight'] },
|
||||
{ entity: 'pervz', name: 'Kenzie Reeves', fields: ['avatar', 'gender', 'measurements', 'nationality', 'ethnicity', 'hairColor'] },
|
||||
{ entity: 'sayuncle', name: 'Greg McKeon', fields: ['avatar', 'gender', 'description'] },
|
||||
// mike adriano
|
||||
{ entity: 'trueanal', name: 'Brenna McKenna', fields: ['avatar', 'gender', 'description', 'dateOfBirth', 'birthPlace', 'measurements', 'eyes', 'weight', 'height', 'hairColor', 'hasTattoos'] },
|
||||
{ entity: 'analonly', name: 'Lilith Grace', fields: ['avatar', 'gender', 'description', 'dateOfBirth', 'birthPlace', 'measurements', 'eyes', 'weight', 'height', 'hairColor'] },
|
||||
|
|
@ -272,7 +277,7 @@ const validators = {
|
|||
description: (value) => typeof value === 'string' && value.length > 3,
|
||||
birthPlace: (value) => typeof value === 'string' && value.length > 1, // may return US or USA
|
||||
birthCountry: (value) => typeof value === 'string' && value.length > 1,
|
||||
nationality: (value) => typeof value === 'string' && value.length > 3,
|
||||
nationality: (value) => typeof value === 'string' && value.length > 2,
|
||||
// height: (value) => !!Number(value) || /\d'\d{1,2}"/.test(value), // ft in needs to be converted
|
||||
height: (value) => !!Number(value) && value > 130,
|
||||
weight: (value) => !!Number(value) && value > 40,
|
||||
|
|
@ -347,7 +352,7 @@ async function init() {
|
|||
assert.fail('profile not found');
|
||||
}
|
||||
|
||||
console.log(profile);
|
||||
console.log(omit(profile, ['scenes']));
|
||||
console.log('Untested fields', Object.entries(profile).filter(([field, value]) => !actor.fields.includes(field) && typeof value !== 'undefined' && value !== null).map(([field]) => `'${field}'`).join(', '));
|
||||
|
||||
await Promise.all(actor.fields.map(async (field) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue