'use strict'; const qu = require('../utils/q'); const { lbsToKg, feetInchesToCm } = require('../utils/convert'); function scrapeScene(data, channel) { const release = {}; release.entryId = data.id; release.url = qu.prefixUrl(`/videos/${data.slug}`, channel.url); release.title = data.title; release.description = data.description; release.date = qu.parseDate(data.publish_date, 'YYYY/MM/DD HH:mm:ss'); release.duration = qu.durationToSeconds(data.videos_duration); release.actors = data?.models_thumbs.map((model) => ({ name: model.name, url: qu.prefixUrl(`/models/${model.slug}`, channel.url), avatar: model.thumb, })) || data.models; release.tags = data.tags; release.poster = [data.trailer_screencap].concat(data.extra_thumbnails); release.photos = data.previews.full .map((url) => [url, url.replace('full/', 'thumbs/')]) // photos .concat(data.thumbs); // screenshots release.trailer = data.trailer_url; release.teaser = data.special_thumbnails; release.qualities = data.videos && Object.values(data.videos).map((video) => video.height); release.rating = data.rating; return release; } function scrapeProfile(data, scenes, entity) { const profile = {}; profile.entryId = data.id; profile.url = qu.prefixUrl(`/models/${data.slug}`, entity.url); profile.description = data.Bio || data.bio; profile.birthPlace = data.Born || data.born; profile.dateOfBirth = qu.parseDate(data.Birthdate || data.birthdate, 'YYYY-MM-DD'); profile.measurements = data.Measurements || data.Measurements; profile.height = feetInchesToCm(data.Height || data.height); profile.weight = lbsToKg(data.Weight || data.weight); profile.eyes = data.Eyes || data.eyes; profile.hairColor = data.Hair || data.hair; profile.avatar = data.thumb; profile.scenes = scenes?.map((scene) => scrapeScene(scene, entity)); return profile; } async function fetchLatest(channel, page = 1) { const url = `${channel.url}/videos?order_by=publish_date&per_page=100&page=${page}`; // unsure if page works, not enough videos as of 2022-05-29 const res = await qu.get(url); if (res.ok) { const dataString = res.item.query.html('#__NEXT_DATA__'); const data = dataString && JSON.parse(dataString); if (data.props?.pageProps?.contents?.data) { return data.props.pageProps.contents.data.map((scene) => scrapeScene(scene, channel)); } return null; } return res.status; } async function fetchScene(url, channel, baseRelease) { if (baseRelease.entryId) { // deep data is identical to update data return baseRelease; } const res = await qu.get(url); if (res.ok) { const dataString = res.item.query.html('#__NEXT_DATA__'); const data = dataString && JSON.parse(dataString); if (data.props?.pageProps?.content) { return scrapeScene(data.props.pageProps.content, channel); } return null; } return res.status; } async function fetchProfile({ slug }, entity) { const url = `${entity.url}/models/${slug}`; const res = await qu.get(url); if (res.ok) { const dataString = res.item.query.html('#__NEXT_DATA__'); const data = dataString && JSON.parse(dataString); if (data.props?.pageProps?.model) { return scrapeProfile(data.props.pageProps.model, data.props.pageProps.model_contents, entity); } return null; } return res.status; } module.exports = { fetchLatest, fetchScene, fetchProfile, };