diff --git a/assets/components/actor/actor.vue b/assets/components/actor/actor.vue index 58104695..09f3eaa2 100644 --- a/assets/components/actor/actor.vue +++ b/assets/components/actor/actor.vue @@ -1,5 +1,126 @@ + + + + diff --git a/assets/components/errors/404.vue b/assets/components/errors/404.vue new file mode 100644 index 00000000..f81d5889 --- /dev/null +++ b/assets/components/errors/404.vue @@ -0,0 +1,34 @@ + + + diff --git a/assets/components/network/network.vue b/assets/components/network/network.vue new file mode 100644 index 00000000..3dd956f0 --- /dev/null +++ b/assets/components/network/network.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/assets/components/site/site.vue b/assets/components/site/site.vue new file mode 100644 index 00000000..d19c88af --- /dev/null +++ b/assets/components/site/site.vue @@ -0,0 +1,5 @@ + diff --git a/assets/components/tile/release.vue b/assets/components/tile/release.vue new file mode 100644 index 00000000..3a82cc33 --- /dev/null +++ b/assets/components/tile/release.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/assets/components/tile/site.vue b/assets/components/tile/site.vue new file mode 100644 index 00000000..6d19f7a8 --- /dev/null +++ b/assets/components/tile/site.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/assets/img/link.svg b/assets/img/link.svg new file mode 100644 index 00000000..b66881ec --- /dev/null +++ b/assets/img/link.svg @@ -0,0 +1,6 @@ + + +link + + + diff --git a/assets/img/new-tab.svg b/assets/img/new-tab.svg new file mode 100644 index 00000000..7207dc1a --- /dev/null +++ b/assets/img/new-tab.svg @@ -0,0 +1,6 @@ + + +new-tab + + + diff --git a/assets/img/new-tab2.svg b/assets/img/new-tab2.svg new file mode 100644 index 00000000..48e13875 --- /dev/null +++ b/assets/img/new-tab2.svg @@ -0,0 +1,6 @@ + + +new-tab2 + + + diff --git a/assets/img/share2.svg b/assets/img/share2.svg new file mode 100644 index 00000000..61f5e339 --- /dev/null +++ b/assets/img/share2.svg @@ -0,0 +1,5 @@ + + +share2 + + diff --git a/assets/js/actors/actions.js b/assets/js/actors/actions.js new file mode 100644 index 00000000..86d2d66a --- /dev/null +++ b/assets/js/actors/actions.js @@ -0,0 +1,22 @@ +import { get } from '../api'; + +function initActorActions(_store, _router) { + async function fetchActors({ _commit }, actorId) { + const networks = await get(`/actors/${actorId || ''}`); + + return networks; + } + + async function fetchActorReleases({ _commit }, actorId) { + const releases = await get(`/actors/${actorId}/releases`); + + return releases; + } + + return { + fetchActors, + fetchActorReleases, + }; +} + +export default initActorActions; diff --git a/assets/js/actors/actors.js b/assets/js/actors/actors.js new file mode 100644 index 00000000..59be7fdf --- /dev/null +++ b/assets/js/actors/actors.js @@ -0,0 +1,13 @@ +import state from './state'; +import mutations from './mutations'; +import actions from './actions'; + +function initActorsStore(store, router) { + return { + state, + mutations, + actions: actions(store, router), + }; +} + +export default initActorsStore; diff --git a/assets/js/actors/mutations.js b/assets/js/actors/mutations.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/assets/js/actors/mutations.js @@ -0,0 +1 @@ +export default {}; diff --git a/assets/js/actors/state.js b/assets/js/actors/state.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/assets/js/actors/state.js @@ -0,0 +1 @@ +export default {}; diff --git a/assets/js/networks/actions.js b/assets/js/networks/actions.js new file mode 100644 index 00000000..e0e59583 --- /dev/null +++ b/assets/js/networks/actions.js @@ -0,0 +1,22 @@ +import { get } from '../api'; + +function initNetworksActions(_store, _router) { + async function fetchNetworks({ _commit }, networkId) { + const networks = await get(`/networks/${networkId || ''}`); + + return networks; + } + + async function fetchNetworkReleases({ _commit }, networkId) { + const releases = await get(`/networks/${networkId}/releases`); + + return releases; + } + + return { + fetchNetworks, + fetchNetworkReleases, + }; +} + +export default initNetworksActions; diff --git a/assets/js/networks/mutations.js b/assets/js/networks/mutations.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/assets/js/networks/mutations.js @@ -0,0 +1 @@ +export default {}; diff --git a/assets/js/networks/networks.js b/assets/js/networks/networks.js new file mode 100644 index 00000000..44aeaa6c --- /dev/null +++ b/assets/js/networks/networks.js @@ -0,0 +1,13 @@ +import state from './state'; +import mutations from './mutations'; +import actions from './actions'; + +function initNetworksStore(store, router) { + return { + state, + mutations, + actions: actions(store, router), + }; +} + +export default initNetworksStore; diff --git a/assets/js/networks/state.js b/assets/js/networks/state.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/assets/js/networks/state.js @@ -0,0 +1 @@ +export default {}; diff --git a/assets/js/store.js b/assets/js/store.js index 755a9856..1168131c 100644 --- a/assets/js/store.js +++ b/assets/js/store.js @@ -4,6 +4,7 @@ import Vuex from 'vuex'; import initAuthStore from './auth/auth'; import initReleasesStore from './releases/releases'; import initNetworksStore from './networks/networks'; +import initActorsStore from './actors/actors'; function initStore(router) { Vue.use(Vuex); @@ -12,6 +13,7 @@ function initStore(router) { store.registerModule('auth', initAuthStore(store, router)); store.registerModule('releases', initReleasesStore(store, router)); + store.registerModule('actors', initActorsStore(store, router)); store.registerModule('networks', initNetworksStore(store, router)); return store; diff --git a/migrations/20190325001339_releases.js b/migrations/20190325001339_releases.js index 3b72e9cb..e3007db3 100644 --- a/migrations/20190325001339_releases.js +++ b/migrations/20190325001339_releases.js @@ -5,7 +5,16 @@ exports.up = knex => Promise.resolve() table.string('name') .unique() .notNullable(); + table.string('gender', 18); + table.text('description'); + table.date('birthdate'); + table.string('ethnicity'); + table.string('country_alpha2', 2); + table.string('city'); + table.integer('height'); + table.string('boobs_size'); + table.boolean('boobs_natural'); table.integer('alias_for', 12) .references('id') diff --git a/public/css/style.css b/public/css/style.css index 30d3c2fe..d81ac30e 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -15,7 +15,7 @@ } .thumbnail[data-v-3abcf101] { width: 100%; - height: 200px; + height: 12rem; display: flex; justify-content: center; align-items: center; @@ -227,14 +227,40 @@ } /* $primary: #ff886c; */ -.network[data-v-757c14c2] { +.tile[data-v-f4958086] { display: flex; + flex-direction: column; + align-items: center; + box-sizing: border-box; padding: 1rem; - overflow: hidden; + border-radius: .25rem; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.25); + height: 100%; + text-align: center; } +.link[data-v-f4958086] { + text-decoration: none; +} +.logo[data-v-f4958086] { + width: 100%; + height: 4rem; + -o-object-fit: contain; + object-fit: contain; +} +.title[data-v-f4958086] { + color: #222; + height: 100%; + display: flex; + align-items: center; + margin: 0; + font-size: 1rem; +} + +/* $primary: #ff886c; */ .header[data-v-757c14c2] { display: flex; justify-content: space-between; + padding: 1rem; } .title[data-v-757c14c2] { display: inline-block; @@ -242,15 +268,53 @@ } .heading[data-v-757c14c2] { padding: 0; - margin: 1rem 0; + margin: 0 0 1rem 0; } .logo[data-v-757c14c2] { height: 3rem; } +.sites[data-v-757c14c2], .scenes[data-v-757c14c2] { display: grid; - grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); grid-gap: 1rem; + margin: 0 0 1rem 0; +} +.scenes[data-v-757c14c2] { + grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); +} +.sites[data-v-757c14c2] { + grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); +} + +/* $primary: #ff886c; */ +.header[data-v-677a8360] { + display: flex; + justify-content: space-between; + padding: 1rem; +} +.title[data-v-677a8360] { + display: inline-block; + margin: 0 .5rem 0 0; +} +.heading[data-v-677a8360] { + padding: 0; + margin: 0 0 1rem 0; +} +.bio-heading[data-v-677a8360] { + display: inline-block; + font-weight: bold; + margin: .5rem 0 0 0; +} +.bio-heading[data-v-677a8360]::after { + content: ':'; +} +.scenes[data-v-677a8360] { + display: grid; + grid-gap: 1rem; + margin: 0 0 1rem 0; +} +.scenes[data-v-677a8360] { + grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); } /* $primary: #ff886c; */ diff --git a/public/img/404.png b/public/img/404.png new file mode 100644 index 00000000..94e46937 Binary files /dev/null and b/public/img/404.png differ diff --git a/public/img/networks/legalporno.png b/public/img/networks/legalporno.png new file mode 100644 index 00000000..590a754e Binary files /dev/null and b/public/img/networks/legalporno.png differ diff --git a/public/img/networks/vixen.png b/public/img/networks/vixen.png new file mode 100644 index 00000000..6529fb48 Binary files /dev/null and b/public/img/networks/vixen.png differ diff --git a/public/img/sites/allanal.png b/public/img/sites/allanal.png new file mode 100644 index 00000000..0b3c6e29 Binary files /dev/null and b/public/img/sites/allanal.png differ diff --git a/public/img/sites/blacked.png b/public/img/sites/blacked.png new file mode 100644 index 00000000..c74a8ea1 Binary files /dev/null and b/public/img/sites/blacked.png differ diff --git a/public/img/sites/blackedraw.png b/public/img/sites/blackedraw.png new file mode 100644 index 00000000..e8391e43 Binary files /dev/null and b/public/img/sites/blackedraw.png differ diff --git a/public/img/sites/deeper.png b/public/img/sites/deeper.png new file mode 100644 index 00000000..e29341ff Binary files /dev/null and b/public/img/sites/deeper.png differ diff --git a/public/img/sites/legalporno.png b/public/img/sites/legalporno.png new file mode 100644 index 00000000..590a754e Binary files /dev/null and b/public/img/sites/legalporno.png differ diff --git a/public/img/sites/nympho.png b/public/img/sites/nympho.png new file mode 100644 index 00000000..bdadaf87 Binary files /dev/null and b/public/img/sites/nympho.png differ diff --git a/public/img/sites/swallowed.png b/public/img/sites/swallowed.png new file mode 100644 index 00000000..809d8176 Binary files /dev/null and b/public/img/sites/swallowed.png differ diff --git a/public/img/sites/trueanal.png b/public/img/sites/trueanal.png new file mode 100644 index 00000000..378c316a Binary files /dev/null and b/public/img/sites/trueanal.png differ diff --git a/public/img/sites/tushy.png b/public/img/sites/tushy.png new file mode 100644 index 00000000..6f97d828 Binary files /dev/null and b/public/img/sites/tushy.png differ diff --git a/public/img/sites/tushyraw.png b/public/img/sites/tushyraw.png new file mode 100644 index 00000000..6650b52d Binary files /dev/null and b/public/img/sites/tushyraw.png differ diff --git a/public/img/sites/vixen.png b/public/img/sites/vixen.png new file mode 100644 index 00000000..8db569bd Binary files /dev/null and b/public/img/sites/vixen.png differ diff --git a/src/actors.js b/src/actors.js new file mode 100644 index 00000000..45d47ff6 --- /dev/null +++ b/src/actors.js @@ -0,0 +1,40 @@ +'use strict'; + +const knex = require('./knex'); + +async function curateActor(actor) { + const aliases = await knex('actors') + .where({ alias_for: actor.id }); + + return { + id: actor.id, + name: actor.name, + description: actor.description, + birthdate: actor.birthdate && new Date(actor.birthdate), + country: actor.country_alpha2, + city: actor.city, + ethnicity: actor.ethnicity, + height: actor.height, + boobSize: actor.boobs_size, + boobsNatural: actor.boobs_natural, + aliases: aliases.map(({ name }) => name), + slug: actor.slug, + }; +} + +function curateActors(releases) { + return Promise.all(releases.map(async release => curateActor(release))); +} + +async function fetchActors(actorId, actorSlug) { + const releases = await knex('actors') + .where({ id: actorId }) + .orWhere({ slug: actorSlug }) + .limit(100); + + return curateActors(releases); +} + +module.exports = { + fetchActors, +}; diff --git a/src/networks.js b/src/networks.js new file mode 100644 index 00000000..2a281faf --- /dev/null +++ b/src/networks.js @@ -0,0 +1,63 @@ +'use strict'; + +const knex = require('./knex'); + +async function curateNetwork(network) { + const [sites, studios] = await Promise.all([ + knex('sites') + .where({ network_id: network.id }), + knex('studios') + .where({ network_id: network.id }), + ]); + + return { + id: network.id, + name: network.name, + url: network.url, + description: network.description, + slug: network.slug, + sites: sites.map(site => ({ + id: site.id, + name: site.name, + url: site.url, + description: site.description, + slug: site.slug, + })), + studios: studios.map(studio => ({ + id: studio.id, + name: studio.name, + url: studio.url, + description: studio.description, + slug: studio.slug, + })), + }; +} + +function curateNetworks(releases) { + return Promise.all(releases.map(async release => curateNetwork(release))); +} + +async function fetchNetworks(networkId, networkSlug) { + const releases = await knex('networks') + .where({ id: networkId }) + .orWhere({ slug: networkSlug }) + .limit(100); + + return curateNetworks(releases); +} + +async function fetchNetworksFromReleases() { + const releases = await knex('releases') + .select('site_id', '') + .leftJoin('sites', 'sites.id', 'releases.site_id') + .leftJoin('networks', 'networks.id', 'sites.network_id') + .groupBy('networks.id') + .limit(100); + + return curateNetworks(releases); +} + +module.exports = { + fetchNetworks, + fetchNetworksFromReleases, +}; diff --git a/src/releases.js b/src/releases.js index 4996fb1e..2392643f 100644 --- a/src/releases.js +++ b/src/releases.js @@ -69,7 +69,8 @@ async function fetchReleases(releaseId) { const releases = await knex('releases') .where(releaseId ? { 'releases.id': releaseId } : {}) .select( - 'releases.*', 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', + 'releases.*', + 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', 'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url', 'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url', ) @@ -87,7 +88,8 @@ async function fetchSiteReleases(siteId, siteSlug) { .where({ 'sites.id': siteId }) .orWhere({ 'sites.slug': siteSlug }) .select( - 'releases.*', 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', + 'releases.*', + 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', 'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url', 'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url', ) @@ -105,7 +107,8 @@ async function fetchNetworkReleases(networkId, networkSlug) { .where({ 'networks.id': networkId }) .orWhere({ 'networks.slug': networkSlug }) .select( - 'releases.*', 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', + 'releases.*', + 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', 'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url', 'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url', ) @@ -118,8 +121,31 @@ async function fetchNetworkReleases(networkId, networkSlug) { return curateReleases(releases); } +async function fetchActorReleases(actorId, actorSlug) { + const releases = await knex('actors_associated') + .where({ 'actors.id': actorId }) + .orWhere({ 'actors.slug': actorSlug }) + .select( + 'releases.*', + 'actors.name as actor_name', + 'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', + 'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url', + 'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url', + ) + .leftJoin('releases', 'actors_associated.release_id', 'releases.id') + .leftJoin('actors', 'actors_associated.actor_id', 'actors.id') + .leftJoin('sites', 'releases.site_id', 'sites.id') + .leftJoin('studios', 'releases.studio_id', 'studios.id') + .leftJoin('networks', 'sites.network_id', 'networks.id') + .orderBy([{ column: 'releases.date', order: 'desc' }, { column: 'releases.created_at', order: 'desc' }]) + .limit(100); + + return curateReleases(releases); +} + module.exports = { fetchReleases, + fetchActorReleases, fetchSiteReleases, fetchNetworkReleases, }; diff --git a/src/sites.js b/src/sites.js new file mode 100644 index 00000000..37d339d1 --- /dev/null +++ b/src/sites.js @@ -0,0 +1,50 @@ +'use strict'; + +const knex = require('./knex'); + +async function curateSite(site) { + const network = await knex('network').where({ id: site.network_id }); + + return { + id: site.id, + name: site.name, + url: site.url, + description: site.description, + slug: site.slug, + network: { + id: network.id, + name: network.name, + url: network.url, + description: network.description, + slug: network.slug, + }, + }; +} + +function curateSites(releases) { + return Promise.all(releases.map(async site => curateSite(site))); +} + +async function fetchSites(siteId, siteSlug) { + const releases = await knex('sites') + .where({ id: siteId }) + .orWhere({ slug: siteSlug }) + .limit(100); + + return curateSites(releases); +} + +async function fetchSitesFromReleases() { + const releases = await knex('releases') + .select('site_id', '') + .leftJoin('sites', 'sites.id', 'releases.site_id') + .groupBy('sites.id') + .limit(100); + + return curateSites(releases); +} + +module.exports = { + fetchSites, + fetchSitesFromReleases, +}; diff --git a/src/web/actors.js b/src/web/actors.js new file mode 100644 index 00000000..81f32dac --- /dev/null +++ b/src/web/actors.js @@ -0,0 +1,16 @@ +'use strict'; + +const { fetchActors } = require('../actors'); + +async function fetchActorsApi(req, res) { + const actorId = typeof req.params.actorId === 'number' ? req.params.actorId : null; + const actorSlug = typeof req.params.actorId === 'string' ? req.params.actorId : null; + + const actors = await fetchActors(actorId, actorSlug); + + res.send(actors); +} + +module.exports = { + fetchActors: fetchActorsApi, +}; diff --git a/src/web/networks.js b/src/web/networks.js new file mode 100644 index 00000000..d77dac43 --- /dev/null +++ b/src/web/networks.js @@ -0,0 +1,23 @@ +'use strict'; + +const { fetchNetworks, fetchNetworksFromReleases } = require('../networks'); + +async function fetchNetworksApi(req, res) { + const networkId = typeof req.params.networkId === 'number' ? req.params.networkId : null; + const networkSlug = typeof req.params.networkId === 'string' ? req.params.networkId : null; + + const networks = await fetchNetworks(networkId, networkSlug); + + res.send(networks); +} + +async function fetchNetworksFromReleasesApi(req, res) { + const networks = await fetchNetworksFromReleases(); + + res.send(networks); +} + +module.exports = { + fetchNetworks: fetchNetworksApi, + fetchNetworksFromReleases: fetchNetworksFromReleasesApi, +}; diff --git a/src/web/releases.js b/src/web/releases.js index 9012d6e2..082a8137 100644 --- a/src/web/releases.js +++ b/src/web/releases.js @@ -1,6 +1,11 @@ 'use strict'; -const { fetchReleases, fetchNetworkReleases, fetchSiteReleases } = require('../releases'); +const { + fetchReleases, + fetchActorReleases, + fetchNetworkReleases, + fetchSiteReleases, +} = require('../releases'); async function fetchReleasesApi(req, res) { const releases = await fetchReleases(req.params.releaseId); @@ -8,6 +13,15 @@ async function fetchReleasesApi(req, res) { res.send(releases); } +async function fetchActorReleasesApi(req, res) { + const actorId = Number.isInteger(Number(req.params.actorId)) ? Number(req.params.actorId) : null; + const actorSlug = typeof req.params.actorId === 'string' ? req.params.actorId : null; + + const releases = await fetchActorReleases(actorId, actorSlug); + + res.send(releases); +} + async function fetchNetworkReleasesApi(req, res) { const networkId = typeof req.params.networkId === 'number' ? req.params.networkId : null; const networkSlug = typeof req.params.networkId === 'string' ? req.params.networkId : null; @@ -28,6 +42,7 @@ async function fetchSiteReleasesApi(req, res) { module.exports = { fetchReleases: fetchReleasesApi, + fetchActorReleases: fetchActorReleasesApi, fetchNetworkReleases: fetchNetworkReleasesApi, fetchSiteReleases: fetchSiteReleasesApi, }; diff --git a/src/web/server.js b/src/web/server.js index caba17b8..023e1e7a 100644 --- a/src/web/server.js +++ b/src/web/server.js @@ -6,8 +6,19 @@ const express = require('express'); const Router = require('express-promise-router'); const bodyParser = require('body-parser'); -const { fetchReleases, fetchNetworkReleases, fetchSiteReleases } = require('./releases'); -const { fetchNetworks, fetchNetworksFromReleases } = require('./networks'); +const { + fetchReleases, + fetchActorReleases, + fetchNetworkReleases, + fetchSiteReleases, +} = require('./releases'); + +const { + fetchNetworks, + fetchNetworksFromReleases, +} = require('./networks'); + +const { fetchActors } = require('./actors'); const { fetchSites } = require('./sites'); function initServer() { @@ -16,12 +27,21 @@ function initServer() { router.use('/media', express.static(config.photoPath)); router.use(express.static('public')); + + router.use('/img', (req, res) => { + res.status(404).send(); + }); + router.use(bodyParser.json({ strict: false })); router.get('/api/releases', fetchReleases); router.get('/api/releases/:releaseId', fetchReleases); router.get('/api/releases/networks', fetchNetworksFromReleases); + router.get('/api/actors', fetchActors); + router.get('/api/actors/:actorId', fetchActors); + router.get('/api/actors/:actorId/releases', fetchActorReleases); + router.get('/api/networks', fetchNetworks); router.get('/api/networks/:networkId', fetchNetworks); router.get('/api/networks/:networkId/releases', fetchNetworkReleases); diff --git a/src/web/sites.js b/src/web/sites.js new file mode 100644 index 00000000..433d7287 --- /dev/null +++ b/src/web/sites.js @@ -0,0 +1,23 @@ +'use strict'; + +const { fetchSites, fetchSitesFromReleases } = require('../networks'); + +async function fetchSitesApi(req, res) { + const siteId = typeof req.params.siteId === 'number' ? req.params.siteId : null; + const siteSlug = typeof req.params.siteId === 'string' ? req.params.siteId : null; + + const sites = await fetchSites(siteId, siteSlug); + + res.send(sites); +} + +async function fetchSitesFromReleasesApi(req, res) { + const sites = await fetchSitesFromReleases(); + + res.send(sites); +} + +module.exports = { + fetchSites: fetchSitesApi, + fetchSitesFromReleases: fetchSitesFromReleasesApi, +};