Generating thumbnails. Added site overview page.

This commit is contained in:
ThePendulum 2019-11-11 03:20:00 +01:00
parent 948597d265
commit 50816d7b28
28 changed files with 780 additions and 182 deletions

View File

@ -10,7 +10,7 @@
"no-console": 0, "no-console": 0,
"indent": ["error", 4], "indent": ["error", 4],
"max-len": [2, { "max-len": [2, {
"code": 200, "code": 300,
"tabWidth": 4, "tabWidth": 4,
"ignoreUrls": true "ignoreUrls": true
}], }],

View File

@ -77,6 +77,8 @@ import ReleaseTile from '../tile/release.vue';
async function mounted() { async function mounted() {
this.releases = await this.$store.dispatch('fetchReleases'); this.releases = await this.$store.dispatch('fetchReleases');
this.networks = await this.$store.dispatch('fetchNetworks');
this.pageTitle = ''; this.pageTitle = '';
} }
@ -91,6 +93,7 @@ export default {
showGay: false, showGay: false,
showTrans: false, showTrans: false,
releases: [], releases: [],
networks: [],
pageTitle: null, pageTitle: null,
}; };
}, },

View File

@ -125,6 +125,6 @@ export default {
} }
.sites { .sites {
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
} }
</style> </style>

View File

@ -8,7 +8,7 @@
<video <video
v-if="release.trailer" v-if="release.trailer"
:src="`/media/${release.trailer.path}`" :src="`/media/${release.trailer.path}`"
:poster="`/media/${(release.poster && release.poster.path) || (release.photos.length && release.photos[Math.floor(Math.random() * release.photos.length)].path)}`" :poster="`/media/${(release.poster && release.poster.thumbnail) || (release.photos.length && release.photos[Math.floor(Math.random() * release.photos.length)].path)}`"
:alt="release.title" :alt="release.title"
class="banner-item" class="banner-item"
controls controls
@ -23,7 +23,7 @@
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<img <img
:src="`/media/${photo.path}`" :src="`/media/${photo.thumbnail}`"
:alt="`Photo ${photo.index + 1}`" :alt="`Photo ${photo.index + 1}`"
class="banner-item" class="banner-item"
> >
@ -77,15 +77,11 @@
<a <a
:href="`/network/${release.network.slug}`" :href="`/network/${release.network.slug}`"
target="_blank"
rel="noopener noreferrer"
class="network-link" class="network-link"
>{{ release.network.name }}:</a> >{{ release.network.name }}:</a>
<a <a
:href="`/site/${release.site.slug}`" :href="`/site/${release.site.slug}`"
target="_blank"
rel="noopener noreferrer"
class="site-link" class="site-link"
>{{ release.site.name }}</a> >{{ release.site.name }}</a>
</span> </span>

View File

@ -1,5 +1,157 @@
<template> <template>
<div> <div
<h1>Site</h1> v-if="site"
class="content site"
>
<div class="header">
<span class="intro">
<h2 class="title">
{{ site.name }}
<a
v-if="site.url"
:href="site.url"
target="_blank"
rel="noopener noreferrer"
>
<Icon
icon="new-tab"
class="icon-href"
/>
</a>
</h2>
<span class="description">{{ site.description }}</span>
</span>
<span class="link">
<a
v-if="site.url"
:href="site.url"
target="_blank"
rel="noopener noreferrer"
class="logo-link"
>
<object
:data="`/img/logos/${site.network.slug}/${site.slug}.png`"
:title="site.name"
type="image/png"
class="logo"
>{{ site.name }}</object>
</a>
<span class="networklogo-container">
Part of
<a
:href="site.network.url"
target="_blank"
rel="noopener noreferrer"
class="networklogo-link"
>
<object
:data="`/img/logos/${site.network.slug}/network.png`"
:title="site.network.name"
type="image/png"
class="networklogo"
>{{ site.network.name }}</object>
</a>
</span>
</span>
</div>
<div class="content-inner">
<h3 class="heading">Latest releases</h3>
<ul class="nolist scenes">
<li
v-for="release in releases"
:key="`release-${release.id}`"
>
<ReleaseTile :release="release" />
</li>
</ul>
</div>
</div> </div>
</template> </template>
<script>
import ReleaseTile from '../tile/release.vue';
async function mounted() {
[this.site] = await this.$store.dispatch('fetchSites', this.$route.params.siteSlug);
this.releases = await this.$store.dispatch('fetchSiteReleases', this.$route.params.siteSlug);
this.pageTitle = this.site.name;
}
export default {
components: {
ReleaseTile,
},
data() {
return {
site: null,
releases: null,
pageTitle: null,
};
},
mounted,
};
</script>
<style lang="scss" scoped>
@import 'theme';
.header {
display: flex;
justify-content: space-between;
padding: 1rem;
}
.title {
display: inline-block;
margin: 0 .5rem 0 0;
}
.heading {
padding: 0;
margin: 0 0 1rem 0;
}
.link {
display: flex;
flex-shrink: 0;
flex-direction: column;
align-items: flex-end;
}
.logo {
height: 3rem;
}
.networklogo-container {
color: $shadow;
display: block;
margin: .5rem 0 0 0;
}
.networklogo {
color: $text;
height: 1rem;
font-weight: bold;
}
.sites,
.scenes {
display: grid;
grid-gap: 1rem;
margin: 0 0 1rem 0;
}
.scenes {
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
}
.sites {
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
</style>

View File

@ -5,8 +5,6 @@
<a <a
:href="`/site/${release.site.slug}`" :href="`/site/${release.site.slug}`"
:title="release.network.name" :title="release.network.name"
target="_blank"
rel="noopener noreferrer"
class="site site-link" class="site site-link"
>{{ release.site.name }}</a> >{{ release.site.name }}</a>
@ -34,14 +32,14 @@
> >
<img <img
v-if="release.poster" v-if="release.poster"
:src="`/media/${release.poster.path}`" :src="`/media/${release.poster.thumbnail}`"
:alt="release.title" :alt="release.title"
class="thumbnail" class="thumbnail"
> >
<img <img
v-else-if="release.photos.length > 0" v-else-if="release.photos.length > 0"
:src="`/media/${release.photos[0].path}`" :src="`/media/${release.photos[0].thumbnail}`"
:alt="release.title" :alt="release.title"
class="thumbnail" class="thumbnail"
> >
@ -92,8 +90,6 @@
> >
<a <a
:href="`/tag/${tag.slug}`" :href="`/tag/${tag.slug}`"
target="_blank"
rel="noopener noreferrer"
class="tag-link" class="tag-link"
>{{ tag.name }}</a> >{{ tag.name }}</a>
</li> </li>
@ -135,11 +131,8 @@ export default {
.thumbnail { .thumbnail {
width: 100%; width: 100%;
height: 12rem;
display: flex;
justify-content: center;
align-items: center;
object-fit: cover; object-fit: cover;
object-position: 50% 0;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
background-color: $shadow-hint; background-color: $shadow-hint;

View File

@ -47,7 +47,7 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 4rem; height: 3rem;
object-fit: contain; object-fit: contain;
font-size: 1rem; font-size: 1rem;
font-weight: bold; font-weight: bold;

View File

@ -0,0 +1,22 @@
import { get } from '../api';
function initSitesActions(_store, _router) {
async function fetchSites({ _commit }, siteId) {
const sites = await get(`/sites/${siteId || ''}`);
return sites;
}
async function fetchSiteReleases({ _commit }, siteId) {
const releases = await get(`/sites/${siteId}/releases`);
return releases;
}
return {
fetchSites,
fetchSiteReleases,
};
}
export default initSitesActions;

View File

@ -0,0 +1 @@
export default {};

13
assets/js/sites/sites.js Normal file
View File

@ -0,0 +1,13 @@
import state from './state';
import mutations from './mutations';
import actions from './actions';
function initSitesStore(store, router) {
return {
state,
mutations,
actions: actions(store, router),
};
}
export default initSitesStore;

1
assets/js/sites/state.js Normal file
View File

@ -0,0 +1 @@
export default {};

View File

@ -3,6 +3,7 @@ import Vuex from 'vuex';
import initAuthStore from './auth/auth'; import initAuthStore from './auth/auth';
import initReleasesStore from './releases/releases'; import initReleasesStore from './releases/releases';
import initSitesStore from './sites/sites';
import initNetworksStore from './networks/networks'; import initNetworksStore from './networks/networks';
import initActorsStore from './actors/actors'; import initActorsStore from './actors/actors';
@ -14,6 +15,7 @@ function initStore(router) {
store.registerModule('auth', initAuthStore(store, router)); store.registerModule('auth', initAuthStore(store, router));
store.registerModule('releases', initReleasesStore(store, router)); store.registerModule('releases', initReleasesStore(store, router));
store.registerModule('actors', initActorsStore(store, router)); store.registerModule('actors', initActorsStore(store, router));
store.registerModule('sites', initSitesStore(store, router));
store.registerModule('networks', initNetworksStore(store, router)); store.registerModule('networks', initNetworksStore(store, router));
return store; return store;

View File

@ -12,6 +12,8 @@ module.exports = {
'21sextury', '21sextury',
'blowpass', 'blowpass',
'brazzers', 'brazzers',
'dogfart',
'evilangel',
'julesjordan', 'julesjordan',
['kink', [ ['kink', [
'boundgangbangs', 'boundgangbangs',
@ -27,6 +29,7 @@ module.exports = {
'waterbondage', 'waterbondage',
]], ]],
'legalporno', 'legalporno',
'mikeadriano',
'mofos', 'mofos',
'naughtyamerica', 'naughtyamerica',
'pervcity', 'pervcity',
@ -79,7 +82,10 @@ module.exports = {
width: 30, width: 30,
}, },
], ],
photoPath: './', media: {
path: './',
thumbnailSize: 324, // width for 16:9 will be exactly 576px
},
filename: { filename: {
dateFormat: 'DD-MM-YYYY', dateFormat: 'DD-MM-YYYY',
actorsJoin: ', ', actorsJoin: ', ',

View File

@ -145,8 +145,10 @@ exports.up = knex => Promise.resolve()
table.increments('id', 16); table.increments('id', 16);
table.string('path'); table.string('path');
table.string('thumbnail');
table.integer('index'); table.integer('index');
table.string('mime'); table.string('mime');
table.string('hash');
table.enum('domain', ['networks', 'sites', 'releases', 'actors', 'directors']); table.enum('domain', ['networks', 'sites', 'releases', 'actors', 'directors']);
table.integer('target_id', 16); table.integer('target_id', 16);

346
package-lock.json generated
View File

@ -1584,8 +1584,7 @@
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
"dev": true
}, },
"arch": { "arch": {
"version": "2.1.1", "version": "2.1.1",
@ -1596,7 +1595,6 @@
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"dev": true,
"requires": { "requires": {
"delegates": "^1.0.0", "delegates": "^1.0.0",
"readable-stream": "^2.0.6" "readable-stream": "^2.0.6"
@ -2446,6 +2444,41 @@
"integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==",
"dev": true "dev": true
}, },
"bl": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz",
"integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==",
"requires": {
"readable-stream": "^3.0.1"
},
"dependencies": {
"readable-stream": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
"integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"blake2": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/blake2/-/blake2-4.0.0.tgz",
"integrity": "sha512-PIOc6RXAZYBYcdpyMzI6/SCU3BH8EbmA9vr0BAVyQv48CQTXDN6viHOTM+8KQue2IPsyHNpIR3UDisz8rZDPTA==",
"requires": {
"nan": "^2.14.0"
},
"dependencies": {
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
}
}
},
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@ -2859,8 +2892,7 @@
"chownr": { "chownr": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
"dev": true
}, },
"chrome-trace-event": { "chrome-trace-event": {
"version": "1.0.2", "version": "1.0.2",
@ -3003,6 +3035,15 @@
"object-visit": "^1.0.0" "object-visit": "^1.0.0"
} }
}, },
"color": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz",
"integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==",
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
}
},
"color-convert": { "color-convert": {
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -3016,6 +3057,15 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}, },
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"colors": { "colors": {
"version": "1.3.3", "version": "1.3.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
@ -3121,8 +3171,7 @@
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
"dev": true
}, },
"consolidate": { "consolidate": {
"version": "0.15.1", "version": "0.15.1",
@ -3480,6 +3529,19 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
}, },
"decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"requires": {
"mimic-response": "^2.0.0"
}
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"deep-is": { "deep-is": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -3547,8 +3609,7 @@
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
"dev": true
}, },
"depd": { "depd": {
"version": "1.1.2", "version": "1.1.2",
@ -3584,6 +3645,11 @@
"repeating": "^2.0.0" "repeating": "^2.0.0"
} }
}, },
"detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
},
"dev-null": { "dev-null": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz",
@ -4293,6 +4359,11 @@
} }
} }
}, },
"expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
},
"expand-tilde": { "expand-tilde": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
@ -4809,6 +4880,11 @@
"readable-stream": "^2.0.0" "readable-stream": "^2.0.0"
} }
}, },
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"fs-extra": { "fs-extra": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
@ -4819,6 +4895,14 @@
"universalify": "^0.1.0" "universalify": "^0.1.0"
} }
}, },
"fs-minipass": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.0.0.tgz",
"integrity": "sha512-40Qz+LFXmd9tzYVnnBmZvFfvAADfUA14TXPK1s7IfElJTIZ97rA8w4Kin7Wt5JBrC3ShnnFJO/5vPjPEeJIq9A==",
"requires": {
"minipass": "^3.0.0"
}
},
"fs-readdir-recursive": { "fs-readdir-recursive": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
@ -5418,7 +5502,6 @@
"version": "2.7.4", "version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"dev": true,
"requires": { "requires": {
"aproba": "^1.0.3", "aproba": "^1.0.3",
"console-control-strings": "^1.0.0", "console-control-strings": "^1.0.0",
@ -5433,14 +5516,12 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
"dev": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -5449,7 +5530,6 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -5460,7 +5540,6 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -5508,6 +5587,11 @@
"assert-plus": "^1.0.0" "assert-plus": "^1.0.0"
} }
}, },
"github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
},
"glob": { "glob": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
@ -5679,8 +5763,7 @@
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
"dev": true
}, },
"has-value": { "has-value": {
"version": "1.0.0", "version": "1.0.0",
@ -7137,6 +7220,11 @@
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"dev": true "dev": true
}, },
"mimic-response": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.0.0.tgz",
"integrity": "sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ=="
},
"mini-css-extract-plugin": { "mini-css-extract-plugin": {
"version": "0.7.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.7.0.tgz", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.7.0.tgz",
@ -7174,6 +7262,37 @@
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}, },
"minipass": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz",
"integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==",
"requires": {
"yallist": "^4.0.0"
},
"dependencies": {
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
},
"minizlib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz",
"integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==",
"requires": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"dependencies": {
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
},
"mississippi": { "mississippi": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
@ -7310,6 +7429,11 @@
"to-regex": "^3.0.1" "to-regex": "^3.0.1"
} }
}, },
"napi-build-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.1.tgz",
"integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA=="
},
"natural-compare": { "natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -7337,6 +7461,14 @@
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
}, },
"node-abi": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.12.0.tgz",
"integrity": "sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw==",
"requires": {
"semver": "^5.4.1"
}
},
"node-gyp": { "node-gyp": {
"version": "3.8.0", "version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
@ -7520,6 +7652,11 @@
} }
} }
}, },
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
},
"nopt": { "nopt": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
@ -7577,7 +7714,6 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"requires": { "requires": {
"are-we-there-yet": "~1.1.2", "are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0", "console-control-strings": "~1.1.0",
@ -8379,6 +8515,35 @@
} }
} }
}, },
"prebuild-install": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.3.tgz",
"integrity": "sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==",
"requires": {
"detect-libc": "^1.0.3",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"napi-build-utils": "^1.0.1",
"node-abi": "^2.7.0",
"noop-logger": "^0.1.1",
"npmlog": "^4.0.1",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^3.0.3",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0",
"which-pm-runs": "^1.0.0"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"prelude-ls": { "prelude-ls": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@ -8655,6 +8820,24 @@
"schema-utils": "^1.0.0" "schema-utils": "^1.0.0"
} }
}, },
"rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"react": { "react": {
"version": "16.8.6", "version": "16.8.6",
"resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz",
@ -9506,6 +9689,34 @@
} }
} }
}, },
"sharp": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.23.2.tgz",
"integrity": "sha512-BSo0tq6Jtzwa6GDKvVMNNPCP/HLczrFLGVcorYv7OtxlKx4UPHy7x9DdfT8F+PK7FCFDemVRwtsjWpvaJI9v6w==",
"requires": {
"color": "^3.1.2",
"detect-libc": "^1.0.3",
"nan": "^2.14.0",
"npmlog": "^4.1.2",
"prebuild-install": "^5.3.2",
"semver": "^6.3.0",
"simple-get": "^3.1.0",
"tar": "^5.0.5",
"tunnel-agent": "^0.6.0"
},
"dependencies": {
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
"shebang-command": { "shebang-command": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -9529,6 +9740,36 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
}, },
"simple-concat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
"integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
},
"simple-get": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
"requires": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"requires": {
"is-arrayish": "^0.3.1"
},
"dependencies": {
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},
"slash": { "slash": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
@ -10027,8 +10268,7 @@
"strip-json-comments": { "strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
"dev": true
}, },
"style-loader": { "style-loader": {
"version": "0.23.1", "version": "0.23.1",
@ -10099,6 +10339,66 @@
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
"dev": true "dev": true
}, },
"tar": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/tar/-/tar-5.0.5.tgz",
"integrity": "sha512-MNIgJddrV2TkuwChwcSNds/5E9VijOiw7kAc1y5hTNJoLDSuIyid2QtLYiCYNnICebpuvjhPQZsXwUL0O3l7OQ==",
"requires": {
"chownr": "^1.1.3",
"fs-minipass": "^2.0.0",
"minipass": "^3.0.0",
"minizlib": "^2.1.0",
"mkdirp": "^0.5.0",
"yallist": "^4.0.0"
},
"dependencies": {
"chownr": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
"integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw=="
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
},
"tar-fs": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz",
"integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==",
"requires": {
"chownr": "^1.1.1",
"mkdirp": "^0.5.1",
"pump": "^3.0.0",
"tar-stream": "^2.0.0"
}
},
"tar-stream": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz",
"integrity": "sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==",
"requires": {
"bl": "^3.0.0",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"dependencies": {
"readable-stream": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
"integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"tarn": { "tarn": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.4.tgz", "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.4.tgz",
@ -11103,11 +11403,15 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
}, },
"which-pm-runs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
},
"wide-align": { "wide-align": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"dev": true,
"requires": { "requires": {
"string-width": "^1.0.2 || 2" "string-width": "^1.0.2 || 2"
} }

View File

@ -64,6 +64,7 @@
}, },
"dependencies": { "dependencies": {
"bhttp": "^1.2.4", "bhttp": "^1.2.4",
"blake2": "^4.0.0",
"bluebird": "^3.5.4", "bluebird": "^3.5.4",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"cheerio": "^1.0.0-rc.2", "cheerio": "^1.0.0-rc.2",
@ -86,6 +87,7 @@
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "^16.8.6", "react": "^16.8.6",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"sharp": "^0.23.2",
"tough-cookie": "^3.0.1", "tough-cookie": "^3.0.1",
"tty-table": "^2.7.0", "tty-table": "^2.7.0",
"vue": "^2.6.10", "vue": "^2.6.10",

View File

@ -15,12 +15,10 @@
} }
.thumbnail[data-v-3abcf101] { .thumbnail[data-v-3abcf101] {
width: 100%; width: 100%;
height: 12rem;
display: flex;
justify-content: center;
align-items: center;
-o-object-fit: cover; -o-object-fit: cover;
object-fit: cover; object-fit: cover;
-o-object-position: 50% 0;
object-position: 50% 0;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
background-color: rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.1);
@ -226,6 +224,52 @@
color: #ff6c88; color: #ff6c88;
} }
/* $primary: #ff886c; */
.header[data-v-3e57cf44] {
display: flex;
justify-content: space-between;
padding: 1rem;
}
.title[data-v-3e57cf44] {
display: inline-block;
margin: 0 .5rem 0 0;
}
.heading[data-v-3e57cf44] {
padding: 0;
margin: 0 0 1rem 0;
}
.link[data-v-3e57cf44] {
display: flex;
flex-shrink: 0;
flex-direction: column;
align-items: flex-end;
}
.logo[data-v-3e57cf44] {
height: 3rem;
}
.networklogo-container[data-v-3e57cf44] {
color: rgba(0, 0, 0, 0.5);
display: block;
margin: .5rem 0 0 0;
}
.networklogo[data-v-3e57cf44] {
color: #222;
height: 1rem;
font-weight: bold;
}
.sites[data-v-3e57cf44],
.scenes[data-v-3e57cf44] {
display: grid;
grid-gap: 1rem;
margin: 0 0 1rem 0;
}
.scenes[data-v-3e57cf44] {
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
}
.sites[data-v-3e57cf44] {
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
/* $primary: #ff886c; */ /* $primary: #ff886c; */
.tile[data-v-f4958086] { .tile[data-v-f4958086] {
display: flex; display: flex;
@ -247,7 +291,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 4rem; height: 3rem;
-o-object-fit: contain; -o-object-fit: contain;
object-fit: contain; object-fit: contain;
font-size: 1rem; font-size: 1rem;
@ -288,7 +332,7 @@
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
} }
.sites[data-v-757c14c2] { .sites[data-v-757c14c2] {
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
} }
/* $primary: #ff886c; */ /* $primary: #ff886c; */

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -8,6 +8,6 @@
"no-unused-vars": ["error", {"argsIgnorePattern": "^_"}], "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}],
"no-console": 0, "no-console": 0,
"indent": ["error", 4], "indent": ["error", 4],
"max-len": [2, {"code": 200, "tabWidth": 4, "ignoreUrls": true}] "max-len": [2, {"code": 300, "tabWidth": 4, "ignoreUrls": true}]
} }
} }

View File

@ -35,6 +35,24 @@ async function fetchActors(actorId, actorSlug) {
return curateActors(releases); return curateActors(releases);
} }
async function storeActors(release, releaseEntry) {
const actors = await knex('actors').whereIn('name', release.actors);
const newActors = release.actors.filter(actorName => !actors.some(actor => actor.name === actorName));
const { rows: insertedActors } = newActors.length
? await knex.raw(`${knex('actors').insert(newActors.map(actorName => ({
name: actorName,
slug: actorName.toLowerCase().replace(/\s+/g, '-'),
})))} ON CONFLICT DO NOTHING RETURNING *`)
: { rows: [] };
return knex('actors_associated').insert(actors.concat(insertedActors).map(actor => ({
release_id: releaseEntry.id,
actor_id: actor.id,
})), '*');
}
module.exports = { module.exports = {
fetchActors, fetchActors,
storeActors,
}; };

View File

@ -5,13 +5,14 @@ const fs = require('fs-extra');
const path = require('path'); const path = require('path');
const Promise = require('bluebird'); const Promise = require('bluebird');
const moment = require('moment'); const moment = require('moment');
const mime = require('mime');
const bhttp = require('bhttp');
const argv = require('./argv'); const argv = require('./argv');
const knex = require('./knex'); const knex = require('./knex');
const scrapers = require('./scrapers'); const scrapers = require('./scrapers');
const fetchScene = require('./fetch-scene'); const fetchScene = require('./fetch-scene');
const { storeTags } = require('./tags');
const { storeActors } = require('./actors');
const { storePoster, storePhotos, storeTrailer } = require('./media');
function destructConfigNetworks(networks) { function destructConfigNetworks(networks) {
return networks.reduce((acc, network) => { return networks.reduce((acc, network) => {
@ -87,112 +88,6 @@ async function findDuplicateReleases(latestReleases, _siteId) {
.orWhereIn('entry_id', latestReleasesEntryIds); .orWhereIn('entry_id', latestReleasesEntryIds);
} }
async function storeActors(release, releaseEntry) {
const actors = await knex('actors').whereIn('name', release.actors);
const newActors = release.actors.filter(actorName => !actors.some(actor => actor.name === actorName));
const { rows: insertedActors } = newActors.length
? await knex.raw(`${knex('actors').insert(newActors.map(actorName => ({
name: actorName,
slug: actorName.toLowerCase().replace(/\s+/g, '-'),
})))} ON CONFLICT DO NOTHING RETURNING *`)
: { rows: [] };
return knex('actors_associated').insert(actors.concat(insertedActors).map(actor => ({
release_id: releaseEntry.id,
actor_id: actor.id,
})), '*');
}
async function storeTags(release, releaseEntry) {
return knex('tags_associated').insert(release.tags.map(tagId => ({
tag_id: tagId,
release_id: releaseEntry.id,
})));
}
async function storePhotos(release, releaseEntry) {
console.log(`Storing ${release.photos.length} photos for (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
const files = await Promise.map(release.photos, async (photoUrl, index) => {
const { pathname } = new URL(photoUrl);
const mimetype = mime.getType(pathname);
const res = await bhttp.get(photoUrl);
if (res.statusCode === 200) {
const filepath = path.join(release.site.slug, releaseEntry.id.toString(), `${index + 1}.${mime.getExtension(mimetype)}`);
await fs.writeFile(path.join(config.photoPath, filepath), res.body);
return {
filepath,
mimetype,
};
}
console.warn(`Failed to store photo ${index + 1} for (${release.site.name}, ${releaseEntry.id}) "${release.title}": ${res.statusCode}`);
return null;
}, {
concurrency: 2,
});
await knex('media').insert(files.filter(file => file).map(({ filepath, mimetype }, index) => ({
path: filepath,
mime: mimetype,
index,
domain: 'releases',
target_id: releaseEntry.id,
role: 'photo',
})));
}
async function storePoster(release, releaseEntry) {
console.log(`Storing poster for (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
const res = await bhttp.get(release.poster);
if (res.statusCode === 200) {
const { pathname } = new URL(release.poster);
const mimetype = res.headers['content-type'] || mime.getType(pathname) || 'image/jpeg';
const filepath = path.join(release.site.slug, releaseEntry.id.toString(), `poster.${mime.getExtension(mimetype)}`);
await fs.writeFile(path.join(config.photoPath, filepath), res.body);
await knex('media').insert({
path: filepath,
mime: mimetype,
domain: 'releases',
target_id: releaseEntry.id,
role: 'poster',
});
return;
}
console.warn(`Failed to store poster for (${release.site.name}, ${releaseEntry.id}) "${release.title}": ${res.statusCode}`);
}
async function storeTrailer(release, releaseEntry) {
console.log(`Storing trailer for (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
const { pathname } = new URL(release.trailer.src);
const mimetype = release.trailer.type || mime.getType(pathname);
const res = await bhttp.get(release.trailer.src);
const filepath = path.join(release.site.slug, releaseEntry.id.toString(), `trailer${release.trailer.quality ? `_${release.trailer.quality}` : ''}.${mime.getExtension(mimetype)}`);
await fs.writeFile(path.join(config.photoPath, filepath), res.body);
await knex('media').insert({
path: filepath,
mime: mimetype,
domain: 'releases',
target_id: releaseEntry.id,
role: 'trailer',
quality: release.trailer.quality || null,
});
}
async function storeReleases(releases = []) { async function storeReleases(releases = []) {
return Promise.map(releases, async (release) => { return Promise.map(releases, async (release) => {
const curatedRelease = { const curatedRelease = {
@ -212,11 +107,6 @@ async function storeReleases(releases = []) {
deep: argv.deep, deep: argv.deep,
}; };
/*
const releaseQuery = `${knex('releases').insert(curatedRelease).toString()} ON CONFLICT DO NOTHING RETURNING *`;
const releaseEntry = await knex.raw(releaseQuery);
*/
const releaseEntries = await knex('releases') const releaseEntries = await knex('releases')
.insert(curatedRelease) .insert(curatedRelease)
.returning('*'); .returning('*');
@ -227,7 +117,7 @@ async function storeReleases(releases = []) {
console.log(`Stored (${release.site.name}, ${releaseEntry.id}) "${release.title}"`); console.log(`Stored (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
if (release.poster || (release.photos && release.photos.length)) { if (release.poster || (release.photos && release.photos.length)) {
await fs.mkdir(path.join(config.photoPath, release.site.slug, releaseEntry.id.toString()), { recursive: true }); await fs.mkdir(path.join(config.media.path, release.site.network.slug, release.site.slug, releaseEntry.id.toString()), { recursive: true });
} }
await Promise.all([ await Promise.all([

137
src/media.js Normal file
View File

@ -0,0 +1,137 @@
'use strict';
const config = require('config');
const Promise = require('bluebird');
const path = require('path');
const fs = require('fs-extra');
const bhttp = require('bhttp');
const mime = require('mime');
const sharp = require('sharp');
const blake2 = require('blake2');
const knex = require('./knex');
function getHash(buffer) {
const hash = blake2.createHash('blake2b', { digestLength: 24 });
hash.update(buffer);
return hash.digest('hex');
}
async function storePoster(release, releaseEntry) {
console.log(`Storing poster for (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
const res = await bhttp.get(release.poster);
const thumbnail = await sharp(res.body)
.resize({ width: Math.floor((config.media.thumbnailSize / 9) * 16), height: config.media.thumbnailSize }) // ensure thumbnail is 16:9
.toBuffer();
if (res.statusCode === 200) {
const { pathname } = new URL(release.poster);
const mimetype = res.headers['content-type'] || mime.getType(pathname) || 'image/jpeg';
const extension = mime.getExtension(mimetype);
const filepath = path.join(release.site.network.slug, release.site.slug, releaseEntry.id.toString(), `poster.${extension}`);
const thumbpath = path.join(release.site.network.slug, release.site.slug, releaseEntry.id.toString(), `poster_thumb.${extension}`);
const hash = getHash(res.body);
await Promise.all([
fs.writeFile(path.join(config.media.path, filepath), res.body),
fs.writeFile(path.join(config.media.path, thumbpath), thumbnail),
]);
await knex('media').insert({
path: filepath,
thumbnail: thumbpath,
mime: mimetype,
hash,
domain: 'releases',
target_id: releaseEntry.id,
role: 'poster',
});
return;
}
console.warn(`Failed to store poster for (${release.site.name}, ${releaseEntry.id}) "${release.title}": ${res.statusCode}`);
}
async function storePhotos(release, releaseEntry) {
console.log(`Storing ${release.photos.length} photos for (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
const files = await Promise.map(release.photos, async (photoUrl, index) => {
const { pathname } = new URL(photoUrl);
const mimetype = mime.getType(pathname);
const res = await bhttp.get(photoUrl);
const thumbnail = await sharp(res.body).resize({ height: config.media.thumbnailSize }).toBuffer();
if (res.statusCode === 200) {
const extension = mime.getExtension(mimetype);
const filepath = path.join(release.site.network.slug, release.site.slug, releaseEntry.id.toString(), `${index + 1}.${extension}`);
const thumbpath = path.join(release.site.network.slug, release.site.slug, releaseEntry.id.toString(), `${index + 1}_thumb.${extension}`);
const hash = getHash(res.body);
await Promise.all([
fs.writeFile(path.join(config.media.path, filepath), res.body),
fs.writeFile(path.join(config.media.path, thumbpath), thumbnail),
]);
return {
filepath,
thumbpath,
mimetype,
hash,
};
}
console.warn(`Failed to store photo ${index + 1} for (${release.site.name}, ${releaseEntry.id}) "${release.title}": ${res.statusCode}`);
return null;
}, {
concurrency: 2,
});
await knex('media')
.insert(files.filter(file => file)
.map((file, index) => ({
path: file.filepath,
thumbnail: file.thumbpath,
mime: file.mimetype,
hash: file.hash,
index,
domain: 'releases',
target_id: releaseEntry.id,
role: 'photo',
})));
}
async function storeTrailer(release, releaseEntry) {
console.log(`Storing trailer for (${release.site.name}, ${releaseEntry.id}) "${release.title}"`);
const { pathname } = new URL(release.trailer.src);
const mimetype = release.trailer.type || mime.getType(pathname);
const res = await bhttp.get(release.trailer.src);
const filepath = path.join(release.site.network.slug, release.site.slug, releaseEntry.id.toString(), `trailer${release.trailer.quality ? `_${release.trailer.quality}` : ''}.${mime.getExtension(mimetype)}`);
await Promise.all([
fs.writeFile(path.join(config.media.path, filepath), res.body),
knex('media').insert({
path: filepath,
mime: mimetype,
domain: 'releases',
target_id: releaseEntry.id,
role: 'trailer',
quality: release.trailer.quality || null,
}),
]);
}
module.exports = {
storePoster,
storePhotos,
storeTrailer,
};

View File

@ -3,8 +3,6 @@
const knex = require('./knex'); const knex = require('./knex');
async function curateSite(site) { async function curateSite(site) {
const network = await knex('network').where({ id: site.network_id });
return { return {
id: site.id, id: site.id,
name: site.name, name: site.name,
@ -12,36 +10,40 @@ async function curateSite(site) {
description: site.description, description: site.description,
slug: site.slug, slug: site.slug,
network: { network: {
id: network.id, id: site.network_id,
name: network.name, name: site.network_name,
url: network.url, slug: site.network_slug,
description: network.description, url: site.network_url,
slug: network.slug,
}, },
}; };
} }
function curateSites(releases) { function curateSites(sites) {
return Promise.all(releases.map(async site => curateSite(site))); return Promise.all(sites.map(async site => curateSite(site)));
} }
async function fetchSites(siteId, siteSlug) { async function fetchSites(siteId, siteSlug) {
const releases = await knex('sites') const sites = await knex('sites')
.where({ id: siteId }) .where({ 'sites.id': siteId })
.orWhere({ slug: siteSlug }) .orWhere({ 'sites.slug': siteSlug })
.select(
'sites.*',
'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url',
)
.leftJoin('networks', 'sites.network_id', 'networks.id')
.limit(100); .limit(100);
return curateSites(releases); return curateSites(sites);
} }
async function fetchSitesFromReleases() { async function fetchSitesFromReleases() {
const releases = await knex('releases') const sites = await knex('releases')
.select('site_id', '') .select('site_id', '')
.leftJoin('sites', 'sites.id', 'releases.site_id') .leftJoin('sites', 'sites.id', 'releases.site_id')
.groupBy('sites.id') .groupBy('sites.id')
.limit(100); .limit(100);
return curateSites(releases); return curateSites(sites);
} }
module.exports = { module.exports = {

View File

@ -25,4 +25,14 @@ async function matchTags(rawTags) {
return tagEntries; return tagEntries;
} }
module.exports = { matchTags }; async function storeTags(release, releaseEntry) {
return knex('tags_associated').insert(release.tags.map(tagId => ({
tag_id: tagId,
release_id: releaseEntry.id,
})));
}
module.exports = {
matchTags,
storeTags,
};

View File

@ -25,7 +25,7 @@ function initServer() {
const app = express(); const app = express();
const router = Router(); const router = Router();
router.use('/media', express.static(config.photoPath)); router.use('/media', express.static(config.media.path));
router.use(express.static('public')); router.use(express.static('public'));
router.use('/img', (req, res) => { router.use('/img', (req, res) => {

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
const { fetchSites, fetchSitesFromReleases } = require('../networks'); const { fetchSites, fetchSitesFromReleases } = require('../sites');
async function fetchSitesApi(req, res) { async function fetchSitesApi(req, res) {
const siteId = typeof req.params.siteId === 'number' ? req.params.siteId : null; const siteId = typeof req.params.siteId === 'number' ? req.params.siteId : null;