Extended Aziani scraper to support Cosplayground.

This commit is contained in:
DebaucheryLibrarian
2026-07-24 05:52:17 +02:00
parent 00ba8b9dd3
commit 06a5f5bec7
6 changed files with 61 additions and 17 deletions

View File

@@ -1715,6 +1715,10 @@ const aliases = [
name: 'busty - big boobs', name: 'busty - big boobs',
for: 'big-boobs', for: 'big-boobs',
}, },
{
name: 'big breasts',
for: 'big-boobs',
},
{ {
name: 'busty: big beautiful breast', name: 'busty: big beautiful breast',
for: 'big-boobs', for: 'big-boobs',

View File

@@ -284,6 +284,7 @@ const networks = [
areaId: '3b4c609c-6a0d-4cb9-9cce-0605f32b79ec', areaId: '3b4c609c-6a0d-4cb9-9cce-0605f32b79ec',
blockId: 114458, blockId: 114458,
scene: 'https://aziani.com', scene: 'https://aziani.com',
api: 'https://azianistudios.com/tour_api.php',
cdn: 'https://c75c0c3063.mjedge.net', cdn: 'https://c75c0c3063.mjedge.net',
}, },
}, },
@@ -593,6 +594,11 @@ const networks = [
concurrency: 1, concurrency: 1,
}, },
}, },
{
slug: 'ksm',
name: 'KSM',
hasLogo: false,
},
{ {
slug: 'letsdoeit', slug: 'letsdoeit',
name: 'LetsDoeIt', name: 'LetsDoeIt',

View File

@@ -13529,6 +13529,26 @@ const sites = [
}, },
}, },
}, },
// SKM
{
slug: 'cosplayground',
name: 'Cosplayground',
url: 'https://cosplayground.com',
tags: ['cosplay'],
parent: 'ksm',
independent: true,
parameters: {
// seems to use same CMS as Aziani
api: 'https://api.cosplayground.com/tour_api.php',
seriesId: null,
areaId: '2bc2444e-a053-40a2-bc4b-ca3618521563',
cdn: 'https://c880f36aa8.mjedge.net',
entryIdSlug: true,
videos: '/videos',
scenePath: '/videos',
modelPath: '/models',
},
},
// TEEN CORE CLUB // TEEN CORE CLUB
{ {
name: 'Analyzed Girls', name: 'Analyzed Girls',

View File

@@ -279,6 +279,7 @@ module.exports = {
// etc // etc
'18vr': badoink, '18vr': badoink,
theflourishxxx: theflourish, theflourishxxx: theflourish,
cosplayground: aziani,
pierrewoodman, pierrewoodman,
exploitedx, // only from known URL that will specify site exploitedx, // only from known URL that will specify site
fullpornnetwork, fullpornnetwork,

View File

@@ -6,11 +6,13 @@ const { decode } = require('html-entities');
const slugify = require('../utils/slugify'); const slugify = require('../utils/slugify');
const { feetInchesToCm, femaleFeetUsToEu } = require('../utils/convert'); const { feetInchesToCm, femaleFeetUsToEu } = require('../utils/convert');
const tagKeys = ['tags', 'category', 'categories'];
function scrapeScene(data, channel, parameters) { function scrapeScene(data, channel, parameters) {
const release = {}; const release = {};
release.entryId = data.cms_set_id; release.entryId = data.cms_set_id;
release.url = `${parameters.scene || channel.url}/video/${data.cms_set_id}`; release.url = `${parameters.scene || channel.url}${parameters.scenePath || '/video'}/${parameters.entryIdSlug ? data.slug : data.cms_set_id}`;
release.title = data.name; release.title = data.name;
release.description = data.description; release.description = data.description;
@@ -20,7 +22,7 @@ function scrapeScene(data, channel, parameters) {
release.actors = data.data_types.find((dataType) => dataType.data_type === 'Models' || dataType.data_type === 'Talent')?.data_values.map((actor) => ({ release.actors = data.data_types.find((dataType) => dataType.data_type === 'Models' || dataType.data_type === 'Talent')?.data_values.map((actor) => ({
name: actor.name, name: actor.name,
url: `${channel.url}/model/${actor.cms_data_value_id}?models=${encodeURI(actor.name)}`, // slug does not work unless it's also the ID url: `${channel.url}${parameters.modelPath || '/model'}/${parameters.entryIdSlug && actor.slug ? actor.slug : actor.cms_data_value_id}?models=${encodeURI(actor.name)}`, // slug does not work unless it's also the ID
})); }));
release.directors = data.data_types.find((dataType) => dataType.data_type === 'Videographers')?.data_values.map((director) => ({ release.directors = data.data_types.find((dataType) => dataType.data_type === 'Videographers')?.data_values.map((director) => ({
@@ -29,7 +31,7 @@ function scrapeScene(data, channel, parameters) {
})); }));
release.tags = data.data_types release.tags = data.data_types
.filter((dataType) => dataType.data_type === 'Tags' || dataType.data_type === 'Category') .filter((dataType) => tagKeys.includes(dataType.data_type?.toLowerCase()))
.flatMap((tags) => tags.data_values.map((tag) => tag.name)); .flatMap((tags) => tags.data_values.map((tag) => tag.name));
const poster = data.preview_formatted.thumb; const poster = data.preview_formatted.thumb;
@@ -66,13 +68,14 @@ function scrapeScene(data, channel, parameters) {
release.trailer = unprint.prefixUrl(`${trailer.fileuri}?${trailer.signature}`, parameters.cdn); release.trailer = unprint.prefixUrl(`${trailer.fileuri}?${trailer.signature}`, parameters.cdn);
} }
release.channel = slugify(data.data_types.find((dataType) => dataType.data_type === 'Series')?.data_values[0]?.name, ''); release.channel = slugify(data.data_types.find((dataType) => dataType.data_type === 'Series')?.data_values[0]?.name, '') || null;
return release; return release;
} }
async function getBlockId(slug, dataSource, entity, parameters) { async function getBlockId(slug, dataSource, entity, parameters) {
const res = await unprint.get(`https://azianistudios.com/tour_api.php/content/page?slug=${slug}&data_source=${JSON.stringify(dataSource)}`, { const res = await unprint.get(`${parameters.api || 'https://azianistudios.com/tour_api.php'}/content/page?slug=${slug}&data_source=${JSON.stringify(dataSource)}`, {
interface: 'request', // necessary for KSM/Cosplayground CF wall, ok for Aziani
headers: { headers: {
Referer: entity.url, Referer: entity.url,
'x-nats-cms-area-id': parameters.areaId, 'x-nats-cms-area-id': parameters.areaId,
@@ -109,9 +112,10 @@ async function fetchLatest(channel, page = 1, { parameters }) {
data_type_search: parameters.seriesId && JSON.stringify({ 7: parameters.seriesId.toString() }), // doesn't seem relevant data_type_search: parameters.seriesId && JSON.stringify({ 7: parameters.seriesId.toString() }), // doesn't seem relevant
}).toString(); }).toString();
const url = `https://azianistudios.com/tour_api.php/content/sets?${query}`; const url = `${parameters.api || 'https://azianistudios.com/tour_api.php'}/content/sets?${query}`;
const res = await unprint.get(url, { const res = await unprint.get(url, {
interface: 'request', // necessary for KSM/Cosplayground CF wall, ok for Aziani
headers: { headers: {
Referer: channel.url, Referer: channel.url,
'x-nats-cms-area-id': parameters.areaId, 'x-nats-cms-area-id': parameters.areaId,
@@ -126,20 +130,21 @@ async function fetchLatest(channel, page = 1, { parameters }) {
} }
async function fetchScene(url, entity, _baseRelease, { parameters }) { async function fetchScene(url, entity, _baseRelease, { parameters }) {
const entryId = new URL(url).pathname.match(/\/video\/(\w+)/)[1]; const entryId = new URL(url).pathname.match(/\/videos?\/([\w-]+)/)[1];
if (!entryId) { if (!entryId) {
return null; return null;
} }
const blockId = await getBlockId('/video/:id', entryId, entity, parameters); const blockId = await getBlockId(`${parameters.videos || '/video'}/${parameters.entryIdSlug ? ':slug' : ':id'}`, entryId, entity, parameters);
if (!blockId) { if (!blockId) {
return null; return null;
} }
const query = new URLSearchParams({ const query = new URLSearchParams({
cms_set_ids: entryId, cms_set_ids: parameters.entryIdSlug ? '' : entryId,
...parameters.entryIdSlug ? { slug: entryId } : null,
cms_area_id: parameters.areaId, cms_area_id: parameters.areaId,
cms_block_id: blockId, cms_block_id: blockId,
content: 1, content: 1,
@@ -150,9 +155,10 @@ async function fetchScene(url, entity, _baseRelease, { parameters }) {
content_count: 1, content_count: 1,
}).toString(); }).toString();
const apiUrl = `https://azianistudios.com/tour_api.php/content/sets?${query}`; const apiUrl = `${parameters.api || 'https://azianistudios.com/tour_api.php'}/content/sets?${query}`;
const res = await unprint.get(apiUrl, { const res = await unprint.get(apiUrl, {
interface: 'request', // necessary for KSM/Cosplayground CF wall, ok for Aziani
headers: { headers: {
Referer: entity.url, Referer: entity.url,
'x-nats-cms-area-id': parameters.areaId, 'x-nats-cms-area-id': parameters.areaId,
@@ -174,7 +180,7 @@ function scrapeProfile(data, entity, parameters) {
decode(detail.value || detail.content_formatted || detail.content), decode(detail.value || detail.content_formatted || detail.content),
])); ]));
profile.url = `${entity.url}/model/${data.cms_data_value_id}`; profile.url = `${entity.url}/model/${parameters.entryIdSlug ? data.slug : data.cms_data_value_id}`;
profile.entryId = data.cms_data_value_id; profile.entryId = data.cms_data_value_id;
profile.description = data.description; profile.description = data.description;
@@ -182,6 +188,7 @@ function scrapeProfile(data, entity, parameters) {
profile.gender = bio.gender?.toLowerCase(); profile.gender = bio.gender?.toLowerCase();
profile.age = bio.age; profile.age = bio.age;
profile.dateOfBirth = unprint.extractDate(`${bio.born} 0`, 'MMMM Do YYYY', { match: /\w+ \d+\w{2} \d{1,4}/ }); profile.dateOfBirth = unprint.extractDate(`${bio.born} 0`, 'MMMM Do YYYY', { match: /\w+ \d+\w{2} \d{1,4}/ });
profile.ethnicity = bio.ethnicity;
profile.measurements = bio.measurements; profile.measurements = bio.measurements;
profile.height = feetInchesToCm(bio.height); profile.height = feetInchesToCm(bio.height);
@@ -190,7 +197,9 @@ function scrapeProfile(data, entity, parameters) {
profile.hairColor = bio.hair_color; profile.hairColor = bio.hair_color;
profile.eyeColor = bio.eye_color; profile.eyeColor = bio.eye_color;
const avatar = bio.thumbnail?.image[0]; const avatar = bio.thumbnail?.image?.[0] // aziani
|| bio.biopic?.image?.[0] // cosplayground profile
|| bio.headshot?.image?.[0]; // cosplayground headshot
if (avatar) { if (avatar) {
profile.avatar = { profile.avatar = {
@@ -210,27 +219,30 @@ async function fetchProfile({ name, url }, { entity, parameters }) {
return null; return null;
} }
const actorId = new URL(url).pathname.match(/model\/(\d+)/)[1]; const actorId = new URL(url).pathname.match(/models?\/(\d+)/)?.[1];
if (!actorId) { if (!actorId && !parameters.entryIdSlug) {
return null; return null;
} }
const blockId = await getBlockId('/model/:id', { models: name, id: actorId }, entity, parameters); const slug = slugify(name);
const blockId = await getBlockId(`${parameters.modelPath || '/model'}/${parameters.entryIdSlug ? ':slug' : 'id'}`, { models: name, id: actorId, slug }, entity, parameters);
if (!blockId) { if (!blockId) {
return null; return null;
} }
const query = new URLSearchParams({ const query = new URLSearchParams({
cms_data_value_ids: actorId, cms_data_value_ids: actorId || '',
...parameters.entryIdSlug ? { slug } : null,
cms_block_id: blockId, cms_block_id: blockId,
cms_data_type_id: 4, cms_data_type_id: 4,
}).toString(); }).toString();
const apiUrl = `https://azianistudios.com/tour_api.php/content/data-values?${query}`; const apiUrl = `${parameters.api || 'https://azianistudios.com/tour_api.php'}/content/data-values?${query}`;
const res = await unprint.get(apiUrl, { const res = await unprint.get(apiUrl, {
interface: 'request', // necessary for KSM/Cosplayground CF wall, ok for Aziani
headers: { headers: {
Referer: entity.url, Referer: entity.url,
'x-nats-cms-area-id': entity.parameters.areaId, 'x-nats-cms-area-id': entity.parameters.areaId,

View File

@@ -102,6 +102,7 @@ module.exports = {
acam, acam,
analvids: pornbox, analvids: pornbox,
pornbox, pornbox,
cosplayground: aziani,
kellymadison, kellymadison,
kink, kink,
'8kmembers': kellymadison, '8kmembers': kellymadison,