'use strict'; const unprint = require('unprint'); const slugify = require('../utils/slugify'); function scrapeProfile({ query }) { const profile = {}; const bio = Object.fromEntries(query.all('.profile-meta-list li').map((bioEl) => [ slugify(unprint.query.content(bioEl, 'span:first-child'), '_'), unprint.query.content(bioEl, 'span:last-child'), ]).filter(([_key, value]) => value?.toLowerCase() !== 'unknown')); profile.description = query.content('#description div[data-test="biography"]'); profile.dateOfBirth = unprint.extractDate(bio.date_of_birth, 'MMMM D, YYYY'); profile.age = unprint.extractNumber(bio.age); profile.birthPlace = bio.place_of_birth; profile.nationality = bio.nationality; profile.ethnicity = bio.ethnicity; profile.eyes = bio.eye_color; profile.hairColor = bio.hair_color; [profile.bust, profile.cup] = bio.bra?.match(/(\d+)([a-z]+)/i)?.slice(1) || []; // TODO: differentiate between bust and bra band size if (!profile.bust) { profile.bust = bio.bust; } if (!profile.cup) { profile.cup = bio.cup; } profile.bust = unprint.extractNumber(bio.bra); profile.cup = bio.cup; profile.waist = unprint.extractNumber(bio.waist); profile.hip = unprint.extractNumber(bio.hip); profile.height = unprint.extractNumber(bio.height); profile.weight = unprint.extractNumber(bio.weight); profile.foot = unprint.extractNumber(bio.shoe_size); profile.socials = query.urls('.profile-meta-item .teaser__link'); if (/yes/i.test(bio.tattoos)) profile.hasTattoos = true; if (/no/i.test(bio.tattoos)) profile.hasTattoos = false; profile.tattoos = bio.tattoo_locations; if (/yes/i.test(bio.piercings)) profile.hasPiercings = true; if (/no/i.test(bio.piercings)) profile.hasPiercings = false; profile.piercings = bio.piercing_locations; if (/natural/i.test(bio.boobs)) profile.naturalBoobs = true; if (/fake/i.test(bio.boobs)) profile.naturalBoobs = false; if (/natural/i.test(bio.butt)) profile.naturalButt = true; if (/fake/i.test(bio.butt)) profile.naturalButt = false; const avatar = query.img('.dashboard-image-container img'); if (!avatar?.match(/placeholder/i)) { profile.avatar = avatar; } return profile; } async function getActorUrl(actor) { if (actor.url) { return actor.url; } const res = await unprint.post('https://www.freeones.com/xhr/search', { performerTypes: ['babe', 'male', 'trans'], query: actor.name, recipe: 'subject', size: 12, }); if (res.ok) { const model = res.data.hits?.find((result) => slugify(result.name) === actor.slug); if (model?.url) { return `https://www.freeones.com${model.url}/bio`; } } return null; } async function fetchProfile(actor) { const res = await unprint.get(`https://freeones.com/${actor.slug}/bio`); if (res.ok) { return scrapeProfile(res.context); } const actorUrl = await getActorUrl(actor); if (actorUrl) { const actorRes = await unprint.get(actorUrl); if (actorRes.ok) { return scrapeProfile(actorRes.context); } } return null; } module.exports = { fetchProfile, };