diff --git a/public/img/logos/adulttime/bubblegumdungeon.png b/public/img/logos/adulttime/bubblegumdungeon.png
new file mode 100644
index 00000000..465192f1
Binary files /dev/null and b/public/img/logos/adulttime/bubblegumdungeon.png differ
diff --git a/public/img/logos/adulttime/favicon.png b/public/img/logos/adulttime/favicon.png
new file mode 100644
index 00000000..6a63f86e
Binary files /dev/null and b/public/img/logos/adulttime/favicon.png differ
diff --git a/public/img/logos/adulttime/girlsway.png b/public/img/logos/adulttime/girlsway.png
new file mode 100644
index 00000000..a7e668f9
Binary files /dev/null and b/public/img/logos/adulttime/girlsway.png differ
diff --git a/public/img/logos/adulttime/ladygonzo.png b/public/img/logos/adulttime/ladygonzo.png
new file mode 100644
index 00000000..95dc04a0
Binary files /dev/null and b/public/img/logos/adulttime/ladygonzo.png differ
diff --git a/public/img/logos/adulttime/misc/adult-time.png b/public/img/logos/adulttime/misc/adult-time.png
new file mode 100644
index 00000000..2d489e8b
Binary files /dev/null and b/public/img/logos/adulttime/misc/adult-time.png differ
diff --git a/public/img/logos/adulttime/misc/adult-time.svg b/public/img/logos/adulttime/misc/adult-time.svg
new file mode 100644
index 00000000..0baf7ada
--- /dev/null
+++ b/public/img/logos/adulttime/misc/adult-time.svg
@@ -0,0 +1,170 @@
+
+
diff --git a/public/img/logos/adulttime/misc/girls-way.png b/public/img/logos/adulttime/misc/girls-way.png
new file mode 100644
index 00000000..5744e175
Binary files /dev/null and b/public/img/logos/adulttime/misc/girls-way.png differ
diff --git a/public/img/logos/adulttime/misc/girls-way.svg b/public/img/logos/adulttime/misc/girls-way.svg
new file mode 100644
index 00000000..6540c7d7
--- /dev/null
+++ b/public/img/logos/adulttime/misc/girls-way.svg
@@ -0,0 +1,113 @@
+
+
+
diff --git a/public/img/logos/adulttime/misc/lady-gonzo.png b/public/img/logos/adulttime/misc/lady-gonzo.png
new file mode 100644
index 00000000..0afa63ff
Binary files /dev/null and b/public/img/logos/adulttime/misc/lady-gonzo.png differ
diff --git a/public/img/logos/adulttime/misc/lady-gonzo.svg b/public/img/logos/adulttime/misc/lady-gonzo.svg
new file mode 100644
index 00000000..3247e477
--- /dev/null
+++ b/public/img/logos/adulttime/misc/lady-gonzo.svg
@@ -0,0 +1,478 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/public/img/logos/adulttime/network.png b/public/img/logos/adulttime/network.png
new file mode 100644
index 00000000..1dd909ec
Binary files /dev/null and b/public/img/logos/adulttime/network.png differ
diff --git a/public/img/logos/adulttime/underthebed.png b/public/img/logos/adulttime/underthebed.png
new file mode 100644
index 00000000..1a773f86
Binary files /dev/null and b/public/img/logos/adulttime/underthebed.png differ
diff --git a/seeds/00_networks.js b/seeds/00_networks.js
index ac7810bb..b9a12a9c 100644
--- a/seeds/00_networks.js
+++ b/seeds/00_networks.js
@@ -8,6 +8,12 @@ const networks = [
url: 'https://www.21sextury.com',
description: 'Watch all the latest scenes and porn video updates on 21Sextury.com, the best European porn site with the hottest pornstars from all over the world! Watch porn videos from the large network here.',
},
+ {
+ slug: 'adulttime',
+ name: 'Adult Time',
+ url: 'https://www.adulttime.com',
+ description: 'Adult Time is a premium streaming service for adults! Watch adult movies, series, and channels from the top names in the industry.',
+ },
{
slug: 'babes',
name: 'Babes',
diff --git a/seeds/01_sites.js b/seeds/01_sites.js
index 027d2955..259d437e 100644
--- a/seeds/01_sites.js
+++ b/seeds/01_sites.js
@@ -119,6 +119,45 @@ const sites = [
name: 'Sweet Sophie Moone',
network: '21sextury',
},
+ // ADULT TIME
+ {
+ name: 'Bubblegum Dungeon',
+ slug: 'bubblegumdungeon',
+ url: 'https://www.bubblegumdungeon.com',
+ network: 'adulttime',
+ parameters: {
+ referer: 'https://freetour.bubblegumdungeon.com/en/join',
+ deep: false,
+ },
+ },
+ {
+ name: 'Lady Gonzo',
+ slug: 'ladygonzo',
+ url: 'https://www.ladygonzo.com',
+ description: 'LadyGonzo.com is a new Adult Time porn series featuring Joanna Angel shooting hardcore sex and gonzo porn movies the way she\'d like to see it!',
+ network: 'adulttime',
+ },
+ {
+ name: 'Girlsway',
+ slug: 'girlsway',
+ url: 'https://www.girlsway.com',
+ 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!',
+ network: 'adulttime',
+ parameters: {
+ scene: 'https://www.girlsway.com/en/video/girlsway',
+ },
+ },
+ {
+ name: 'Under The Bed',
+ slug: 'underthebed',
+ url: 'https://www.underthebed.com',
+ description: '',
+ network: 'adulttime',
+ parameters: {
+ referer: 'https://freetour.underthebed.com/en/join',
+ deep: false,
+ },
+ },
// BABES
{
name: 'Babes',
diff --git a/seeds/03_tags.js b/seeds/03_tags.js
index c11dc8d2..dd1c71ae 100644
--- a/seeds/03_tags.js
+++ b/seeds/03_tags.js
@@ -1632,6 +1632,7 @@ function getSiteTags() {
familyhookups: ['family'],
familystrokes: ['family'],
girlgrind: ['lesbian'],
+ girlsway: ['lesbian'],
givemepink: ['solo', 'masturbation'],
godsofmen: ['gay'],
iconmale: ['gay'],
diff --git a/src/logger.js b/src/logger.js
index 6d082a8e..a144b2f8 100644
--- a/src/logger.js
+++ b/src/logger.js
@@ -5,27 +5,30 @@ const winston = require('winston');
const args = require('./argv');
require('winston-daily-rotate-file');
-const logger = winston.createLogger({
- format: winston.format.combine(
- winston.format.timestamp(),
- winston.format.printf(info => `${info.timestamp} ${info.level}: ${util.inspect(info.message)}`),
- ),
- transports: [
- new winston.transports.Console({
- level: args.level,
- format: winston.format.combine(
- winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
- winston.format.colorize(),
- winston.format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`),
- ),
- timestamp: true,
- }),
- new winston.transports.DailyRotateFile({
- datePattern: 'YYYY-MM-DD',
- filename: 'log/%DATE%.log',
- level: 'silly',
- }),
- ],
-});
+function logger(filename) {
+ return winston.createLogger({
+ format: winston.format.combine(
+ winston.format.timestamp(),
+ winston.format.printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${util.inspect(info.message)}`),
+ ),
+ transports: [
+ new winston.transports.Console({
+ level: args.level,
+ format: winston.format.combine(
+ winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
+ winston.format.colorize(),
+ // winston.format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`),
+ winston.format.printf(info => `${info.timestamp} ${info.level} [${filename}]: ${util.inspect(info.message)}`),
+ ),
+ timestamp: true,
+ }),
+ new winston.transports.DailyRotateFile({
+ datePattern: 'YYYY-MM-DD',
+ filename: 'log/%DATE%.log',
+ level: 'silly',
+ }),
+ ],
+ });
+}
module.exports = logger;
diff --git a/src/media.js b/src/media.js
index d422e890..b9a201ea 100644
--- a/src/media.js
+++ b/src/media.js
@@ -9,7 +9,7 @@ const mime = require('mime');
const sharp = require('sharp');
const blake2 = require('blake2');
-const logger = require('./logger');
+const logger = require('./logger')(__filename);
const knex = require('./knex');
const upsert = require('./utils/upsert');
const { ex } = require('./utils/q');
diff --git a/src/releases.js b/src/releases.js
index 8f2c1b22..54f5a6bb 100644
--- a/src/releases.js
+++ b/src/releases.js
@@ -358,7 +358,7 @@ async function storeReleaseAssets(releases) {
role: 'teaser',
}, identifier);
} catch (error) {
- logger.error(error.message);
+ logger.error({ label: 'media', message: error.message });
}
}, {
concurrency: 10,
@@ -422,7 +422,7 @@ async function storeReleases(releases) {
...releaseWithChannelSite,
};
} catch (error) {
- logger.error(error.message);
+ logger.error({ label: 'media', message: error.message });
return null;
}
diff --git a/src/scrapers/adulttime.js b/src/scrapers/adulttime.js
new file mode 100644
index 00000000..d6a1cfa1
--- /dev/null
+++ b/src/scrapers/adulttime.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const { fetchApiLatest, fetchApiUpcoming, fetchScene, fetchApiProfile } = require('./gamma');
+
+function curateRelease(release, site) {
+ if (['bubblegumdungeon', 'ladygonzo'].includes(site.slug)) {
+ return {
+ ...release,
+ title: release.title.split(/:|\|/)[1].trim(),
+ };
+ }
+
+ return release;
+}
+
+async function networkFetchScene(url, site) {
+ const scene = await fetchScene(url, site);
+
+ return curateRelease(scene, site);
+}
+
+async function fetchLatest(site, page = 1) {
+ const releases = await fetchApiLatest(site, page, false);
+
+ console.log(releases);
+
+ return releases.map(release => curateRelease(release, site));
+}
+
+async function fetchUpcoming(site, page = 1) {
+ const releases = await fetchApiUpcoming(site, page, false);
+
+ return releases.map(release => curateRelease(release, site));
+}
+
+module.exports = {
+ fetchLatest,
+ fetchProfile: fetchApiProfile,
+ fetchScene: networkFetchScene,
+ fetchUpcoming,
+};
diff --git a/src/scrapers/gamma.js b/src/scrapers/gamma.js
index e5c433b2..5137ada4 100644
--- a/src/scrapers/gamma.js
+++ b/src/scrapers/gamma.js
@@ -7,6 +7,7 @@ const cheerio = require('cheerio');
const moment = require('moment');
const argv = require('../argv');
+const logger = require('../logger');
const { ex, get } = require('../utils/q');
const slugify = require('../utils/slugify');
@@ -71,7 +72,7 @@ async function getPhotos(albumPath, site) {
return photos;
} catch (error) {
- console.error(`Failed to fetch ${site.name} photos from ${albumUrl}: ${error.message}`);
+ logger.warn(`Failed to fetch ${site.name} photos from ${albumUrl}: ${error.message}`);
return [];
}
@@ -88,11 +89,16 @@ async function scrapeApiReleases(json, site) {
dislikes: scene.ratings_down,
};
- release.url = `${site.url}/en/video/${scene.url_title}/${release.entryId}`;
+ release.url = site.parameters?.scene
+ ? `${site.parameters.scene}/${scene.url_title}/${release.entryId}`
+ : `${site.url}/en/video/${scene.url_title}/${release.entryId}`;
+
release.date = moment.utc(scene.release_date, 'YYYY-MM-DD').toDate();
release.actors = scene.actors.map(({ name }) => name);
release.director = scene.directors[0].name;
+ console.log(release.url);
+
release.tags = scene.master_categories.concat(scene.categories?.map(category => category.name));
const posterPath = scene.pictures.resized || (scene.pictures.nsfw?.top && Object.values(scene.pictures.nsfw.top)[0]);
@@ -159,7 +165,7 @@ function scrapeAll(html, site, networkUrl, hasTeaser = true) {
async function scrapeScene(html, url, site) {
const $ = cheerio.load(html, { normalizeWhitespace: true });
- const release = { $ };
+ const release = { $, url };
const json = $('script[type="application/ld+json"]').html();
const videoJson = $('script:contains("window.ScenePlayerOptions")').html();
@@ -325,20 +331,7 @@ function scrapeApiProfile(data, releases, siteSlug) {
return profile;
}
-async function fetchApiCredentials(referer) {
- const res = await bhttp.get(referer);
- const body = res.body.toString();
-
- const apiLine = body.split('\n').find(bodyLine => bodyLine.match('apiKey'));
-
- if (!apiLine) {
- throw new Error(`Can not use Gamma API for ${referer}`);
- }
-
- const apiSerial = apiLine.slice(apiLine.indexOf('{'), apiLine.indexOf('};') + 1);
- const apiData = JSON.parse(apiSerial);
-
- const { applicationID: appId, apiKey } = apiData.api.algolia;
+function getApiUrl(appId, apiKey) {
const userAgent = 'Algolia for vanilla JavaScript (lite) 3.27.0;instantsearch.js 2.7.4;JS Helper 2.26.0';
const apiUrl = `https://${appId.toLowerCase()}-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=${userAgent}&x-algolia-application-id=${appId}&x-algolia-api-key=${apiKey}`;
@@ -351,9 +344,31 @@ async function fetchApiCredentials(referer) {
};
}
+async function fetchApiCredentials(referer, site) {
+ if (site.parameters?.appId && site.parameters?.apiKey) {
+ return getApiUrl(site.parameters.appId, site.parameters.apiKey);
+ }
+
+ const res = await bhttp.get(referer);
+ const body = res.body.toString();
+
+ const apiLine = body.split('\n').find(bodyLine => bodyLine.match('apiKey'));
+
+ if (!apiLine) {
+ throw new Error(`No Gamma API key found for ${referer}`);
+ }
+
+ const apiSerial = apiLine.slice(apiLine.indexOf('{'), apiLine.indexOf('};') + 1);
+ const apiData = JSON.parse(apiSerial);
+
+ const { applicationID: appId, apiKey } = apiData.api.algolia;
+
+ return getApiUrl(appId, apiKey);
+}
+
async function fetchApiLatest(site, page = 1, upcoming = false) {
- const referer = `${site.parameters?.networkReferer ? site.network.url : site.url}/en/videos`;
- const { apiUrl } = await fetchApiCredentials(referer);
+ const referer = site.parameters?.referer || `${site.parameters?.networkReferer ? site.network.url : site.url}/en/videos`;
+ const { apiUrl } = await fetchApiCredentials(referer, site);
const res = await bhttp.post(apiUrl, {
requests: [
@@ -394,7 +409,11 @@ async function fetchUpcoming(site) {
return scrapeAll(res.body.toString(), site);
}
-async function fetchScene(url, site) {
+async function fetchScene(url, site, release) {
+ if (site.parameters?.deep === false) {
+ return release;
+ }
+
const res = await bhttp.get(url);
return scrapeScene(res.body.toString(), url, site);
diff --git a/src/scrapers/scrapers.js b/src/scrapers/scrapers.js
index 4cfd91fc..4db485cf 100644
--- a/src/scrapers/scrapers.js
+++ b/src/scrapers/scrapers.js
@@ -1,6 +1,7 @@
'use strict';
// releases
+const adulttime = require('./adulttime');
const babes = require('./babes');
const bang = require('./bang');
const dogfart = require('./dogfart');
@@ -51,6 +52,7 @@ const pornhub = require('./pornhub');
module.exports = {
releases: {
+ adulttime,
'21sextury': twentyonesextury,
babes,
bang,
diff --git a/src/tags.js b/src/tags.js
index 4d397b5b..494b0eb1 100644
--- a/src/tags.js
+++ b/src/tags.js
@@ -1,6 +1,6 @@
'use strict';
-const logger = require('./logger');
+const logger = require('./logger')(__filename);
const knex = require('./knex');
const whereOr = require('./utils/where-or');
diff --git a/src/utils/upsert.js b/src/utils/upsert.js
index eca86605..50c4f6e5 100644
--- a/src/utils/upsert.js
+++ b/src/utils/upsert.js
@@ -1,7 +1,7 @@
'use strict';
const knex = require('../knex');
-const logger = require('../logger');
+const logger = require('./logger')(__filename);
async function upsert(table, items, identifier = ['id'], _knex) {
const identifiers = Array.isArray(identifier) ? identifier : [identifier];