'use strict'; const qu = require('../utils/qu'); const http = require('../utils/http'); const slugify = require('../utils/slugify'); const { feetInchesToCm, lbsToKg } = require('../utils/convert'); function scrapeAll(scenes) { return scenes.map(({ query }) => { const release = {}; release.title = query.cnt('.title'); release.url = query.url('.title a'); release.entryId = new URL(release.url).pathname.match(/\/view\/(\d+)/)[1]; release.date = query.date('.pub-date', 'MMM DD, YYYY'); release.duration = query.duration('.video-duration'); release.actors = query.all('.models a').map((el) => ({ name: query.cnt(el), url: query.url(el, null), })); if (query.exists('.thumb-big')) { // updates page release.poster = query.img('.thumb-big', 'data-image') || JSON.parse(query.el('.thumbnails-wrap a', 'data-images')); release.photos = [query.img('.thumb-top', 'data-image'), query.img('.thumb-bottom', 'data-image')]; } if (query.exists('.thumbnails-wrap')) { // actor page try { const images = JSON.parse(query.el('.thumbnails-wrap a', 'data-images')); release.poster = images.slice(0, 1)[0]; release.photos = images.slice(1); } catch (error) { // images probably not available } } return release; }); } function scrapeUpcoming({ query }) { const release = {}; release.url = query.url('.bottom-info a'); release.entryId = new URL(release.url).pathname.match(/\/view\/(\d+)/)?.[1]; release.title = query.cnt('.title'); release.actors = query.all('.model-wrap li').map((el) => ({ name: query.cnt(el, 'h5'), url: query.url(el, '.model-thumb a'), avatar: query.img(el, '.model-thumb img'), })); return release; } function scrapeScene({ query }, url) { const release = {}; release.title = query.cnt('.title'); release.entryId = new URL(url).pathname.match(/\/view\/(\d+)/)[1]; release.date = query.date('.date', 'MMMM DD, YYYY', /\w+ \d{1,2}, \d{4}/); release.description = query.cnt('.description p'); release.duration = query.duration('.total-time'); release.actors = query.all('.model-wrap li').map((el) => ({ name: query.cnt(el, 'h5'), url: query.url(el, 'a'), avatar: query.img(el), })); release.poster = query.poster(); release.photos = query.urls('.photos-slider a'); release.trailer = query.video(); release.comment = query.cnt('.series'); return release; } async function fetchLatest(channel, page) { const res = await qu.getAll(`${channel.url}/episodes?page=${page}`, '.content-item'); if (res.ok) { return scrapeAll(res.items, channel); } return res.status; } async function fetchUpcoming(channel) { const res = await qu.get(channel.url, '.upcoming-info-wrap'); if (res.ok && res.item) { return [scrapeUpcoming(res.item, channel)]; } return res.status; } function scrapeProfile({ query }, url) { const profile = { url }; const bio = Object.fromEntries(query.all('.model-desc li').map((el) => [slugify(query.cnt(el, 'span'), '_'), query.text(el)])); profile.description = bio.bio; profile.dateOfBirth = qu.extractDate(bio.birthdate, 'YYYY-MM-DD'); profile.birthPlace = bio.birthplace; profile.hairColor = bio.hair_color; profile.eyes = bio.eye_color; profile.height = feetInchesToCm(bio.height); profile.weight = lbsToKg(bio.weight); profile.measurements = bio.measurements; profile.avatar = query.img('.model-pic img'); profile.scenes = scrapeAll(qu.initAll(query.all('.content-item'))); return profile; } async function searchActor(baseActor, channel) { const searchRes = await http.post(`${channel.url}/search-preview`, { q: slugify(baseActor.name, ' ') }, { encodeJSON: false, headers: { 'Accept-Language': 'en-US,en;', }, }); if (searchRes.ok) { const actorUrl = searchRes.body.find((item) => item.type === 'model' && slugify(item.title) === baseActor.slug)?.url; return actorUrl || null; } return null; } async function fetchProfile(baseActor, context, include, retry = false) { const actorUrl = (!retry && baseActor.url) || await searchActor(baseActor, context.entity); if (!actorUrl) { return null; } const res = await qu.get(actorUrl); if (res.ok) { return scrapeProfile(res.item, actorUrl); } if (baseActor.url) { return fetchProfile(baseActor, context, include, true); } return res.status; } module.exports = { fetchLatest, fetchProfile, fetchUpcoming, scrapeAll, scrapeScene, };