feat(api): add support for invisible images

This commit is contained in:
diced 2021-09-02 20:59:30 -07:00
parent 912f716362
commit 3daac34d3e
No known key found for this signature in database
GPG key ID: 85AB64C74535D76E
9 changed files with 81 additions and 56 deletions

View file

@ -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",

View file

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Image" ADD COLUMN "embed" BOOLEAN NOT NULL DEFAULT false;

View file

@ -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

View file

@ -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,

View file

@ -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'),

View file

@ -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;
}

View file

@ -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
}
};
};

View file

@ -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}`
});
}

View file

@ -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"