'use strict'; const bhttp = require('bhttp'); const slugify = require('../utils/slugify'); const clusterId = '617fb597b659459bafe6472470d9073a'; const authKey = 'YmFuZy1yZWFkOktqVDN0RzJacmQ1TFNRazI='; const genderMap = { M: 'male', F: 'female', }; function getScreenUrl(item, scene) { return `https://i.bang.com/screenshots/${scene.dvd.id}/movie/${scene.order}/${item.screenId}.jpg`; } function encodeId(id) { return Buffer .from(id, 'hex') .toString('base64') .replace(/\+/g, '-') .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, 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())); release.actors = scene.actors.map(actor => ({ name: actor.name, gender: genderMap[actor.gender] })); 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 = getScreenUrl(poster, scene); release.photos = photos.map(photo => getScreenUrl(photo, scene)); 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) { return scenes.map(({ _source: scene }) => scrapeScene(scene, site)); } async function fetchLatest(site, page = 1) { const res = await bhttp.post(`https://${clusterId}.us-east-1.aws.found.io/videos/video/_search`, { size: 50, from: (page - 1) * 50, query: { bool: { must: [ { match: { status: 'ok', }, }, { range: { releaseDate: { lte: 'now', }, }, }, /* * global fetch { nested: { path: 'studio', query: { bool: { must: [ { match: { 'studio.name': { operator: 'AND', query: 'bang! originals', }, }, }, ], }, }, }, }, */ { nested: { path: 'series', query: { bool: { must: [ { match: { 'series.id': { operator: 'AND', query: site.parameters.siteId, }, }, }, ], }, }, }, }, ], must_not: [ { match: { type: 'trailer', }, }, ], }, }, sort: [ { releaseDate: { order: 'desc', }, }, ], }, { encodeJSON: true, headers: { Authorization: `Basic ${authKey}`, }, }); 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 = { fetchLatest, fetchScene, };