'use strict'; const format = require('template-format'); const qu = require('../utils/qu'); const http = require('../utils/http'); const slugify = require('../utils/slugify'); const { lbsToKg, feetInchesToCm } = require('../utils/convert'); function getChannelSlug(channelName, entity) { if (entity.type === 'channel') { return entity.slug; } const channelSlug = slugify(channelName, '', { removePunctuation: true }); const channel = entity.children.find((child) => new RegExp(channelSlug).test(child.slug)); return channel?.slug || null; } function scrapeScene(scene, channel) { const release = {}; release.entryId = scene.id; release.url = `${channel.type === 'network' ? channel.url : channel.parent.url}/movies/${release.entryId}`; release.title = scene.title; release.date = qu.extractDate(scene.publishedDate); release.actors = scene.models?.map((model) => model.modelName) || []; release.actors = scene.models?.map((model) => ({ name: model.modelName, avatar: `https://images.mylfcdn.net/tsv4/model/profiles/${slugify(model.modelName, '_')}.jpg`, url: `${channel.url}/models/www.mylf.com/models/${model.modelId}`, })); release.poster = [ scene.img.replace('med.jpg', 'hi.jpg'), scene.img, ]; release.teaser = scene.videoTrailer; if (scene.video) { release.trailer = { stream: `https://videodelivery.net/${scene.video}/manifest/video.mpd` }; } release.tags = scene.tags; release.likes = scene.stats.likeCount; release.dislikes = scene.stats.dislikeCount; release.channel = getChannelSlug(scene.site.name || scene.site.nickName, channel); return release; } function scrapeAll(scenes, channel) { return scenes.map(({ _source: scene }) => scrapeScene(scene, channel)); } function scrapeProfile(actor, entity) { const profile = {}; if (actor.bio.about && !/\band\b/.test(actor.bio.about)) { const bio = actor.bio.about.split(/\n/).filter(Boolean).reduce((acc, item) => { const [key, value] = item.match(/(.+): (.+)/).slice(1); return { ...acc, [slugify(key, '_')]: value.trim() }; }, {}); // birthdate seems never/rarely correct if (bio.measurements) { profile.measurements = bio.measurements; } else { const breastSize = actor.bio.breastSize?.match(/(\d+)(\w+)/)?.slice(1) || actor.bio.about.match(/Measurements: (\d+)(\w+)/)?.slice(1); if (breastSize) { [profile.bust, profile.cup] = breastSize; } } profile.birthPlace = bio.birth_location; profile.nationality = bio.nationality; profile.ethnicity = bio.ethnicity; profile.hairColor = bio.hair_color; const piercings = actor.bio.about.match(/Piercings: (\w+)/i)?.[1]; const tattoos = actor.bio.about.match(/Tattoos: (\w+)/i)?.[1]; if (/yes|various/i.test(piercings)) profile.hasPiercings = true; else if (/no/i.test(piercings)) profile.hasPiercings = false; else if (bio.piercings) { profile.hasPiercings = true; profile.piercings = piercings; } if (/yes|various/i.test(tattoos)) profile.hasTattoos = true; else if (/no/i.test(tattoos)) profile.hasTattoos = false; else if (bio.tattoos) { profile.hasTattoos = true; profile.tattoos = tattoos; } } if (actor.bio.heightFeet && actor.bio.heightInches) { profile.height = feetInchesToCm(actor.bio.heightFeet, actor.bio.heightInches); } if (actor.bio.weight) { profile.weight = lbsToKg(actor.bio.weight); } profile.avatar = actor.img; profile.scenes = actor.movies?.map((scene) => scrapeScene(scene, entity)); return profile; } async function fetchLatest(channel, page = 1, { parameters }) { const res = await http.get(`${parameters.videos}/_search?q=site.seo.seoSlug:"${parameters.id}"&sort=publishedDate:desc&size=30&from=${(page - 1) * 30}`); if (res.ok) { return scrapeAll(res.body.hits.hits, channel); } return res.status; } async function fetchScene(url, channel, baseScene, { parameters }) { const sceneSlug = new URL(url).pathname.match(/\/([\w-]+$)/)[1]; const res = await http.get(`${parameters.videos}/${sceneSlug}`); if (res.ok && res.body.found) { return scrapeScene(res.body._source, channel); } return res.status; } async function fetchProfile(baseActor, { entity, parameters }) { const url = format(parameters.profiles, { slug: baseActor.slug }); const res = await qu.get(url); if (res.ok && res.body) { return scrapeProfile(res.body._source, entity); } return res.status; } module.exports = { fetchLatest, fetchScene, fetchProfile, };