diff --git a/public/img/logos/teamskeet/badmilfs.png b/public/img/logos/teamskeet/badmilfs.png new file mode 100644 index 000000000..106818574 Binary files /dev/null and b/public/img/logos/teamskeet/badmilfs.png differ diff --git a/public/img/logos/teamskeet/bracefaced.png b/public/img/logos/teamskeet/bracefaced.png new file mode 100644 index 000000000..8a5570ff9 Binary files /dev/null and b/public/img/logos/teamskeet/bracefaced.png differ diff --git a/public/img/logos/teamskeet/cfnmteens.png b/public/img/logos/teamskeet/cfnmteens.png new file mode 100644 index 000000000..e08cc44ba Binary files /dev/null and b/public/img/logos/teamskeet/cfnmteens.png differ diff --git a/public/img/logos/teamskeet/dadcrush.png b/public/img/logos/teamskeet/dadcrush.png new file mode 100644 index 000000000..40a7154a1 Binary files /dev/null and b/public/img/logos/teamskeet/dadcrush.png differ diff --git a/public/img/logos/teamskeet/daughterswap.png b/public/img/logos/teamskeet/daughterswap.png new file mode 100644 index 000000000..44ae20334 Binary files /dev/null and b/public/img/logos/teamskeet/daughterswap.png differ diff --git a/public/img/logos/teamskeet/dyked.png b/public/img/logos/teamskeet/dyked.png new file mode 100644 index 000000000..ba29f7f35 Binary files /dev/null and b/public/img/logos/teamskeet/dyked.png differ diff --git a/public/img/logos/teamskeet/exxxtrasmall.png b/public/img/logos/teamskeet/exxxtrasmall.png new file mode 100644 index 000000000..244b47822 Binary files /dev/null and b/public/img/logos/teamskeet/exxxtrasmall.png differ diff --git a/public/img/logos/teamskeet/favicon.png b/public/img/logos/teamskeet/favicon.png new file mode 100644 index 000000000..2e81cacc5 Binary files /dev/null and b/public/img/logos/teamskeet/favicon.png differ diff --git a/public/img/logos/teamskeet/gingerpatch.png b/public/img/logos/teamskeet/gingerpatch.png new file mode 100644 index 000000000..5e9b00d85 Binary files /dev/null and b/public/img/logos/teamskeet/gingerpatch.png differ diff --git a/public/img/logos/teamskeet/herfreshmanyear.png b/public/img/logos/teamskeet/herfreshmanyear.png new file mode 100644 index 000000000..3febe4eaa Binary files /dev/null and b/public/img/logos/teamskeet/herfreshmanyear.png differ diff --git a/public/img/logos/teamskeet/innocenthigh.png b/public/img/logos/teamskeet/innocenthigh.png new file mode 100644 index 000000000..cf65741b6 Binary files /dev/null and b/public/img/logos/teamskeet/innocenthigh.png differ diff --git a/public/img/logos/teamskeet/lusthd.png b/public/img/logos/teamskeet/lusthd.png new file mode 100644 index 000000000..29136e3fb Binary files /dev/null and b/public/img/logos/teamskeet/lusthd.png differ diff --git a/public/img/logos/teamskeet/misc/cfnm-teens_original.png b/public/img/logos/teamskeet/misc/cfnm-teens_original.png new file mode 100644 index 000000000..a13ae5566 Binary files /dev/null and b/public/img/logos/teamskeet/misc/cfnm-teens_original.png differ diff --git a/public/img/logos/teamskeet/misc/dad-crush_original.png b/public/img/logos/teamskeet/misc/dad-crush_original.png new file mode 100644 index 000000000..1fce8991d Binary files /dev/null and b/public/img/logos/teamskeet/misc/dad-crush_original.png differ diff --git a/public/img/logos/teamskeet/misc/dyked_old.png b/public/img/logos/teamskeet/misc/dyked_old.png new file mode 100644 index 000000000..17afdf9f7 Binary files /dev/null and b/public/img/logos/teamskeet/misc/dyked_old.png differ diff --git a/public/img/logos/teamskeet/misc/pov-life.png b/public/img/logos/teamskeet/misc/pov-life.png new file mode 100644 index 000000000..213f9b9ab Binary files /dev/null and b/public/img/logos/teamskeet/misc/pov-life.png differ diff --git a/public/img/logos/teamskeet/misc/team-skeet_dark.png b/public/img/logos/teamskeet/misc/team-skeet_dark.png new file mode 100644 index 000000000..ffa7c3e15 Binary files /dev/null and b/public/img/logos/teamskeet/misc/team-skeet_dark.png differ diff --git a/public/img/logos/teamskeet/misc/team-skeet_light.png b/public/img/logos/teamskeet/misc/team-skeet_light.png new file mode 100644 index 000000000..5429d2733 Binary files /dev/null and b/public/img/logos/teamskeet/misc/team-skeet_light.png differ diff --git a/public/img/logos/teamskeet/misc/team-skeet_square.png b/public/img/logos/teamskeet/misc/team-skeet_square.png new file mode 100644 index 000000000..4b318dc33 Binary files /dev/null and b/public/img/logos/teamskeet/misc/team-skeet_square.png differ diff --git a/public/img/logos/teamskeet/mybabysittersclub.png b/public/img/logos/teamskeet/mybabysittersclub.png new file mode 100644 index 000000000..c6af8faa1 Binary files /dev/null and b/public/img/logos/teamskeet/mybabysittersclub.png differ diff --git a/public/img/logos/teamskeet/network.png b/public/img/logos/teamskeet/network.png new file mode 100644 index 000000000..4b318dc33 Binary files /dev/null and b/public/img/logos/teamskeet/network.png differ diff --git a/public/img/logos/teamskeet/oyeloca.png b/public/img/logos/teamskeet/oyeloca.png new file mode 100644 index 000000000..84016cd30 Binary files /dev/null and b/public/img/logos/teamskeet/oyeloca.png differ diff --git a/public/img/logos/teamskeet/povlife.png b/public/img/logos/teamskeet/povlife.png new file mode 100644 index 000000000..5b66c795a Binary files /dev/null and b/public/img/logos/teamskeet/povlife.png differ diff --git a/public/img/logos/teamskeet/rubateen.png b/public/img/logos/teamskeet/rubateen.png new file mode 100644 index 000000000..6592fab0c Binary files /dev/null and b/public/img/logos/teamskeet/rubateen.png differ diff --git a/public/img/logos/teamskeet/selfdesire.png b/public/img/logos/teamskeet/selfdesire.png new file mode 100644 index 000000000..eec43d652 Binary files /dev/null and b/public/img/logos/teamskeet/selfdesire.png differ diff --git a/public/img/logos/teamskeet/shesnew.png b/public/img/logos/teamskeet/shesnew.png new file mode 100644 index 000000000..e65a4232d Binary files /dev/null and b/public/img/logos/teamskeet/shesnew.png differ diff --git a/public/img/logos/teamskeet/sislovesme.png b/public/img/logos/teamskeet/sislovesme.png new file mode 100644 index 000000000..71ba27ac1 Binary files /dev/null and b/public/img/logos/teamskeet/sislovesme.png differ diff --git a/public/img/logos/teamskeet/solointerviews.png b/public/img/logos/teamskeet/solointerviews.png new file mode 100644 index 000000000..7e33f8e35 Binary files /dev/null and b/public/img/logos/teamskeet/solointerviews.png differ diff --git a/public/img/logos/teamskeet/stepsiblings.png b/public/img/logos/teamskeet/stepsiblings.png new file mode 100644 index 000000000..2ebcaa11c Binary files /dev/null and b/public/img/logos/teamskeet/stepsiblings.png differ diff --git a/public/img/logos/teamskeet/teamskeetextras.png b/public/img/logos/teamskeet/teamskeetextras.png new file mode 100644 index 000000000..d7cb98568 Binary files /dev/null and b/public/img/logos/teamskeet/teamskeetextras.png differ diff --git a/public/img/logos/teamskeet/teencurves.png b/public/img/logos/teamskeet/teencurves.png new file mode 100644 index 000000000..269267a4e Binary files /dev/null and b/public/img/logos/teamskeet/teencurves.png differ diff --git a/public/img/logos/teamskeet/teenjoi.png b/public/img/logos/teamskeet/teenjoi.png new file mode 100644 index 000000000..4f0f00933 Binary files /dev/null and b/public/img/logos/teamskeet/teenjoi.png differ diff --git a/public/img/logos/teamskeet/teenpies.png b/public/img/logos/teamskeet/teenpies.png new file mode 100644 index 000000000..7ab7086ae Binary files /dev/null and b/public/img/logos/teamskeet/teenpies.png differ diff --git a/public/img/logos/teamskeet/teensdoporn.png b/public/img/logos/teamskeet/teensdoporn.png new file mode 100644 index 000000000..edb07c8df Binary files /dev/null and b/public/img/logos/teamskeet/teensdoporn.png differ diff --git a/public/img/logos/teamskeet/teensloveanal.png b/public/img/logos/teamskeet/teensloveanal.png new file mode 100644 index 000000000..a83933e56 Binary files /dev/null and b/public/img/logos/teamskeet/teensloveanal.png differ diff --git a/public/img/logos/teamskeet/teenslovemoney.png b/public/img/logos/teamskeet/teenslovemoney.png new file mode 100644 index 000000000..16fc1d747 Binary files /dev/null and b/public/img/logos/teamskeet/teenslovemoney.png differ diff --git a/public/img/logos/teamskeet/teenyblack.png b/public/img/logos/teamskeet/teenyblack.png new file mode 100644 index 000000000..ca853a0a8 Binary files /dev/null and b/public/img/logos/teamskeet/teenyblack.png differ diff --git a/public/img/logos/teamskeet/therealworkout.png b/public/img/logos/teamskeet/therealworkout.png new file mode 100644 index 000000000..aa150ff5a Binary files /dev/null and b/public/img/logos/teamskeet/therealworkout.png differ diff --git a/public/img/logos/teamskeet/thisgirlsucks.png b/public/img/logos/teamskeet/thisgirlsucks.png new file mode 100644 index 000000000..15b758da9 Binary files /dev/null and b/public/img/logos/teamskeet/thisgirlsucks.png differ diff --git a/public/img/logos/teamskeet/tittyattack.png b/public/img/logos/teamskeet/tittyattack.png new file mode 100644 index 000000000..cf0bd17c9 Binary files /dev/null and b/public/img/logos/teamskeet/tittyattack.png differ diff --git a/seeds/00_networks.js b/seeds/00_networks.js index de2c2cd0f..32c85a446 100644 --- a/seeds/00_networks.js +++ b/seeds/00_networks.js @@ -120,6 +120,12 @@ const networks = [ url: 'https://www.realitykings.com', description: 'Home of HD reality porn featuring the nicest tits and ass online! The hottest curvy girls in real amateur sex stories are only on REALITYkings.com', }, + { + slug: 'teamskeet', + name: 'Team Skeet', + url: 'https://www.teamskeet.com', + description: 'Welcome to teamskeet.com, the largest collection of exclusive teen porn sites and videos on the web. Check out our TeamSkeet porn sites now.', + }, { slug: 'vixen', name: 'Vixen', diff --git a/seeds/01_sites.js b/seeds/01_sites.js index c3cb24473..b77852348 100644 --- a/seeds/01_sites.js +++ b/seeds/01_sites.js @@ -2480,6 +2480,230 @@ function getSites(networksMap) { slug: 'monstercurves', network_id: networksMap.realitykings, }, + { + slug: 'exxxtrasmall', + name: 'Exxxtra Small', + description: '', + url: 'https://www.exxxtrasmall.com', + parameters: JSON.stringify({ id: 'exs' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teenpies', + name: 'Teen Pies', + description: '', + url: 'https://www.teenpies.com', + parameters: JSON.stringify({ id: 'tp' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'innocenthigh', + name: 'Innocent High', + description: '', + url: 'https://www.innocenthigh.com', + parameters: JSON.stringify({ id: 'ih' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teencurves', + name: 'Teen Curves', + description: '', + url: 'https://www.teencurves.com', + parameters: JSON.stringify({ id: 'tc' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'cfnmteens', + name: 'CFNM Teens', + description: '', + url: 'https://www.cfnmteens.com', + parameters: JSON.stringify({ id: 'cfnm' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teensloveanal', + name: 'Teens Love Anal', + description: '', + url: 'https://www.teensloveanal.com', + parameters: JSON.stringify({ id: 'tla' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'mybabysittersclub', + name: 'My Babysitters Club', + description: '', + url: 'https://www.mybabysittersclub.com', + parameters: JSON.stringify({ id: 'bsc' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'shesnew', + name: 'She\'s New', + description: '', + url: 'https://www.shesnow.com', + parameters: JSON.stringify({ id: 'bsc' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teensdoporn', + name: 'Teens Do Porn', + description: '', + url: 'https://www.teensdoporn.com', + parameters: JSON.stringify({ id: 'tdp' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'povlife', + name: 'POV Life', + description: '', + url: 'https://www.povlife.com', + parameters: JSON.stringify({ id: 'pov' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'therealworkout', + name: 'The Real Workout', + description: '', + url: 'https://www.therealworkout.com', + parameters: JSON.stringify({ id: 'trw' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'thisgirlsucks', + name: 'This Girl Sucks', + description: '', + url: 'https://www.thisgirlsucks.com', + parameters: JSON.stringify({ id: 'tgs' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teenslovemoney', + name: 'Teens Love Money', + description: '', + url: 'https://www.teenslovemoney.com', + parameters: JSON.stringify({ id: 'tlm' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'oyeloca', + name: 'Oye Loca', + description: '', + url: 'https://www.oyeloca.com', + parameters: JSON.stringify({ id: 'ol' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'tittyattack', + name: 'Titty Attack', + description: '', + url: 'https://www.tittyattack.com', + parameters: JSON.stringify({ id: 'ta' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teenyblack', + name: 'Teeny Black', + description: '', + url: 'https://www.teenyblack.com', + parameters: JSON.stringify({ id: 'tb' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'lusthd', + name: 'Lust HD', + description: '', + url: 'https://www.lusthd.com', + parameters: JSON.stringify({ id: 'lhd' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'rubateen', + name: 'Rub A Teen', + description: '', + url: 'https://www.rubateen.com', + parameters: JSON.stringify({ id: 'rat' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'herfreshmanyear', + name: 'Her Freshman Year', + description: '', + url: 'https://www.exxxtrasmall.com', + parameters: JSON.stringify({ id: 'hfy' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'selfdesire', + name: 'Self Desire', + description: '', + url: 'https://www.selfdesire.com', + parameters: JSON.stringify({ id: 'sd' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'solointerviews', + name: 'Solo Interviews', + description: '', + url: 'https://www.solointerviews.com', + parameters: JSON.stringify({ id: 'si' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teamskeetextras', + name: 'Team Skeet Extras', + description: '', + url: 'https://www.teamskeetextras.com', + parameters: JSON.stringify({ id: 'tse' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'dyked', + name: 'Dyked', + description: '', + url: 'https://www.dyked.com', + parameters: JSON.stringify({ id: 'dyk' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'badmilfs', + name: 'Bad MILFs', + description: '', + url: 'https://www.badmilfs.com', + parameters: JSON.stringify({ id: 'bad' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'gingerpatch', + name: 'Ginger Patch', + description: '', + url: 'https://www.gingerpatch.com', + parameters: JSON.stringify({ id: 'gp' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'bracefaced', + name: 'Brace Faced', + description: '', + url: 'https://www.bracefaced.com', + parameters: JSON.stringify({ id: 'bfd' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'teenjoi', + name: 'Teen JOI', + description: '', + url: 'https://www.teenjoi.com', + parameters: JSON.stringify({ id: 'joi' }), + network_id: networksMap.teamskeet, + }, + { + slug: 'stepsiblings', + name: 'Step Siblings', + description: '', + url: 'https://www.stepsiblings.com', + parameters: JSON.stringify({ id: 'sss' }), + network_id: networksMap.teamskeet, + }, // VIXEN { slug: 'vixen', diff --git a/src/scrapers/jayrock.js b/src/scrapers/jayrock.js index d40c16c08..08f431126 100644 --- a/src/scrapers/jayrock.js +++ b/src/scrapers/jayrock.js @@ -4,6 +4,7 @@ const Promise = require('bluebird'); const bhttp = require('bhttp'); +const logger = require('../logger'); const slugify = require('../utils/slugify'); async function fetchToken(site) { @@ -30,12 +31,17 @@ async function fetchActors(entryId, site, { token, time }) { async function fetchTrailerLocation(entryId, site) { const url = `${site.url}/api/download/${entryId}/hd1080/stream`; - const res = await bhttp.get(url, { - followRedirects: false, - }); - if (res.statusCode === 302) { - return res.headers.location; + try { + const res = await bhttp.get(url, { + followRedirects: false, + }); + + if (res.statusCode === 302) { + return res.headers.location; + } + } catch (error) { + logger.warn(`${site.name}: Unable to fetch trailer at '${url}': ${error.message}`); } return null; @@ -72,11 +78,11 @@ function scrapeLatest(scenes, site, tokens) { return Promise.map(scenes, async scene => scrapeScene(scene, site, tokens), { concurrency: 10 }); } -async function fetchLatest(site) { +async function fetchLatest(site, page = 1) { const { time, token } = await fetchToken(site); // transParameters[v1] includes _resources, [v2] includes photos, [preset] is mandatory - const url = `${site.url}/sapi/${token}/${time}/content.load?limit=20&transitParameters[v1]=OhUOlmasXD&transitParameters[v2]=OhUOlmasXD&transitParameters[preset]=videos`; + const url = `${site.url}/sapi/${token}/${time}/content.load?limit=50&offset=${(page - 1) * 50}&transitParameters[v1]=OhUOlmasXD&transitParameters[v2]=OhUOlmasXD&transitParameters[preset]=videos`; const res = await bhttp.get(url); if (res.statusCode === 200 && res.body.status) { diff --git a/src/scrapers/scrapers.js b/src/scrapers/scrapers.js index ab3a225b6..e96bfe412 100644 --- a/src/scrapers/scrapers.js +++ b/src/scrapers/scrapers.js @@ -15,6 +15,7 @@ const pervcity = require('./pervcity'); const privateNetwork = require('./private'); // reserved keyword const naughtyamerica = require('./naughtyamerica'); const realitykings = require('./realitykings'); +const teamskeet = require('./teamskeet'); const vixen = require('./vixen'); // releases and profiles @@ -52,6 +53,7 @@ module.exports = { private: privateNetwork, naughtyamerica, realitykings, + teamskeet, vixen, xempire, }, diff --git a/src/scrapers/teamskeet.js b/src/scrapers/teamskeet.js new file mode 100644 index 000000000..cf5b54646 --- /dev/null +++ b/src/scrapers/teamskeet.js @@ -0,0 +1,105 @@ +'use strict'; + +const bhttp = require('bhttp'); +const { JSDOM } = require('jsdom'); +const moment = require('moment'); + +function extractTitle(pathname) { + return pathname + .split('/') + .slice(-2)[0] + .split('_') + .map(seg => `${seg.charAt(0).toUpperCase()}${seg.slice(1)}`) + .join(' '); +} + +function extractActors(str) { + return str + .split(/,|\band/) + .filter(actor => !/\.{3}/.test(actor)) + .map(actor => actor.trim()) + .filter(actor => actor.length > 0); +} + +function scrapeLatest(html, site) { + const { document } = new JSDOM(html).window; + + const scenes = Array.from(document.querySelectorAll('#updatesList li.grey, #updatesList li.white')); + + return scenes.map((scene) => { + const release = { site }; + + const link = scene.querySelector('.info a'); + const poster = scene.querySelector('img'); + const { pathname } = new URL(link); + + [release.entryId] = poster.id.match(/\d+/); + + release.url = `https://www.teamskeet.com${pathname}`; + release.title = extractTitle(pathname); + + release.date = moment.utc(scene.querySelector('strong').textContent, 'MM/DD/YYYY').toDate(); + + const photos = Array.from({ length: 5 }, (_value, index) => poster.dataset.original.replace(/\d+.jpg/, `${String(index + 1).padStart(2, '0')}.jpg`)); + [release.poster] = photos; + release.photos = photos.slice(1); + + const actors = scene.querySelector('div span[rel="test"]').textContent; + release.actors = extractActors(actors); + + return release; + }); +} + +function scrapeScene(html, site) { + const { document } = new JSDOM(html).window; + const release = { site }; + + release.entryId = document.querySelector('#story-and-tags .scene_rater').attributes.rel.value; + release.description = document.querySelector('#story-and-tags td:nth-child(2) div').textContent; + const [actors, title, channel] = document.querySelector('title').textContent.split('|').map(item => item.trim()); + + release.title = title; + release.actors = extractActors(actors); + release.channel = channel.toLowerCase(); + release.tags = Array.from(document.querySelectorAll('#story-and-tags tr:nth-child(2) a'), el => el.rel); + + const date = document.querySelector('h3 ~ div:nth-child(4), h3 ~ div div.gray:not(.scene_rater)').textContent.split(':')[1].trim(); + release.date = moment.utc(date, 'MMMM Do, YYYY').toDate(); + + const { poster } = document.querySelector('video'); + if (poster && !/gen/.test(poster)) release.poster = [poster.replace('low', 'hi'), poster]; + + const siteId = document.querySelector('#story-and-tags img').src.match(/\w+.jpg/)[0].replace('.jpg', ''); + const actorsSlug = document.querySelector('h3 a').href.split('/').slice(-2)[0]; + + release.photos = Array.from({ length: 5 }, (value, index) => `https://images.psmcdn.net/teamskeet/${siteId}/${actorsSlug}/shared/scenes/new/${String(index + 1).padStart(2, '0')}.jpg`); + + const trailer = document.querySelector('div.right.gray a').href; + if (trailer) release.trailer = { src: trailer }; + + return release; +} + +async function fetchLatest(site, page = 1) { + const url = `https://www.teamskeet.com/t1/updates/load?fltrs[site]=${site.parameters.id}&page=${page}&view=newest&fltrs[time]=ALL&order=DESC`; + const res = await bhttp.get(url); + + if (res.statusCode === 200) { + return scrapeLatest(res.body.toString(), site); + } + + return null; +} + +async function fetchScene(url, site) { + const session = bhttp.session(); // resolve redirects + const res = await session.get(url); + + return scrapeScene(res.body.toString(), site); +} + +module.exports = { + fetchLatest, + fetchScene, +}; diff --git a/src/tags.js b/src/tags.js index 2b3f31d33..ded8e20b2 100644 --- a/src/tags.js +++ b/src/tags.js @@ -1,5 +1,6 @@ 'use strict'; +const logger = require('./logger'); const knex = require('./knex'); const whereOr = require('./utils/where-or'); @@ -58,7 +59,7 @@ async function matchTags(rawTags) { async function associateTags(release, releaseId) { if (!release.tags || release.tags.length === 0) { - console.warn(`No tags available for (${release.site.name}, ${releaseId}) "${release.title}"`); + logger.info(`No tags available for (${release.site.name}, ${releaseId}) "${release.title}"`); return; }