diff --git a/pages/import_from_derpi.tsx b/pages/import_from_derpi.tsx new file mode 100644 index 0000000..0c57429 --- /dev/null +++ b/pages/import_from_derpi.tsx @@ -0,0 +1,68 @@ +import AppBar from '../components/AppBar' +import db_ops from '../server/helpers/db_ops' +import Button from '@material-ui/core/Button'; +import axios from 'axios' +import config from '../config/config' +import TextField from '@material-ui/core/TextField'; + +import ErrorPage from 'next/error' +import { useState } from 'react'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function Import_from_derpi(props:any) { + if(props.err){ + return + } + const [error, setError] = useState(false); + const [ImageID, setID] = useState(''); + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.keyCode === 13 || e.which === 13) { + add_image(); + } + }; + const add_image=()=>{ + axios(`${config.domain}/import_from_derpi`, { + method: "post", + data: {id:ImageID}, + withCredentials: true + }).then((resp)=>{ + alert(JSON.stringify(resp.data)) + }).catch((err)=>{ + console.log(err) + }) + } + + + return ( +
+ + setID(e.target.value)} + onKeyPress={(e)=>handleKeyPress(e)} + /> + +
+ ); +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export async function getServerSideProps(context:any) { + if(context.req.session.authed&&context.req.session.user_id){ + const user=await db_ops.activated_user.find_user_by_id(context.req.session.user_id) + if(user[0].isAdmin){ + return { + props: {}, + } + } +} + return { + props: {err:true}, + } +} + \ No newline at end of file diff --git a/server/index.ts b/server/index.ts index 3dc1c80..7e2eb44 100644 --- a/server/index.ts +++ b/server/index.ts @@ -32,6 +32,7 @@ import change_password from './routes/change_password'; import forgot_password from './routes/forgot_password'; import activate_account_email from './routes/activate_account_email'; import update_image_data from './routes/update_image_data' +import import_from_derpi from './routes/import_from_derpi' next_app.prepare().then(() => { const app = express() const limiter = rateLimit({ @@ -84,6 +85,7 @@ next_app.prepare().then(() => { app.post('/update_image_data', update_image_data) + app.post('/import_from_derpi', import_from_derpi) app.post('/signup', [ recaptcha.middleware.verify, diff --git a/server/routes/import_from_derpi.ts b/server/routes/import_from_derpi.ts new file mode 100644 index 0000000..e03fb54 --- /dev/null +++ b/server/routes/import_from_derpi.ts @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable @typescript-eslint/no-var-requires */ +import db_ops from './../helpers/db_ops' +import { Request, Response } from 'express'; +import axios from 'axios' +import fs from 'fs' +import path from 'path'; +const imghash: any = require('imghash'); +const PATH_TO_IMAGES = path.join(process.cwd(), 'public', 'images') +async function parse_author(tags: any) { + for (const tag of tags) { + const idx = tag.indexOf("artist:") + if (idx === 0) { //tag starts with "artist:" + return tag.slice(7) //strip off "artist:" + } + } + return "???" +} + +async function import_from_derpi(req: Request, res: Response) { + const id = parseInt(req.body.id); + const ALLOWED_FORMATS = ["png", 'jpg', "jpeg"] + if (req.session?.user_id) { + const user = await db_ops.activated_user.find_user_by_id(req.session?.user_id) + if (user[0].isAdmin) { + try { + const imgs = await db_ops.image_ops.find_image_by_id(id) + console.log(imgs.length) + if (imgs.length !== 0) { + res.json({ message: "Already in the DB" }) + return + } + const response = await axios.get(`https://www.derpibooru.org/api/v1/json/images/${id}`,{ headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36' } }); + const derpi_data = response.data.image + if (!ALLOWED_FORMATS.includes(derpi_data.format.toLowerCase())) { + res.json({ message: "format is not in allowed formats" }) + return + } + const image =await axios.get(derpi_data.representations.full, {responseType: 'arraybuffer'}) + const image_id = (await db_ops.image_ops.get_max_image_id())+1 + fs.writeFile(`${PATH_TO_IMAGES}/${image_id}.${derpi_data.format.toLowerCase()}`, image.data, 'binary', function (err) { + if (err) { + console.log(`There was an error writing the image: derpi_id: ${id} id: ${image_id}`) + } + }); + const parsed_author = await parse_author(derpi_data.tags) + const derpi_link = "https://derpibooru.org/images/" + derpi_data.id + const phash = await imghash.hash(`${PATH_TO_IMAGES}/${image_id}.${derpi_data.format.toLowerCase()}`, 16); + await db_ops.image_ops.add_image(image_id, derpi_data.format.toLowerCase(), derpi_data.width, derpi_data.height, parsed_author, derpi_data.size, + derpi_link, derpi_data.upvotes, derpi_data.downvotes, derpi_data.id, derpi_data.created_at, + derpi_data.source_url, derpi_data.tags, derpi_data.wilson_score, derpi_data.sha512_hash, phash, derpi_data.description) + res.json({ message: `OK. New image_id: ${image_id}`}) + return + } catch (error) { + console.error(error); + } + + } + } + res.sendStatus(404); +} + +export default import_from_derpi; \ No newline at end of file