Added Ricky's Room.
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 8.2 KiB |
|
@ -8093,6 +8093,12 @@ const sites = [
|
||||||
parameters: null,
|
parameters: null,
|
||||||
parent: 'realitykings',
|
parent: 'realitykings',
|
||||||
},
|
},
|
||||||
|
// RICKYS ROOM
|
||||||
|
{
|
||||||
|
name: 'Ricky\'s Room',
|
||||||
|
slug: 'rickysroom',
|
||||||
|
url: 'https://rickysroom.com',
|
||||||
|
},
|
||||||
// SCORE
|
// SCORE
|
||||||
{
|
{
|
||||||
name: '18 Eighteen',
|
name: '18 Eighteen',
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
'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,
|
||||||
|
};
|
|
@ -53,6 +53,7 @@ const pinkyxxx = require('./pinkyxxx');
|
||||||
const privateNetwork = require('./private'); // reserved keyword
|
const privateNetwork = require('./private'); // reserved keyword
|
||||||
const purgatoryx = require('./purgatoryx'); // reserved keyword
|
const purgatoryx = require('./purgatoryx'); // reserved keyword
|
||||||
const radical = require('./radical');
|
const radical = require('./radical');
|
||||||
|
const rickysroom = require('./rickysroom');
|
||||||
const score = require('./score');
|
const score = require('./score');
|
||||||
const spizoo = require('./spizoo');
|
const spizoo = require('./spizoo');
|
||||||
const teamskeet = require('./teamskeet');
|
const teamskeet = require('./teamskeet');
|
||||||
|
@ -140,6 +141,7 @@ const scrapers = {
|
||||||
private: privateNetwork,
|
private: privateNetwork,
|
||||||
purgatoryx,
|
purgatoryx,
|
||||||
radical,
|
radical,
|
||||||
|
rickysroom,
|
||||||
score,
|
score,
|
||||||
sexyhub: mindgeek,
|
sexyhub: mindgeek,
|
||||||
spizoo,
|
spizoo,
|
||||||
|
@ -264,6 +266,7 @@ const scrapers = {
|
||||||
purgatoryx,
|
purgatoryx,
|
||||||
realitykings: mindgeek,
|
realitykings: mindgeek,
|
||||||
realvr: badoink,
|
realvr: badoink,
|
||||||
|
rickysroom,
|
||||||
roccosiffredi: famedigital,
|
roccosiffredi: famedigital,
|
||||||
score,
|
score,
|
||||||
seehimfuck: hush,
|
seehimfuck: hush,
|
||||||
|
|
|
@ -48,7 +48,7 @@ async function curateReleaseEntry(release, batchId, existingRelease, type = 'sce
|
||||||
curatedRelease.shoot_id = release.shootId || null;
|
curatedRelease.shoot_id = release.shootId || null;
|
||||||
curatedRelease.production_date = Number(release.productionDate) ? release.productionDate : null;
|
curatedRelease.production_date = Number(release.productionDate) ? release.productionDate : null;
|
||||||
curatedRelease.duration = release.duration;
|
curatedRelease.duration = release.duration;
|
||||||
curatedRelease.qualities = Array.from(new Set(release.qualities?.map(Number).filter(Boolean)));
|
curatedRelease.qualities = Array.from(new Set(release.qualities?.map(Number).filter(Boolean))).sort((qualityA, qualityB) => qualityB - qualityA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (release.productionLocation) {
|
if (release.productionLocation) {
|
||||||
|
|