traxxx/src/scrapers/rickysroom.js

126 lines
3.3 KiB
JavaScript
Executable File

'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,
};