'use strict'; const qu = require('../utils/q'); const slugify = require('../utils/slugify'); function scrapeAll(scenes, channel) { return scenes.map(({ query }) => { const release = {}; const network = channel.type === 'network' ? channel : channel.parent; release.url = query.url('a.title'); release.entryId = new URL(release.url).pathname.match(/\/trailers\/(.+).html/)?.[1].toLowerCase(); release.title = query.cnt('.title'); release.date = query.date('time', 'MMMM D, YYYY'); release.actors = query.all('.actors a').map((el) => ({ name: query.cnt(el), url: query.url(el, null), })); [release.poster, ...release.photos] = Object .entries(query.el('.images img').dataset) .filter(([key]) => /src/.test(key)) .map(([, value]) => qu.prefixUrl(value, network.url)); release.likes = query.number('.rating-on-thumb'); const siteId = query.url('.site a', 'href', { origin: network.url, object: true })?.searchParams.get('site[]'); if (siteId) { release.channel = network.children.find((child) => child.parameters.siteId.toString() === siteId)?.slug; } return release; }); } function scrapeScene({ query }, url, channel) { const release = {}; const network = channel.type === 'network' ? channel : channel.parent; release.entryId = new URL(url).pathname.match(/\/trailers\/(.+).html/)[1].toLowerCase(); release.title = query.cnt('.title-line h1'); release.description = query.cnt('.shadow .text'); release.date = query.date('.title-line .date', 'MMMM D, YYYY'); release.duration = query.number('.dur') * 60; release.actors = query.all('.site a[href*="/models"]').map((el) => ({ name: query.cnt(el), url: query.url(el, null), })); release.tags = query.cnts('.tag-list a'); release.poster = query.poster(); release.trailer = query.video(); release.likes = query.number('.rating-data .value'); const siteId = query.url('.site a[href*="site[]"]', 'href', { origin: network.url, object: true })?.searchParams.get('site[]'); if (siteId) { release.channel = network.children.find((child) => child.parameters.siteId.toString() === siteId)?.slug; } return release; } function scrapeProfile({ query, el }, url, entity) { const profile = {}; const bio = query.all('.stats li').reduce((acc, bioEl) => ({ ...acc, [slugify(query.cnt(bioEl, '.title'))]: query.cnt(bioEl, '.value'), }), {}); profile.url = url; profile.description = query.cnt('.bio .text'); profile.hairColor = bio.hair; profile.eyes = bio.eyes; profile.avatar = query.img('.model-info .photo img', 'data-src', { origin: entity.url }); profile.scenes = scrapeAll(qu.initAll(el, '.video-list .video[data-type="vids"]'), entity); return profile; } async function fetchLatest(channel, page = 1) { const url = `${channel.type === 'network' ? channel.url : channel.parent.url}/search.php?site[]=${channel.parameters.siteId}&page=${page}`; const res = await qu.getAll(url, '.video-list .video'); if (res.ok) { return scrapeAll(res.items, channel); } return res.status; } async function fetchProfile({ name: actorName }, entity, include) { const url = `${entity.url}/models/${slugify(actorName)}.html`; const res = await qu.get(url); if (res.ok) { return scrapeProfile(res.item, url, entity, include); } return res.status; } module.exports = { fetchLatest, fetchProfile, scrapeScene, };