feat(api): add support for invisible images
This commit is contained in:
parent
912f716362
commit
3daac34d3e
9 changed files with 81 additions and 56 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "zip3",
|
||||
"version": "3.2.0",
|
||||
"version": "3.2.1",
|
||||
"scripts": {
|
||||
"prepare": "husky install",
|
||||
"dev": "NODE_ENV=development node server",
|
||||
|
@ -20,7 +20,7 @@
|
|||
"@material-ui/data-grid": "^4.0.0-alpha.32",
|
||||
"@material-ui/icons": "^5.0.0-alpha.37",
|
||||
"@material-ui/styles": "^5.0.0-alpha.35",
|
||||
"@prisma/client": "^2.30.0",
|
||||
"@prisma/client": "^2.30.3",
|
||||
"@reduxjs/toolkit": "^1.6.0",
|
||||
"argon2": "^0.28.2",
|
||||
"colorette": "^1.2.2",
|
||||
|
@ -29,8 +29,8 @@
|
|||
"fecha": "^4.2.1",
|
||||
"formik": "^2.2.9",
|
||||
"multer": "^1.4.2",
|
||||
"next": "11.1.0",
|
||||
"prisma": "^2.30.0",
|
||||
"next": "11.1.1",
|
||||
"prisma": "^2.30.3",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-dropzone": "^11.3.2",
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Image" ADD COLUMN "embed" BOOLEAN NOT NULL DEFAULT false;
|
|
@ -43,6 +43,7 @@ model Image {
|
|||
created_at DateTime @default(now())
|
||||
views Int @default(0)
|
||||
favorite Boolean @default(false)
|
||||
embed Boolean @default(false)
|
||||
invisible InvisibleImage?
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
|
|
@ -60,14 +60,16 @@ function shouldUseYarn() {
|
|||
const prisma = new PrismaClient();
|
||||
|
||||
const srv = createServer(async (req, res) => {
|
||||
if (req.url.startsWith(config.uploader.route)) {
|
||||
if (req.url.startsWith('/raw')) {
|
||||
const parts = req.url.split('/');
|
||||
if (!parts[2] || parts[2] === '') return;
|
||||
|
||||
let image = await prisma.image.findFirst({
|
||||
where: {
|
||||
OR: { file: parts[2] },
|
||||
OR: { invisible: { invis: decodeURI(parts[2]) } }
|
||||
OR: [
|
||||
{ file: parts[2] },
|
||||
{ invisible:{ invis: decodeURI(parts[2]) } }
|
||||
]
|
||||
},
|
||||
select: {
|
||||
mimetype: true,
|
||||
|
|
|
@ -14,7 +14,6 @@ module.exports = async config => {
|
|||
path('core.port', 'number'),
|
||||
path('core.database_url', 'string'),
|
||||
path('uploader.route', 'string'),
|
||||
path('uploader.embed_route', 'string'),
|
||||
path('uploader.length', 'number'),
|
||||
path('uploader.directory', 'string'),
|
||||
path('uploader.admin_limit', 'number'),
|
||||
|
|
|
@ -11,12 +11,11 @@ const envValues = [
|
|||
e('PORT', 'number', (c, v) => c.core.port = v),
|
||||
e('DATABASE_URL', 'string', (c, v) => c.core.database_url = v),
|
||||
e('UPLOADER_ROUTE', 'string', (c, v) => c.uploader.route = v),
|
||||
e('UPLOADER_EMBED_ROUTE', 'string', (c, v) => c.uploader.embed_route = v),
|
||||
e('UPLOADER_LENGTH', 'number', (c, v) => c.uploader.length = v),
|
||||
e('UPLOADER_DIRECTORY', 'string', (c, v) => c.uploader.directory = v),
|
||||
e('UPLOADER_ADMIN_LIMIT', 'number', (c, v) => c.uploader.admin_limit = v),
|
||||
e('UPLOADER_USER_LIMIT', 'number', (c, v) => c.uploader.user_limit = v),
|
||||
e('UPLOADER_DISABLED_EXTS', 'array', (c, v) => c.uploader.disabled_extentions = v),
|
||||
e('UPLOADER_DISABLED_EXTS', 'array', (c, v) => v ? c.uploader.disabled_extentions = v : c.uploader.disabled_extentions = [], false),
|
||||
];
|
||||
|
||||
module.exports = () => {
|
||||
|
@ -43,7 +42,6 @@ function tryReadEnv() {
|
|||
},
|
||||
uploader: {
|
||||
route: undefined,
|
||||
embed_route: undefined,
|
||||
length: undefined,
|
||||
directory: undefined,
|
||||
admin_limit: undefined,
|
||||
|
@ -63,11 +61,13 @@ function tryReadEnv() {
|
|||
}
|
||||
|
||||
envValues[i].fn(config, value);
|
||||
if (envValue.required) {
|
||||
if (envValue.type === 'number') value = parseToNumber(value);
|
||||
else if (envValue.type === 'boolean') value = parseToBoolean(value);
|
||||
else if (envValue.type === 'array') value = parseToArray(value);
|
||||
envValues[i].fn(config, value);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import Head from 'next/head';
|
||||
import { GetServerSideProps } from 'next';
|
||||
import { Box } from '@material-ui/core';
|
||||
|
@ -8,9 +8,24 @@ import prisma from 'lib/prisma';
|
|||
export default function EmbeddedImage({ image, title, username, color, normal, embed }) {
|
||||
const dataURL = (route: string) => `${route}/${image.file}`;
|
||||
|
||||
const updateImage = () => {
|
||||
const original = new Image;
|
||||
original.src = dataURL('/raw');
|
||||
|
||||
const imageEl = document.getElementById('image_content') as HTMLImageElement;
|
||||
imageEl.width = Math.floor(original.width * Math.min((innerHeight / original.height), (innerWidth / original.width)));
|
||||
imageEl.height = innerHeight;
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') window.onresize = () => updateImage();
|
||||
|
||||
useEffect(() => updateImage(), []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
{embed && (
|
||||
<>
|
||||
{title ? (
|
||||
<>
|
||||
<meta property='og:site_name' content={`${image.file} • ${username}`} />
|
||||
|
@ -20,19 +35,20 @@ export default function EmbeddedImage({ image, title, username, color, normal, e
|
|||
<meta property='og:title' content={`${image.file} • ${username}`} />
|
||||
)}
|
||||
<meta property='theme-color' content={color}/>
|
||||
<meta property='og:url' content={dataURL(embed)} />
|
||||
<meta property='og:image' content={dataURL(normal)} />
|
||||
<meta property='og:url' content={dataURL(normal)} />
|
||||
<meta property='og:image' content={dataURL('/raw')} />
|
||||
<meta property='twitter:card' content='summary_large_image' />
|
||||
</>
|
||||
)}
|
||||
<title>{image.file}</title>
|
||||
</Head>
|
||||
|
||||
<Box
|
||||
display='flex'
|
||||
justifyContent='center'
|
||||
alignItems='center'
|
||||
minHeight='100vh'
|
||||
>
|
||||
<img src={dataURL(normal)} alt={dataURL(normal)}/>
|
||||
<img src={dataURL('/raw')} alt={dataURL('/raw')} id='image_content' />
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
@ -41,24 +57,28 @@ export default function EmbeddedImage({ image, title, username, color, normal, e
|
|||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const id = context.params.id[1];
|
||||
const route = context.params.id[0];
|
||||
if (route !== config.uploader.embed_route.substr(1)) return {
|
||||
if (route !== config.uploader.route.substring(1)) return {
|
||||
notFound: true
|
||||
};
|
||||
|
||||
const image = await prisma.image.findFirst({
|
||||
where: {
|
||||
file: id
|
||||
OR: [
|
||||
{ file: id },
|
||||
{ invisible: { invis: id } }
|
||||
]
|
||||
},
|
||||
select: {
|
||||
file: true,
|
||||
mimetype: true,
|
||||
userId: true
|
||||
id: true,
|
||||
file: true,
|
||||
invisible: true,
|
||||
userId: true,
|
||||
embed: true
|
||||
}
|
||||
});
|
||||
|
||||
if (!image) return {
|
||||
notFound: true
|
||||
};
|
||||
if (!image) return { notFound: true };
|
||||
|
||||
const user = await prisma.user.findFirst({
|
||||
select: {
|
||||
|
@ -74,7 +94,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
|||
if (!image.mimetype.startsWith('image')) return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
destination: `${config.uploader.route}/${image.file}`,
|
||||
destination: `raw/${image.file}`,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -85,7 +105,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
|||
color: user.embedColor,
|
||||
username: user.username,
|
||||
normal: config.uploader.route,
|
||||
embed: config.uploader.embed_route
|
||||
embed: image.embed
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -33,7 +33,8 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
data: {
|
||||
file: `${rand}.${ext}`,
|
||||
mimetype: req.file.mimetype,
|
||||
userId: user.id
|
||||
userId: user.id,
|
||||
embed: !!req.headers.embed
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -44,7 +45,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
Logger.get('image').info(`User ${user.username} (${user.id}) uploaded an image ${image.file} (${image.id})`);
|
||||
|
||||
return res.json({
|
||||
url: `${zconfig.core.secure ? 'https' : 'http'}://${req.headers.host}${req.headers.embed ? zconfig.uploader.embed_route : zconfig.uploader.route}/${invis ? invis.invis : image.file}`
|
||||
url: `${zconfig.core.secure ? 'https' : 'http'}://${req.headers.host}${zconfig.uploader.route}/${invis ? invis.invis : image.file}`
|
||||
});
|
||||
}
|
||||
|
||||
|
|
36
yarn.lock
36
yarn.lock
|
@ -599,22 +599,22 @@
|
|||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
|
||||
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
|
||||
|
||||
"@prisma/client@^2.30.0":
|
||||
version "2.30.0"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-2.30.0.tgz#b0ed9db67405f619e428577f2d45843104142e00"
|
||||
integrity sha512-tjJNHVfgyNOwS2F+AkjMMCJGPnXzHuUCrOnAMJyidAu4aNzxbJ8jWwjt96rRMpyrg9Hwen3xqqQ2oA+ikK7nhQ==
|
||||
"@prisma/client@^2.30.3":
|
||||
version "2.30.3"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-2.30.3.tgz#49c1015e2cec26a44b20c62eb2fd738cb0bb043b"
|
||||
integrity sha512-Ey2miZ+Hne12We3rA8XrlPoAF0iuKEhw5IK2nropaelSt0Ju3b2qSz9Qt50a/1Mx3+7yRSu/iSXt8y9TUMl/Yw==
|
||||
dependencies:
|
||||
"@prisma/engines-version" "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb"
|
||||
"@prisma/engines-version" "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
|
||||
|
||||
"@prisma/engines-version@2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb":
|
||||
version "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb.tgz#1360113dc19e1d43d4442e3b638ccfa0e1711943"
|
||||
integrity sha512-oThNpx7HtJ0eEmnvrWARYcNCs6dqFdAK3Smt2bJVDD6Go4HLuuhjx028osP+rHaFrGOTx7OslLZYtvvFlAXRDA==
|
||||
"@prisma/engines-version@2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20":
|
||||
version "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20.tgz#d5ef55c92beeba56e52bba12b703af0bfd30530d"
|
||||
integrity sha512-/iDRgaoSQC77WN2oDsOM8dn61fykm6tnZUAClY+6p+XJbOEgZ9gy4CKuKTBgrjSGDVjtQ/S2KGcYd3Ring8xaw==
|
||||
|
||||
"@prisma/engines@2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb":
|
||||
version "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb.tgz#b4d91ff876662b1de83e0cc913149a1c088becc7"
|
||||
integrity sha512-LPKq88lIbYezvX0OOc1PU42hHdTsSMPJWmK8lusaHK7DaLHyXjDp/551LbsVapypbjW6N3Jx/If6GoMDASSMSw==
|
||||
"@prisma/engines@2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20":
|
||||
version "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20.tgz#2df768aa7c9f84acaa1f35c970417822233a9fb1"
|
||||
integrity sha512-WPnA/IUrxDihrRhdP6+8KAVSwsc0zsh8ioPYsLJjOhzVhwpRbuFH2tJDRIAbc+qFh+BbTIZbeyBYt8fpNXaYQQ==
|
||||
|
||||
"@reduxjs/toolkit@^1.6.0":
|
||||
version "1.6.0"
|
||||
|
@ -4426,12 +4426,12 @@ prepend-http@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
|
||||
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
|
||||
|
||||
prisma@^2.30.0:
|
||||
version "2.30.0"
|
||||
resolved "https://registry.yarnpkg.com/prisma/-/prisma-2.30.0.tgz#5b12091c480d538540b898d364b73651d44b4a01"
|
||||
integrity sha512-2XYpSibcVpMd1JDxYypGDU/JKq0W2f/HI1itdddr4Pfg+q6qxt/ItWKcftv4/lqN6u/BVlQ2gDzXVEjpHeO5kQ==
|
||||
prisma@^2.30.3:
|
||||
version "2.30.3"
|
||||
resolved "https://registry.yarnpkg.com/prisma/-/prisma-2.30.3.tgz#e4a770e1f52151e72c1c5be0aa2e75222a0135c4"
|
||||
integrity sha512-48qYba2BIyUmXuosBZs0g3kYGrxKvo4VkSHYOuLlDdDirmKyvoY2hCYMUYHSx3f++8ovfgs+MX5KmNlP+iAZrQ==
|
||||
dependencies:
|
||||
"@prisma/engines" "2.30.0-28.60b19f4a1de4fe95741da371b4c44a92f4d1adcb"
|
||||
"@prisma/engines" "2.30.1-2.b8c35d44de987a9691890b3ddf3e2e7effb9bf20"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
|
|
Loading…
Reference in a new issue