Added Bang! deep scrape. Improved network page layout. Added Bang Bros logos.
|
@ -120,16 +120,6 @@ export default {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import 'theme';
|
|
||||||
|
|
||||||
@media(max-width: $breakpoint3) {
|
|
||||||
.releases .tiles {
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import 'theme';
|
@import 'theme';
|
||||||
|
|
||||||
|
@ -216,7 +206,7 @@ export default {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint) {
|
@media(max-width: $breakpoint3) {
|
||||||
.header,
|
.header,
|
||||||
.header.hideable {
|
.header.hideable {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -103,6 +103,7 @@ export default {
|
||||||
|
|
||||||
.trailer-video {
|
.trailer-video {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
|
|
|
@ -180,7 +180,6 @@ export default {
|
||||||
.details {
|
.details {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
|
|
|
@ -163,7 +163,7 @@ function initActorActions(store, _router) {
|
||||||
|
|
||||||
const { actors } = await graphql(`
|
const { actors } = await graphql(`
|
||||||
query Actors($limit:Int) {
|
query Actors($limit:Int) {
|
||||||
actors(first:$limit) {
|
actors(first:$limit, orderBy: NAME_ASC) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
function curateActor(actor) {
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
function curateActor(actor, release) {
|
||||||
const curatedActor = {
|
const curatedActor = {
|
||||||
...actor,
|
...actor,
|
||||||
origin: actor.originCountry && {
|
origin: actor.originCountry && {
|
||||||
|
@ -8,13 +10,17 @@ function curateActor(actor) {
|
||||||
|
|
||||||
if (actor.avatar) curatedActor.avatar = actor.avatar.media;
|
if (actor.avatar) curatedActor.avatar = actor.avatar.media;
|
||||||
|
|
||||||
|
if (release && release.date && curatedActor.birthdate) {
|
||||||
|
curatedActor.ageThen = dayjs(release.date).diff(actor.birthdate, 'year');
|
||||||
|
}
|
||||||
|
|
||||||
return curatedActor;
|
return curatedActor;
|
||||||
}
|
}
|
||||||
|
|
||||||
function curateRelease(release) {
|
function curateRelease(release) {
|
||||||
const curatedRelease = {
|
const curatedRelease = {
|
||||||
...release,
|
...release,
|
||||||
actors: release.actors ? release.actors.map(({ actor }) => curateActor(actor)) : [],
|
actors: [],
|
||||||
poster: release.poster && release.poster.media,
|
poster: release.poster && release.poster.media,
|
||||||
tags: release.tags ? release.tags.map(({ tag }) => tag) : [],
|
tags: release.tags ? release.tags.map(({ tag }) => tag) : [],
|
||||||
network: release.site.network,
|
network: release.site.network,
|
||||||
|
@ -22,6 +28,7 @@ function curateRelease(release) {
|
||||||
|
|
||||||
if (release.photos) curatedRelease.photos = release.photos.map(({ media }) => media);
|
if (release.photos) curatedRelease.photos = release.photos.map(({ media }) => media);
|
||||||
if (release.trailer) curatedRelease.trailer = release.trailer.media;
|
if (release.trailer) curatedRelease.trailer = release.trailer.media;
|
||||||
|
if (release.actors) curatedRelease.actors = release.actors.map(({ actor }) => curateActor(actor, curatedRelease));
|
||||||
|
|
||||||
return curatedRelease;
|
return curatedRelease;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,6 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
-webkit-box-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-box-pack: justify;
|
-webkit-box-pack: justify;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -309,6 +307,8 @@
|
||||||
}
|
}
|
||||||
.trailer-video[data-v-42bb19c4] {
|
.trailer-video[data-v-42bb19c4] {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
-o-object-fit: cover;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
.item[data-v-42bb19c4] {
|
.item[data-v-42bb19c4] {
|
||||||
height: 18rem;
|
height: 18rem;
|
||||||
|
@ -662,14 +662,6 @@
|
||||||
width: 15rem;
|
width: 15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* $primary: #ff886c; */
|
|
||||||
/* $logo-highlight: drop-shadow(1px 0 0 $highlight-weak) drop-shadow(-1px 0 0 $highlight-weak) drop-shadow(0 1px 0 $highlight-weak) drop-shadow(0 -1px 0 $highlight-weak); */
|
|
||||||
@media (max-width: 1200px) {
|
|
||||||
.releases .tiles {
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* $primary: #ff886c; */
|
/* $primary: #ff886c; */
|
||||||
/* $logo-highlight: drop-shadow(1px 0 0 $highlight-weak) drop-shadow(-1px 0 0 $highlight-weak) drop-shadow(0 1px 0 $highlight-weak) drop-shadow(0 -1px 0 $highlight-weak); */
|
/* $logo-highlight: drop-shadow(1px 0 0 $highlight-weak) drop-shadow(-1px 0 0 $highlight-weak) drop-shadow(0 1px 0 $highlight-weak) drop-shadow(0 -1px 0 $highlight-weak); */
|
||||||
.network[data-v-e2e12602] {
|
.network[data-v-e2e12602] {
|
||||||
|
@ -759,7 +751,7 @@
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 1200px) {
|
||||||
.header[data-v-e2e12602],
|
.header[data-v-e2e12602],
|
||||||
.header.hideable[data-v-e2e12602] {
|
.header.hideable[data-v-e2e12602] {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
|
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1018 B |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 9.1 KiB |
|
@ -124,6 +124,7 @@ function getSites(networksMap) {
|
||||||
name: 'Trickery',
|
name: 'Trickery',
|
||||||
slug: 'bangtrickery',
|
slug: 'bangtrickery',
|
||||||
url: 'https://www.bang.com/original/4800/bang-trickery',
|
url: 'https://www.bang.com/original/4800/bang-trickery',
|
||||||
|
parameters: JSON.stringify({ siteId: 4800 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -131,8 +132,8 @@ function getSites(networksMap) {
|
||||||
slug: 'yngrcom',
|
slug: 'yngrcom',
|
||||||
// url: 'https://www.bang.com/original/5010/bang-yngr',
|
// url: 'https://www.bang.com/original/5010/bang-yngr',
|
||||||
url: 'https://yngr.com',
|
url: 'https://yngr.com',
|
||||||
network_id: networksMap.bang,
|
|
||||||
parameters: JSON.stringify({ siteId: 5010 }),
|
parameters: JSON.stringify({ siteId: 5010 }),
|
||||||
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Roadside XXX',
|
name: 'Roadside XXX',
|
||||||
|
@ -146,17 +147,19 @@ function getSites(networksMap) {
|
||||||
name: 'Surprise',
|
name: 'Surprise',
|
||||||
slug: 'bangsurprise',
|
slug: 'bangsurprise',
|
||||||
url: 'https://www.bang.com/original/5000/bang-surprise',
|
url: 'https://www.bang.com/original/5000/bang-surprise',
|
||||||
|
parameters: JSON.stringify({ siteId: 5000 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Real Teens',
|
name: 'Real Teens',
|
||||||
slug: 'bangrealteens',
|
slug: 'bangrealteens',
|
||||||
url: 'https://www.bang.com/original/3366/bang-real-teens',
|
url: 'https://www.bang.com/original/3366/bang-real-teens',
|
||||||
|
parameters: JSON.stringify({ siteId: 3366 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'FCK.news',
|
name: 'FCK.news',
|
||||||
slug: 'bangfcknews',
|
slug: 'bangfakenews',
|
||||||
// url: 'https://www.bang.com/original/4998/bang-fckNews',
|
// url: 'https://www.bang.com/original/4998/bang-fckNews',
|
||||||
url: 'https://fck.news',
|
url: 'https://fck.news',
|
||||||
parameters: JSON.stringify({ siteId: 4998 }),
|
parameters: JSON.stringify({ siteId: 4998 }),
|
||||||
|
@ -167,49 +170,56 @@ function getSites(networksMap) {
|
||||||
slug: 'prettyandraw',
|
slug: 'prettyandraw',
|
||||||
// url: 'https://www.bang.com/original/4792/bang-pretty-and-raw',
|
// url: 'https://www.bang.com/original/4792/bang-pretty-and-raw',
|
||||||
url: 'https://prettyandraw.com',
|
url: 'https://prettyandraw.com',
|
||||||
parameters: JSON.stringify({ siteId: 4782 }),
|
parameters: JSON.stringify({ siteId: 4792 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Japan',
|
name: 'Japan',
|
||||||
slug: 'bangjapan',
|
slug: 'bangjapan',
|
||||||
url: 'https://www.bang.com/original/3079/bang-japan',
|
url: 'https://www.bang.com/original/3079/bang-japan',
|
||||||
|
parameters: JSON.stringify({ siteId: 3079 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Rammed',
|
name: 'Rammed',
|
||||||
slug: 'bangrammed',
|
slug: 'bangrammed',
|
||||||
url: 'https://www.bang.com/original/4836/bang-rammed',
|
url: 'https://www.bang.com/original/4836/bang-rammed',
|
||||||
|
parameters: JSON.stringify({ siteId: 4836 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Glamkore',
|
name: 'Glamkore',
|
||||||
slug: 'bangglamkore',
|
slug: 'bangglamkore',
|
||||||
url: 'https://www.bang.com/original/4586/bang-glamkore',
|
url: 'https://www.bang.com/original/4586/bang-glamkore',
|
||||||
|
parameters: JSON.stringify({ siteId: 4586 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Screw The Cops',
|
name: 'Screw The Cops',
|
||||||
slug: 'bangscrewthecops',
|
slug: 'screwthecops',
|
||||||
url: 'https://www.bang.com/original/4710/bang-screw-cops',
|
url: 'https://www.bang.com/original/4710/bang-screw-cops',
|
||||||
|
parameters: JSON.stringify({ siteId: 4710 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Real MILFs',
|
name: 'Real MILFs',
|
||||||
slug: 'bangrealmilfs',
|
slug: 'bangrealmilfs',
|
||||||
url: 'https://www.bang.com/original/4448/bang-real-milfs',
|
url: 'https://www.bang.com/original/4448/bang-real-milfs',
|
||||||
|
parameters: JSON.stringify({ siteId: 4448 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Confessions',
|
name: 'Confessions',
|
||||||
slug: 'bangconfessions',
|
slug: 'bangconfessions',
|
||||||
url: 'https://www.bang.com/original/4308/bang-confessions',
|
url: 'https://www.bang.com/original/4308/bang-confessions',
|
||||||
|
parameters: JSON.stringify({ siteId: 4308 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Casting',
|
name: 'Casting',
|
||||||
slug: 'bangcasting',
|
slug: 'bangcasting',
|
||||||
url: 'https://www.bang.com/original/3261/bang-casting',
|
url: 'https://www.bang.com/original/3261/bang-casting',
|
||||||
|
parameters: JSON.stringify({ siteId: 3261 }),
|
||||||
network_id: networksMap.bang,
|
network_id: networksMap.bang,
|
||||||
},
|
},
|
||||||
// BANGBROS
|
// BANGBROS
|
||||||
|
@ -294,7 +304,7 @@ function getSites(networksMap) {
|
||||||
parameters: null,
|
parameters: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'bangcasting',
|
slug: 'bangbroscasting',
|
||||||
network_id: networksMap.bangbros,
|
network_id: networksMap.bangbros,
|
||||||
name: 'Bang Casting',
|
name: 'Bang Casting',
|
||||||
url: 'https://bangbros.com/websites/bangcasting',
|
url: 'https://bangbros.com/websites/bangcasting',
|
||||||
|
@ -542,9 +552,9 @@ function getSites(networksMap) {
|
||||||
parameters: null,
|
parameters: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'partyof3',
|
slug: 'partyofthree',
|
||||||
network_id: networksMap.bangbros,
|
network_id: networksMap.bangbros,
|
||||||
name: 'Party of 3',
|
name: 'Party of Three',
|
||||||
url: 'https://bangbros.com/websites/partyof3',
|
url: 'https://bangbros.com/websites/partyof3',
|
||||||
description: null,
|
description: null,
|
||||||
parameters: null,
|
parameters: null,
|
||||||
|
|
|
@ -9,6 +9,7 @@ const argv = require('./argv');
|
||||||
const scrapers = require('./scrapers/scrapers');
|
const scrapers = require('./scrapers/scrapers');
|
||||||
const whereOr = require('./utils/where-or');
|
const whereOr = require('./utils/where-or');
|
||||||
const resolvePlace = require('./utils/resolve-place');
|
const resolvePlace = require('./utils/resolve-place');
|
||||||
|
const slugify = require('./utils/slugify');
|
||||||
const { createMediaDirectory, storePhotos } = require('./media');
|
const { createMediaDirectory, storePhotos } = require('./media');
|
||||||
|
|
||||||
async function curateActor(actor) {
|
async function curateActor(actor) {
|
||||||
|
@ -89,7 +90,7 @@ function curateActorEntry(actor, scraped, scrapeSuccess) {
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map(segment => `${segment.charAt(0).toUpperCase()}${segment.slice(1)}`)
|
.map(segment => `${segment.charAt(0).toUpperCase()}${segment.slice(1)}`)
|
||||||
.join(' '),
|
.join(' '),
|
||||||
slug: actor.name.toLowerCase().replace(/\s+/g, '-'),
|
slug: slugify(actor.name),
|
||||||
birthdate: actor.birthdate,
|
birthdate: actor.birthdate,
|
||||||
description: actor.description,
|
description: actor.description,
|
||||||
gender: actor.gender,
|
gender: actor.gender,
|
||||||
|
@ -320,7 +321,7 @@ async function mergeProfiles(profiles, actor) {
|
||||||
async function scrapeActors(actorNames) {
|
async function scrapeActors(actorNames) {
|
||||||
await Promise.map(actorNames || argv.actors, async (actorName) => {
|
await Promise.map(actorNames || argv.actors, async (actorName) => {
|
||||||
try {
|
try {
|
||||||
const actorSlug = actorName.toLowerCase().replace(/\s+/g, '-');
|
const actorSlug = slugify(actorName);
|
||||||
const actorEntry = await knex('actors').where({ slug: actorSlug }).first();
|
const actorEntry = await knex('actors').where({ slug: actorSlug }).first();
|
||||||
const sources = argv.sources ? argv.sources.map(source => [source, scrapers.actors[source]]) : Object.entries(scrapers.actors);
|
const sources = argv.sources ? argv.sources.map(source => [source, scrapers.actors[source]]) : Object.entries(scrapers.actors);
|
||||||
|
|
||||||
|
@ -393,28 +394,40 @@ async function scrapeBasicActors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function associateActors(mappedActors, releases) {
|
async function associateActors(mappedActors, releases) {
|
||||||
|
const actorNames = Object.keys(mappedActors);
|
||||||
|
const actorSlugs = actorNames.map(name => slugify(name));
|
||||||
|
|
||||||
const [existingActorEntries, existingAssociationEntries] = await Promise.all([
|
const [existingActorEntries, existingAssociationEntries] = await Promise.all([
|
||||||
knex('actors').whereIn('name', Object.keys(mappedActors)),
|
knex('actors')
|
||||||
|
.whereIn('name', actorNames)
|
||||||
|
.orWhereIn('slug', actorSlugs),
|
||||||
knex('releases_actors').whereIn('release_id', releases.map(release => release.id)),
|
knex('releases_actors').whereIn('release_id', releases.map(release => release.id)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const associations = await Promise.map(Object.entries(mappedActors), async ([actorName, releaseIds]) => {
|
console.log(actorNames, actorSlugs, existingActorEntries.map(actor => actor.name));
|
||||||
const actorEntry = existingActorEntries.find(actor => actor.name === actorName)
|
|
||||||
|| await storeActor({ name: actorName });
|
|
||||||
|
|
||||||
return releaseIds
|
const associations = await Promise.map(Object.entries(mappedActors), async ([actorName, releaseIds]) => {
|
||||||
.map(releaseId => ({
|
try {
|
||||||
release_id: releaseId,
|
const actorEntry = existingActorEntries.find(actor => actor.name === actorName)
|
||||||
actor_id: actorEntry.id,
|
|| await storeActor({ name: actorName });
|
||||||
}))
|
|
||||||
.filter(association => !existingAssociationEntries
|
return releaseIds
|
||||||
// remove associations already in database
|
.map(releaseId => ({
|
||||||
.some(associationEntry => associationEntry.actor_id === association.actor_id
|
release_id: releaseId,
|
||||||
&& associationEntry.release_id === association.release_id));
|
actor_id: actorEntry.id,
|
||||||
|
}))
|
||||||
|
.filter(association => !existingAssociationEntries
|
||||||
|
// remove associations already in database
|
||||||
|
.some(associationEntry => associationEntry.actor_id === association.actor_id
|
||||||
|
&& associationEntry.release_id === association.release_id));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(actorName, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
knex('releases_actors').insert(associations.flat()),
|
knex('releases_actors').insert(associations.filter(association => association).flat()),
|
||||||
scrapeBasicActors(),
|
scrapeBasicActors(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,12 +172,16 @@ async function attachChannelSite(release) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlSite = await findSiteByUrl(release.channel);
|
try {
|
||||||
|
const urlSite = await findSiteByUrl(release.channel);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...release,
|
...release,
|
||||||
site: urlSite,
|
site: urlSite,
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Unable to derive channel site from generic URL: ${release.url}.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function attachStudio(release) {
|
async function attachStudio(release) {
|
||||||
|
@ -384,7 +388,7 @@ async function storeReleases(releases) {
|
||||||
const storedReleases = await Promise.map(releases, async (release) => {
|
const storedReleases = await Promise.map(releases, async (release) => {
|
||||||
try {
|
try {
|
||||||
const releaseWithChannelSite = await attachChannelSite(release);
|
const releaseWithChannelSite = await attachChannelSite(release);
|
||||||
const releaseWithStudio = await attachStudio(release);
|
const releaseWithStudio = await attachStudio(releaseWithChannelSite);
|
||||||
const releaseId = await storeRelease(releaseWithStudio);
|
const releaseId = await storeRelease(releaseWithStudio);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -403,6 +407,8 @@ async function storeReleases(releases) {
|
||||||
const actors = accumulateActors(storedReleases);
|
const actors = accumulateActors(storedReleases);
|
||||||
const movies = accumulateMovies(storedReleases);
|
const movies = accumulateMovies(storedReleases);
|
||||||
|
|
||||||
|
console.log(actors);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
associateActors(actors, storedReleases),
|
associateActors(actors, storedReleases),
|
||||||
Promise.map(storedReleases, async release => storeReleaseAssets(release, release.id), {
|
Promise.map(storedReleases, async release => storeReleaseAssets(release, release.id), {
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
const bhttp = require('bhttp');
|
const bhttp = require('bhttp');
|
||||||
|
|
||||||
|
const slugify = require('../utils/slugify');
|
||||||
|
|
||||||
|
const clusterId = '617fb597b659459bafe6472470d9073a';
|
||||||
|
const authKey = 'YmFuZy1yZWFkOktqVDN0RzJacmQ1TFNRazI=';
|
||||||
|
|
||||||
function encodeId(id) {
|
function encodeId(id) {
|
||||||
return Buffer
|
return Buffer
|
||||||
.from(id, 'hex')
|
.from(id, 'hex')
|
||||||
|
@ -11,52 +16,62 @@ function encodeId(id) {
|
||||||
.replace(/=/g, ',');
|
.replace(/=/g, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decodeId(id) {
|
||||||
|
const restoredId = id
|
||||||
|
.replace(/-/g, '+')
|
||||||
|
.replace(/_/g, '/')
|
||||||
|
.replace(/,/g, '=');
|
||||||
|
|
||||||
|
return Buffer
|
||||||
|
.from(restoredId, 'base64')
|
||||||
|
.toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeScene(scene, site) {
|
||||||
|
const release = {
|
||||||
|
site,
|
||||||
|
entryId: scene.id,
|
||||||
|
title: scene.name,
|
||||||
|
description: scene.description,
|
||||||
|
actors: scene.actors.map(actor => actor.name),
|
||||||
|
tags: scene.genres.concat(scene.actions).map(genre => genre.name),
|
||||||
|
duration: scene.duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
const slug = slugify(release.title);
|
||||||
|
release.url = `https://www.bang.com/video/${encodeId(release.entryId)}/${slug}`;
|
||||||
|
|
||||||
|
const date = new Date(scene.releaseDate);
|
||||||
|
release.date = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
||||||
|
|
||||||
|
if (scene.is4k) release.tags.push('4k');
|
||||||
|
if (scene.gay) release.tags.push('gay');
|
||||||
|
|
||||||
|
const defaultPoster = scene.screenshots.find(photo => photo.default === true);
|
||||||
|
const photoset = scene.screenshots.filter(photo => photo.default === false);
|
||||||
|
|
||||||
|
const photos = defaultPoster ? photoset : photoset.slice(1);
|
||||||
|
const poster = defaultPoster || photoset[0];
|
||||||
|
|
||||||
|
release.poster = `https://i.bang.com/screenshots/${scene.dvd.id}/movie/${scene.order}/${poster.screenId}.jpg`;
|
||||||
|
release.photos = photos.map(photo => `https://i.bang.com/screenshots/${scene.dvd.id}/movie/${scene.order}/${photo.screenId}.jpg`);
|
||||||
|
|
||||||
|
release.trailer = {
|
||||||
|
src: `https://i.bang.com/v/${scene.dvd.id}/${scene.identifier}/preview.mp4`,
|
||||||
|
};
|
||||||
|
|
||||||
|
release.channel = scene.series.name
|
||||||
|
.replace(/[! .]/g, '')
|
||||||
|
.replace('&', 'and');
|
||||||
|
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
|
||||||
function scrapeLatest(scenes, site) {
|
function scrapeLatest(scenes, site) {
|
||||||
return scenes.map(({ _source: scene }) => {
|
return scenes.map(({ _source: scene }) => scrapeScene(scene, site));
|
||||||
const release = {
|
|
||||||
site,
|
|
||||||
entryId: encodeId(scene.id),
|
|
||||||
title: scene.name,
|
|
||||||
description: scene.description,
|
|
||||||
actors: scene.actors.map(actor => actor.name),
|
|
||||||
tags: scene.genres.concat(scene.actions).map(genre => genre.name),
|
|
||||||
duration: scene.duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
const slug = release.title.toLowerCase().trim().replace(/\s+/g, '-');
|
|
||||||
release.url = `https://www.bang.com/video/${release.entryId}/${slug}`;
|
|
||||||
|
|
||||||
const date = new Date(scene.releaseDate);
|
|
||||||
release.date = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
|
||||||
|
|
||||||
if (scene.is4k) release.tags.push('4k');
|
|
||||||
if (scene.gay) release.tags.push('gay');
|
|
||||||
|
|
||||||
const defaultPoster = scene.screenshots.find(photo => photo.default === true);
|
|
||||||
const photoset = scene.screenshots.filter(photo => photo.default === false);
|
|
||||||
|
|
||||||
const photos = defaultPoster ? photoset : photoset.slice(1);
|
|
||||||
const poster = defaultPoster || photoset[0];
|
|
||||||
|
|
||||||
release.poster = `https://i.bang.com/screenshots/${scene.dvd.id}/movie/1/${poster.screenId}.jpg`;
|
|
||||||
release.photos = photos.map(photo => `https://i.bang.com/screenshots/${scene.dvd.id}/movie/1/${photo.screenId}.jpg`);
|
|
||||||
|
|
||||||
release.trailer = {
|
|
||||||
src: `https://i.bang.com/v/${scene.dvd.id}/${scene.identifier}/preview.mp4`,
|
|
||||||
};
|
|
||||||
|
|
||||||
release.studio = scene.series.name
|
|
||||||
.replace(/[! .]/g, '')
|
|
||||||
.replace('&', 'and');
|
|
||||||
|
|
||||||
return release;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchLatest(site, page = 1) {
|
async function fetchLatest(site, page = 1) {
|
||||||
const clusterId = '617fb597b659459bafe6472470d9073a';
|
|
||||||
const authKey = 'YmFuZy1yZWFkOktqVDN0RzJacmQ1TFNRazI=';
|
|
||||||
|
|
||||||
const res = await bhttp.post(`https://${clusterId}.us-east-1.aws.found.io/videos/video/_search`, {
|
const res = await bhttp.post(`https://${clusterId}.us-east-1.aws.found.io/videos/video/_search`, {
|
||||||
size: 50,
|
size: 50,
|
||||||
from: (page - 1) * 50,
|
from: (page - 1) * 50,
|
||||||
|
@ -75,6 +90,8 @@ async function fetchLatest(site, page = 1) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
* global fetch
|
||||||
{
|
{
|
||||||
nested: {
|
nested: {
|
||||||
path: 'studio',
|
path: 'studio',
|
||||||
|
@ -94,6 +111,26 @@ async function fetchLatest(site, page = 1) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
nested: {
|
||||||
|
path: 'series',
|
||||||
|
query: {
|
||||||
|
bool: {
|
||||||
|
must: [
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
'series.id': {
|
||||||
|
operator: 'AND',
|
||||||
|
query: site.parameters.siteId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
must_not: [
|
must_not: [
|
||||||
{
|
{
|
||||||
|
@ -121,7 +158,20 @@ async function fetchLatest(site, page = 1) {
|
||||||
return scrapeLatest(res.body.hits.hits, site);
|
return scrapeLatest(res.body.hits.hits, site);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchScene(url, site) {
|
||||||
|
const encodedId = new URL(url).pathname.split('/')[2];
|
||||||
|
const entryId = decodeId(encodedId);
|
||||||
|
|
||||||
|
const res = await bhttp.get(`https://${clusterId}.us-east-1.aws.found.io/videos/video/${entryId}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Basic ${authKey}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return scrapeScene(res.body._source, site); // eslint-disable-line no-underscore-dangle
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
fetchLatest,
|
fetchLatest,
|
||||||
// fetchScene,
|
fetchScene,
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,9 +5,6 @@ const bhttp = require('bhttp');
|
||||||
const cheerio = require('cheerio');
|
const cheerio = require('cheerio');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
|
||||||
const knex = require('../knex');
|
|
||||||
const { matchTags } = require('../tags');
|
|
||||||
|
|
||||||
function scrapeLatest(html, site) {
|
function scrapeLatest(html, site) {
|
||||||
const $ = cheerio.load(html, { normalizeWhitespace: true });
|
const $ = cheerio.load(html, { normalizeWhitespace: true });
|
||||||
const sceneElements = $('.echThumb').toArray();
|
const sceneElements = $('.echThumb').toArray();
|
||||||
|
@ -57,7 +54,7 @@ async function scrapeScene(html, url, site) {
|
||||||
const description = sceneElement.find('.vdoDesc').text().trim();
|
const description = sceneElement.find('.vdoDesc').text().trim();
|
||||||
|
|
||||||
const [siteName, ...actors] = sceneElement.find('.vdoCast a').map((actorIndex, actorElement) => $(actorElement).text()).toArray();
|
const [siteName, ...actors] = sceneElement.find('.vdoCast a').map((actorIndex, actorElement) => $(actorElement).text()).toArray();
|
||||||
const siteId = siteName.replace(/[\s']+/g, '').toLowerCase();
|
const siteSlug = siteName.replace(/[\s']+/g, '').toLowerCase();
|
||||||
|
|
||||||
const poster = `https:${$('img#player-overlay-image').attr('src')}`;
|
const poster = `https:${$('img#player-overlay-image').attr('src')}`;
|
||||||
const trailer = `https:${$('source[type="video/mp4"]').attr('src')}`;
|
const trailer = `https:${$('source[type="video/mp4"]').attr('src')}`;
|
||||||
|
@ -66,17 +63,7 @@ async function scrapeScene(html, url, site) {
|
||||||
// all scenes seem to have 12 album photos available, not always included on the page
|
// all scenes seem to have 12 album photos available, not always included on the page
|
||||||
const photos = Array.from({ length: 12 }, (val, index) => firstPhotoUrl.replace(/big\d+/, `big${index + 1}`));
|
const photos = Array.from({ length: 12 }, (val, index) => firstPhotoUrl.replace(/big\d+/, `big${index + 1}`));
|
||||||
|
|
||||||
const rawTags = $('.vdoTags a').map((tagIndex, tagElement) => $(tagElement).text()).toArray();
|
const tags = $('.vdoTags a').map((tagIndex, tagElement) => $(tagElement).text()).toArray();
|
||||||
|
|
||||||
const [channelSite, tags] = await Promise.all([
|
|
||||||
site.isFallback
|
|
||||||
? knex('sites')
|
|
||||||
.where({ slug: siteId })
|
|
||||||
.orWhere({ name: siteName })
|
|
||||||
.first()
|
|
||||||
: site,
|
|
||||||
matchTags(rawTags),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const stars = Number(sceneElement.find('.bVdPl_it_like .bVdPl_txt').text().replace('% like', '')) / 20;
|
const stars = Number(sceneElement.find('.bVdPl_it_like .bVdPl_txt').text().replace('% like', '')) / 20;
|
||||||
|
|
||||||
|
@ -96,12 +83,13 @@ async function scrapeScene(html, url, site) {
|
||||||
rating: {
|
rating: {
|
||||||
stars,
|
stars,
|
||||||
},
|
},
|
||||||
site: channelSite || site,
|
site,
|
||||||
|
channel: siteSlug === 'bangcasting' ? 'bangbroscasting' : siteSlug,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchLatest(site, page = 1) {
|
async function fetchLatest(site, page = 1) {
|
||||||
const res = await bhttp.get(`https://bangbros.com/websites/${site.slug}/${page}`);
|
const res = await bhttp.get(`${site.url}/${page}`);
|
||||||
|
|
||||||
return scrapeLatest(res.body.toString(), site);
|
return scrapeLatest(res.body.toString(), site);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function slugify(string) {
|
||||||
|
return string.trim().toLowerCase().match(/\w+/g).join('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = slugify;
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
const ActorPlugins = require('./actors');
|
const ActorPlugins = require('./actors');
|
||||||
const SitePlugins = require('./sites');
|
const SitePlugins = require('./sites');
|
||||||
|
// const ReleasePlugins = require('./releases');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ActorPlugins,
|
ActorPlugins,
|
||||||
SitePlugins,
|
SitePlugins,
|
||||||
|
ReleasePlugins: [],
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { makeExtendSchemaPlugin, gql } = require('graphile-utils');
|
||||||
|
|
||||||
|
const schemaExtender = makeExtendSchemaPlugin(_build => ({
|
||||||
|
typeDefs: gql`
|
||||||
|
`,
|
||||||
|
resolvers: {
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
module.exports = [schemaExtender];
|
|
@ -11,7 +11,7 @@ const PgConnectionFilterPlugin = require('postgraphile-plugin-connection-filter'
|
||||||
const PgSimplifyInflectorPlugin = require('@graphile-contrib/pg-simplify-inflector');
|
const PgSimplifyInflectorPlugin = require('@graphile-contrib/pg-simplify-inflector');
|
||||||
const PgOrderByRelatedPlugin = require('@graphile-contrib/pg-order-by-related');
|
const PgOrderByRelatedPlugin = require('@graphile-contrib/pg-order-by-related');
|
||||||
|
|
||||||
const { ActorPlugins, SitePlugins } = require('./plugins/plugins');
|
const { ActorPlugins, SitePlugins, ReleasePlugins } = require('./plugins/plugins');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
fetchReleases,
|
fetchReleases,
|
||||||
|
@ -57,6 +57,7 @@ function initServer() {
|
||||||
PgOrderByRelatedPlugin,
|
PgOrderByRelatedPlugin,
|
||||||
...ActorPlugins,
|
...ActorPlugins,
|
||||||
...SitePlugins,
|
...SitePlugins,
|
||||||
|
...ReleasePlugins,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|