diff --git a/seeds/00_tags.js b/seeds/00_tags.js index 2c889ec5..f5704794 100755 --- a/seeds/00_tags.js +++ b/seeds/00_tags.js @@ -963,6 +963,11 @@ const tags = [ slug: 'pyjamas', group: 'clothing', }, + { + name: 'rave', + slug: 'rave', + group: 'clothing', + }, { name: 'redhead', slug: 'redhead', diff --git a/seeds/02_sites.js b/seeds/02_sites.js index c698ab8c..89e1e235 100755 --- a/seeds/02_sites.js +++ b/seeds/02_sites.js @@ -5580,6 +5580,20 @@ const sites = [ profile: 'https://www.povpornstars.com/tour/models/{actor}.html', }, }, + { + slug: 'ravebunnys', + name: 'Rave Bunnys', + url: 'https://ravebunnys.com', + tags: ['rave'], + parent: 'hussiepass', + }, + { + slug: 'hotandtatted', + name: 'Hot and Tatted', + url: 'https://hotandtatted.com', + tags: ['tattoos'], + parent: 'hussiepass', + }, // HUSH PASS { slug: 'shotherfirst', diff --git a/src/scrapers/actors.js b/src/scrapers/actors.js index 4d02f1f1..329a193e 100644 --- a/src/scrapers/actors.js +++ b/src/scrapers/actors.js @@ -148,6 +148,8 @@ module.exports = { interracialpovs: hush, povpornstars: hush, seehimfuck: hush, + ravebunnys: hush, + hotandtatted: hush, // wankzvr wankzvr, tranzvr: wankzvr, diff --git a/src/scrapers/hush.js b/src/scrapers/hush.js index 8ed1b7fb..711666c0 100755 --- a/src/scrapers/hush.js +++ b/src/scrapers/hush.js @@ -145,7 +145,10 @@ function scrapeScene({ html, query }, channel, url) { release.date = query.date('.videoInfo p', ['MM/DD/YYYY', 'YYYY-MM-DD']); release.duration = Number(query.content('.videoInfo p:nth-of-type(2)')?.match(/(\d+) min/i)?.[1]) * 60; - release.actors = query.contents('.update_models a'); + release.actors = query.all('.update_models a').map((actorEl) => ({ + name: unprint.query.content(actorEl), + url: unprint.query.url(actorEl, null, { origin: channel.origin }), + })); const posterPath = html.match(/poster="([\w-/.]+)"/)?.[1]; const poster = unprint.prefixUrl(posterPath, channel.url) || query.img('.update_thumb', 'src0_1x', { origin: channel.url }); // latter used when trailer requires signup @@ -182,6 +185,7 @@ function scrapeSceneT1({ html, query }, site, url, baseRelease) { release.actors = query.all('.models-list-thumbs a').map((el) => ({ name: unprint.query.content(el, 'span'), + url: unprint.query.url(el, null), avatar: getImageWithFallbacks(query, 'img', site, el), })); @@ -264,9 +268,9 @@ async function scrapeProfile({ query }, url, channel, options) { if (bio.ethnicity) profile.ethnicity = bio.ethnicity; - if (bio.height) profile.height = Number(bio.height.match(/^\d{2,3}/)?.[0]); - if (bio.weight) profile.weight = Number(bio.weight.match(/^\d{2,3}/)?.[0]); - if (bio.shoe_size) profile.foot = Number(bio.shoe_size); + if (bio.height) profile.height = convert(bio.height, 'cm'); + if (bio.weight) profile.weight = convert(bio.weight.match(/(\d+)\s*lb/i)?.[1], 'lb', 'kg'); + if (bio.shoe_size && !/unknown/i.test(bio.shoe_size)) profile.foot = unprint.extractNumber(bio.shoe_size); profile.measurements = bio.measurements; @@ -283,7 +287,7 @@ async function scrapeProfile({ query }, url, channel, options) { if (bio.piercings && /(yes)|(some)|(many)/i.test(bio.piercings)) profile.hasPiercings = true; if (bio.piercings && /no/i.test(bio.piercings)) profile.hasPiercings = false; - if (bio.aliases) profile.aliases = bio.aliases.split(',').map((alias) => alias.trim()); + if (bio.aliases) profile.aliases = bio.aliases.split(',').map((alias) => alias.trim()).filter((alias) => !/known/i.test(alias)); // filter out "No known aliases" profile.socials = [bio.onlyfans, bio.twitter, bio.instagram, bio.domain].filter(Boolean); @@ -338,21 +342,22 @@ function scrapeProfileT1({ query }, url, site) { return profile; } -async function fetchProfile({ name: actorName }, { channel }, options) { +async function fetchProfile({ name: actorName, url: actorUrl }, { channel }, options) { const actorSlugA = slugify(actorName, '', { lower: false }); const actorSlugB = slugify(actorName); const t1 = channel.parameters?.t1 ? 't1/' : ''; - const { res, url } = channel.parameters?.profile - ? await tryUrls([ + const { res, url } = await tryUrls([ + actorUrl, + ...channel.parameters?.profile ? [ format(channel.parameters.profile, { actor: actorSlugA }), format(channel.parameters.profile, { actor: actorSlugB }), - ], { followRedirects: false }) - : await tryUrls([ + ] : [ `${channel.url}/${t1}models/${actorSlugA}.html`, `${channel.url}/${t1}models/${actorSlugB}.html`, - ], { followRedirects: false }); + ], + ], { followRedirects: false }); if (!res.ok) { return res.status; diff --git a/tests/profiles.js b/tests/profiles.js index e7a85870..fdf11bd7 100644 --- a/tests/profiles.js +++ b/tests/profiles.js @@ -76,6 +76,8 @@ const actors = [ { entity: 'seehimfuck', name: 'Sheem The Dream', fields: ['avatar', 'description', 'dateOfBirth', 'birthPlace', 'ethnicity', 'height', 'weight', 'hasTattoos', 'hasPiercings', 'penisLength', 'isCircumcised', 'socials'] }, { entity: 'hushpass', name: 'Dylan Ryder', fields: ['avatar'] }, { entity: 'interracialpass', name: 'Aidra Fox', fields: ['avatar', 'height', 'measurements'] }, + { entity: 'ravebunnys', name: 'Lacey Jayne', fields: ['avatar', 'height', 'measurements', 'dateOfBirth', 'birthPlace', 'description', 'ethnicity', 'weight', 'naturalBoobs'] }, + { entity: 'hotandtatted', name: 'Valerica Steele', url: 'https://hotandtatted.com/models/tattooed-pornstar-val-steele.html', fields: ['avatar', 'measurements', 'dateOfBirth', 'birthPlace', 'description', 'ethnicity', 'weight', 'foot', 'naturalBoobs', 'hasPiercings'] }, // kelly madison / 8K { entity: 'kellymadison', name: 'Ava Addams', fields: ['avatar', 'description', 'age', 'height', 'measurements', 'birthPlace', 'dateOfBirth', 'ethnicity'] }, { entity: '8kmembers', name: 'Angie Lynx', fields: ['age', 'height', 'measurements', 'birthPlace', 'dateOfBirth', 'ethnicity'] }, @@ -308,9 +310,10 @@ const validators = { hasTattoos: (value) => typeof value === 'boolean', hasPiercings: (value) => typeof value === 'boolean', avatar: async (value) => [].concat(value).reduce(async (chain, url) => { + // testing all avatar fallbacks is too time-consuming, just ensure one is valid const acc = await chain; - if (!acc) { + if (acc) { return acc; }