diff --git a/assets/components/filters/filter-bar.vue b/assets/components/filters/filter-bar.vue index 6f9ce732..9692b062 100644 --- a/assets/components/filters/filter-bar.vue +++ b/assets/components/filters/filter-bar.vue @@ -22,13 +22,13 @@
@@ -251,6 +251,14 @@ export default { .filter-applied { display: none; } + + .filters-filter:not(:last-child) .filter { + padding: 1rem .5rem; + } + + .filters-filter:last-child .filter { + padding: 1rem 0 1rem .5rem; + } } @@ -312,7 +320,7 @@ export default { } } -.filter { +.filters-filter { display: inline-block; flex-shrink: 0; diff --git a/config/default.js b/config/default.js index 1d95a5cc..c343e340 100644 --- a/config/default.js +++ b/config/default.js @@ -161,14 +161,15 @@ module.exports = { 'pervertgallery', 'povperverts', ], + 'kellymadison', 'private', 'ddfnetwork', 'bangbros', + 'hitzefrei', [ 'silverstonedvd', 'silviasaint', ], - 'kellymadison', 'gangbangcreampie', 'gloryholesecrets', 'aziani', diff --git a/public/img/logos/hitzefrei/citycheck.png b/public/img/logos/hitzefrei/citycheck.png new file mode 100644 index 00000000..c2e41429 Binary files /dev/null and b/public/img/logos/hitzefrei/citycheck.png differ diff --git a/public/img/logos/hitzefrei/cuffemall.png b/public/img/logos/hitzefrei/cuffemall.png new file mode 100644 index 00000000..e81deed6 Binary files /dev/null and b/public/img/logos/hitzefrei/cuffemall.png differ diff --git a/public/img/logos/hitzefrei/familyaffairs.png b/public/img/logos/hitzefrei/familyaffairs.png new file mode 100644 index 00000000..bddb0cab Binary files /dev/null and b/public/img/logos/hitzefrei/familyaffairs.png differ diff --git a/public/img/logos/hitzefrei/fanalarm.png b/public/img/logos/hitzefrei/fanalarm.png new file mode 100644 index 00000000..834dcc29 Binary files /dev/null and b/public/img/logos/hitzefrei/fanalarm.png differ diff --git a/public/img/logos/hitzefrei/favicon.png b/public/img/logos/hitzefrei/favicon.png new file mode 100644 index 00000000..c9f92419 Binary files /dev/null and b/public/img/logos/hitzefrei/favicon.png differ diff --git a/public/img/logos/hitzefrei/fuckonarrival.png b/public/img/logos/hitzefrei/fuckonarrival.png new file mode 100644 index 00000000..e7a07cf8 Binary files /dev/null and b/public/img/logos/hitzefrei/fuckonarrival.png differ diff --git a/public/img/logos/hitzefrei/lazy/citycheck.png b/public/img/logos/hitzefrei/lazy/citycheck.png new file mode 100644 index 00000000..52d4e2bf Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/citycheck.png differ diff --git a/public/img/logos/hitzefrei/lazy/cuffemall.png b/public/img/logos/hitzefrei/lazy/cuffemall.png new file mode 100644 index 00000000..51441fca Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/cuffemall.png differ diff --git a/public/img/logos/hitzefrei/lazy/familyaffairs.png b/public/img/logos/hitzefrei/lazy/familyaffairs.png new file mode 100644 index 00000000..fee039d4 Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/familyaffairs.png differ diff --git a/public/img/logos/hitzefrei/lazy/fanalarm.png b/public/img/logos/hitzefrei/lazy/fanalarm.png new file mode 100644 index 00000000..cdaeedd1 Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/fanalarm.png differ diff --git a/public/img/logos/hitzefrei/lazy/fuckonarrival.png b/public/img/logos/hitzefrei/lazy/fuckonarrival.png new file mode 100644 index 00000000..f29f12ab Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/fuckonarrival.png differ diff --git a/public/img/logos/hitzefrei/lazy/hitzefrei.png b/public/img/logos/hitzefrei/lazy/hitzefrei.png new file mode 100644 index 00000000..490484a6 Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/hitzefrei.png differ diff --git a/public/img/logos/hitzefrei/lazy/milfhunters.png b/public/img/logos/hitzefrei/lazy/milfhunters.png new file mode 100644 index 00000000..355829c4 Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/milfhunters.png differ diff --git a/public/img/logos/hitzefrei/lazy/network.png b/public/img/logos/hitzefrei/lazy/network.png new file mode 100644 index 00000000..7eaa9d2b Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/network.png differ diff --git a/public/img/logos/hitzefrei/lazy/pattisanals.png b/public/img/logos/hitzefrei/lazy/pattisanals.png new file mode 100644 index 00000000..6066aef3 Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/pattisanals.png differ diff --git a/public/img/logos/hitzefrei/lazy/unleashed.png b/public/img/logos/hitzefrei/lazy/unleashed.png new file mode 100644 index 00000000..497d57e4 Binary files /dev/null and b/public/img/logos/hitzefrei/lazy/unleashed.png differ diff --git a/public/img/logos/hitzefrei/milfhunters.png b/public/img/logos/hitzefrei/milfhunters.png new file mode 100644 index 00000000..d3cdc346 Binary files /dev/null and b/public/img/logos/hitzefrei/milfhunters.png differ diff --git a/public/img/logos/hitzefrei/misc/hitzefrei.png b/public/img/logos/hitzefrei/misc/hitzefrei.png new file mode 100644 index 00000000..31031c1b Binary files /dev/null and b/public/img/logos/hitzefrei/misc/hitzefrei.png differ diff --git a/public/img/logos/hitzefrei/network.png b/public/img/logos/hitzefrei/network.png new file mode 100644 index 00000000..0fb143f5 Binary files /dev/null and b/public/img/logos/hitzefrei/network.png differ diff --git a/public/img/logos/hitzefrei/pattisanals.png b/public/img/logos/hitzefrei/pattisanals.png new file mode 100644 index 00000000..b979e9ed Binary files /dev/null and b/public/img/logos/hitzefrei/pattisanals.png differ diff --git a/public/img/logos/hitzefrei/thumbs/citycheck.png b/public/img/logos/hitzefrei/thumbs/citycheck.png new file mode 100644 index 00000000..0bc2b644 Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/citycheck.png differ diff --git a/public/img/logos/hitzefrei/thumbs/cuffemall.png b/public/img/logos/hitzefrei/thumbs/cuffemall.png new file mode 100644 index 00000000..82021932 Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/cuffemall.png differ diff --git a/public/img/logos/hitzefrei/thumbs/familyaffairs.png b/public/img/logos/hitzefrei/thumbs/familyaffairs.png new file mode 100644 index 00000000..9266cff5 Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/familyaffairs.png differ diff --git a/public/img/logos/hitzefrei/thumbs/fanalarm.png b/public/img/logos/hitzefrei/thumbs/fanalarm.png new file mode 100644 index 00000000..72e8cca9 Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/fanalarm.png differ diff --git a/public/img/logos/hitzefrei/thumbs/fuckonarrival.png b/public/img/logos/hitzefrei/thumbs/fuckonarrival.png new file mode 100644 index 00000000..9676c9af Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/fuckonarrival.png differ diff --git a/public/img/logos/hitzefrei/thumbs/hitzefrei.png b/public/img/logos/hitzefrei/thumbs/hitzefrei.png new file mode 100644 index 00000000..84d5fb8e Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/hitzefrei.png differ diff --git a/public/img/logos/hitzefrei/thumbs/milfhunters.png b/public/img/logos/hitzefrei/thumbs/milfhunters.png new file mode 100644 index 00000000..db7e740f Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/milfhunters.png differ diff --git a/public/img/logos/hitzefrei/thumbs/network.png b/public/img/logos/hitzefrei/thumbs/network.png new file mode 100644 index 00000000..eaef2d28 Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/network.png differ diff --git a/public/img/logos/hitzefrei/thumbs/pattisanals.png b/public/img/logos/hitzefrei/thumbs/pattisanals.png new file mode 100644 index 00000000..935b6ed5 Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/pattisanals.png differ diff --git a/public/img/logos/hitzefrei/thumbs/unleashed.png b/public/img/logos/hitzefrei/thumbs/unleashed.png new file mode 100644 index 00000000..c66571db Binary files /dev/null and b/public/img/logos/hitzefrei/thumbs/unleashed.png differ diff --git a/public/img/logos/hitzefrei/unleashed.png b/public/img/logos/hitzefrei/unleashed.png new file mode 100644 index 00000000..6f27fa96 Binary files /dev/null and b/public/img/logos/hitzefrei/unleashed.png differ diff --git a/seeds/01_networks.js b/seeds/01_networks.js index e26f5d7d..504650d3 100644 --- a/seeds/01_networks.js +++ b/seeds/01_networks.js @@ -218,6 +218,11 @@ const networks = [ description: 'Girlsway.com has the best lesbian porn videos online! The hottest pornstars & first time lesbians in real girl on girl sex, tribbing, squirting & pussy licking action right HERE!', parent: 'gamma', }, + { + slug: 'hitzefrei', + name: 'Hitzefrei', + url: 'http://www.hitzefrei.com', + }, { slug: 'hussiepass', name: 'Hussie Pass', diff --git a/seeds/02_sites.js b/seeds/02_sites.js index cff532f7..a0d96441 100644 --- a/seeds/02_sites.js +++ b/seeds/02_sites.js @@ -2354,6 +2354,83 @@ const sites = [ referer: 'https://www.girlsway.com', }, }, + // HITZEFREI + { + slug: 'unleashed', + name: 'Unleashed', + url: 'https://unleashed.hitzefrei.com', + parent: 'hitzefrei', + parameters: { + siteId: 10, + }, + }, + { + slug: 'citycheck', + name: 'City Check', + url: 'https://citycheck.hitzefrei.com', + parent: 'hitzefrei', + parameters: { + siteId: 3, + }, + }, + { + slug: 'milfhunters', + name: 'MILF Hunters', + url: 'https://milfhunters.hitzefrei.com', + parent: 'hitzefrei', + tags: ['milf'], + parameters: { + siteId: 7, + }, + }, + { + slug: 'cuffemall', + name: 'Cuff\'em All', + url: 'https://cuffemall.hitzefrei.com', + parent: 'hitzefrei', + parameters: { + siteId: 8, + }, + }, + { + slug: 'fanalarm', + name: 'fANALarm', + url: 'https://fanalarm.hitzefrei.com', + parent: 'hitzefrei', + tags: ['anal'], + parameters: { + siteId: 9, + }, + }, + { + slug: 'fuckonarrival', + name: 'Fuck On Arrival', + url: 'https://fuckonarrival.hitzefrei.com', + parent: 'hitzefrei', + parameters: { + siteId: 5, + }, + }, + { + slug: 'familyaffairs', + name: 'Family Affairs', + url: 'https://familyaffairs.hitzefrei.com', + parent: 'hitzefrei', + tags: ['family'], + parameters: { + siteId: 2, + }, + }, + { + slug: 'pattisanals', + name: 'Patti\'s Anals', + url: 'https://pattisanals.hitzefrei.com', + parent: 'hitzefrei', + tags: ['anal'], + parameters: { + siteId: 1, + }, + }, // HUSSIE PASS { slug: 'hussiepass', diff --git a/src/actors.js b/src/actors.js index 0f091768..d3e879e8 100644 --- a/src/actors.js +++ b/src/actors.js @@ -97,11 +97,11 @@ function getMostFrequentDate(dates) { const month = getMostFrequent(dates.map(dateX => dateX.getMonth())); const date = getMostFrequent(dates.map(dateX => dateX.getDate())); - if (year && month && date) { - return moment({ year, month, date }).toDate(); + if (year === null || month === null || date === null) { + return null; } - return null; + return moment({ year, month, date }).toDate(); } function getLongest(items) { @@ -216,7 +216,7 @@ function curateActorEntry(baseActor, batchId) { name: baseActor.name, slug: baseActor.slug, entity_id: null, - entry_id: baseActor.entry_id, + entry_id: baseActor.entryId, batch_id: batchId, }; } @@ -615,6 +615,8 @@ async function scrapeActors(actorNames) { const [batchId] = newBaseActors.length > 0 ? await knex('batches').insert({ comment: null }).returning('id') : [null]; const curatedActorEntries = batchId && curateActorEntries(newBaseActors, batchId); + // TODO: associate entity when entry ID is provided + const newActorEntries = batchId && await knex('actors') .insert(curatedActorEntries) .returning(['id', 'name', 'slug', 'entry_id']); diff --git a/src/scrapers/brazzers.js b/src/scrapers/brazzers.js index 4d0aa2d9..8e8ee34c 100644 --- a/src/scrapers/brazzers.js +++ b/src/scrapers/brazzers.js @@ -57,8 +57,8 @@ async function scrapeScene({ query, html }, url, _site) { release.description = query.text('#scene-description p[itemprop="description"]'); release.date = query.date('.more-scene-info .scene-date', 'MMMM DD, YYYY'); - release.duration = Number(query.q('#trailer-player-container', 'data-duration')) // more accurate - || Number(query.q('.scene-length[itemprop="duration"]', 'content').slice(1, -1) * 60); + release.duration = query.number('#trailer-player-container', 'data-duration') // more accurate + || query.number('.scene-length[itemprop="duration"]', 'content') * 60; // fallback // actor cards have avatar, but truncated name const actorImagesByActorId = query.imgs('.featured-model .card-image img').reduce((acc, img) => ({ diff --git a/src/scrapers/hitzefrei.js b/src/scrapers/hitzefrei.js new file mode 100644 index 00000000..8edbfaf8 --- /dev/null +++ b/src/scrapers/hitzefrei.js @@ -0,0 +1,157 @@ +'use strict'; + +const qu = require('../utils/qu'); +const http = require('../utils/http'); +const { lbsToKg, feetInchesToCm } = require('../utils/convert'); +const slugify = require('../utils/slugify'); + +function scrapeAll(scenes) { + return scenes.map(({ query }) => { + const release = {}; + + release.url = query.url('.content-title a'); + release.entryId = new URL(release.url).pathname.match(/\/view\/(\d+)/)[1]; + + release.title = query.cnt('.content-title a'); + release.date = query.date('.content-date strong', 'DD/MM/YYYY'); + release.duration = query.dur('.content-date'); + + release.actors = query.cnts('.content-models a'); + + release.poster = query.img('.content-thumbnail img, .large-thumbnail img') || query.poster('.content-thumbnail video, .large-thumbnail video'); + + const teaser = query.video('.vid-hover source'); + release.teaser = { src: teaser }; + + release.channel = slugify(query.cnt('.content-site a'), ''); + + return release; + }); +} + +function scrapeScene({ query }, url) { + const release = {}; + + release.entryId = new URL(url).pathname.match(/\/view\/(\d+)/)[1]; + + release.title = query.cnt('.content-title'); + release.description = query.cnt('.content-description p'); + + release.date = query.date('.content-metas span:nth-child(4)', 'DD/MM/YYYY'); + release.duration = query.dur('.content-metas span:nth-child(2)'); + release.likes = query.number('.content-metas span:nth-child(6)'); + + release.actors = query.all('.model-thumb img').map(el => ({ + name: query.q(el, null, 'alt'), + avatar: query.img(el, null, 'src'), + })); + + release.poster = query.poster('.content-video video'); + release.photos = query.urls('#photo-carousel a').map(photo => [ + photo.replace('/full', ''), + photo, + photo.replace('/full', '/thumbs'), + ]); + + const trailer = query.video('.content-video source'); + release.trailer = { src: trailer }; + + return release; +} + +async function fetchActorScenes({ query }, accReleases = []) { + const releases = scrapeAll(qu.initAll(query.all('.container-large-video-thumb'))); + const nextPage = query.url('.pagination li:nth-last-child(2) a'); + + if (nextPage) { + const res = await qu.get(nextPage); + + if (res.ok) { + return fetchActorScenes(res.item, accReleases.concat(releases)); + } + } + + return accReleases.concat(releases); +} + +async function scrapeProfile({ query }, include) { + const profile = {}; + + /* + const bio = query.all('.model-stats-info div div').reduce((acc, el) => ({ + ...acc, + [slugify(query.cnt(el, '.stat-label'), '_')]: query.cnt(el, '.stat-value'), + }), {}); + */ + + profile.dateOfBirth = query.date('.col-birtdate .stat-value, .col-birthdate .stat-value', 'YYYY-MM-DD'); // sic + profile.birthPlace = query.cnt('.col-birth .stat-value'); + + [profile.bust, profile.waist, profile.hip] = query.cnt('.col-measurements .stat-value').split('-').map(Number); + profile.height = feetInchesToCm(query.cnt('.col-height .stat-value')); + profile.weight = lbsToKg(query.number('.col-weight .stat-value')); + + profile.eyes = query.cnt('.col-eyes .stat-value'); + profile.hair = query.cnt('.col-hair .stat-value'); + + profile.description = query.cnt('.model-profile .model-profile'); + profile.avatar = query.img('.model-thumbnail img'); + + if (include.releases) { + profile.releases = await fetchActorScenes({ query }); + } + + return profile; +} + +async function fetchLatest(channel, page = 1) { + const res = await qu.getAll(`https://tour.hitzefrei.com/videos?site=${channel.parameters.siteId}&page=${page}`, '.hitem'); + + if (res.ok) { + return scrapeAll(res.items, channel); + } + + return res.status; +} + +async function fetchScene(url) { + const res = await qu.get(url, '#content-details'); + + if (res.ok) { + return scrapeScene(res.item, url); + } + + return res.status; +} + +async function fetchProfile(baseActor, entity, include) { + const searchRes = await http.post('https://tour.hitzefrei.com/search-preview', { + q: baseActor.name, + }, { + 'Accept-Language': 'en-US', + }); + + if (searchRes.ok) { + const actor = searchRes.body.find(result => result.type === 'model' && result.title === baseActor.name); + + if (actor) { + const actorRes = await qu.get(actor.url); + + if (actorRes.ok) { + return scrapeProfile(actorRes.item, include); + } + + return actorRes.status; + } + + return null; + } + + return searchRes.status; +} + +module.exports = { + fetchLatest, + fetchScene, + fetchProfile, +}; diff --git a/src/scrapers/scrapers.js b/src/scrapers/scrapers.js index 2162ac0b..bb5f7201 100644 --- a/src/scrapers/scrapers.js +++ b/src/scrapers/scrapers.js @@ -23,6 +23,7 @@ const fantasymassage = require('./fantasymassage'); const fcuk = require('./fcuk'); const fullpornnetwork = require('./fullpornnetwork'); const girlsway = require('./girlsway'); +const hitzefrei = require('./hitzefrei'); const hush = require('./hush'); const iconmale = require('./iconmale'); const insex = require('./insex'); @@ -101,6 +102,7 @@ module.exports = { fullpornnetwork, girlsway, girlgirl: julesjordan, + hitzefrei, hussiepass: hush, hushpass: hush, insex, @@ -183,6 +185,7 @@ module.exports = { girlfaction: fullpornnetwork, gloryholesecrets: aziani, hergape: fullpornnetwork, + hitzefrei, homemadeanalwhores: fullpornnetwork, hotcrazymess: nubiles, hushpass: hush,