224 lines
6.0 KiB
TypeScript
224 lines
6.0 KiB
TypeScript
import { RouterContext } from "https://deno.land/x/oak/mod.ts"
|
|
import "https://deno.land/std@0.178.0/dotenv/load.ts";
|
|
import { writeFileSync, copy } from "https://deno.land/std/fs/mod.ts";
|
|
import { renderFileToString } from "https://deno.land/x/dejs/mod.ts";
|
|
|
|
import getFileHash from './getFileHash.ts';
|
|
import allowedFiletypes from './fileTypes.ts';
|
|
import db from './mongodb.ts';
|
|
const imageCollection = db.collection('images');
|
|
const userTable = db.collection('users');
|
|
|
|
|
|
export const site = async (ctx: RouterContext) => {
|
|
if(ctx.params.filename == "sw.js" || ctx.params.filename == "script.js"){
|
|
ctx.response.type = "text/javascript"
|
|
}
|
|
if(ctx.params.filename == "style.css"){
|
|
ctx.response.type = "text/css"
|
|
}
|
|
ctx.response.body = await renderFileToString(`${Deno.cwd()}/site/${ctx.params.filename}`, {})
|
|
}
|
|
|
|
export const icons = async (ctx: RouterContext, next: any) => {
|
|
const identifier = ctx.params.filename
|
|
if (["t_192.png", "t_48.png", "t_96.png"].indexOf(identifier) != -1){
|
|
const img = await Deno.readFile(`${Deno.cwd()}/site/i/${ctx.params.filename}`);
|
|
ctx.response.type = "image/png";
|
|
ctx.response.body = img;
|
|
} else {
|
|
next()
|
|
}
|
|
}
|
|
|
|
export const announce = async (ctx: RouterContext) => {
|
|
const body = await ctx.request.body({ type: 'json'}).value;
|
|
|
|
const count = await imageCollection.findOne({hash:body.hash});
|
|
|
|
if(body.size >= 50000000 && body.usercode == "anonymous"){
|
|
ctx.response.status = 403
|
|
}
|
|
else if(count){
|
|
ctx.response.body = {file: count.filename};
|
|
ctx.response.status = 409
|
|
}else{
|
|
if(body.size >= 50000000){
|
|
const users = await userTable.findOne({token:body.usercode});
|
|
if(users){
|
|
ctx.response.status = 200
|
|
}else{
|
|
ctx.response.status = 403
|
|
}
|
|
}else{
|
|
ctx.response.status = 200
|
|
}
|
|
}
|
|
}
|
|
|
|
export const chunks = async (ctx: RouterContext) => {
|
|
const hash = ctx.request.headers.get("file-hash");
|
|
const number = ctx.request.headers.get("file-hash");
|
|
|
|
const body = await ctx.request.body({ type: 'form-data'});
|
|
const formData = await body.value.read();
|
|
|
|
const size = ctx.request.headers.get("content-range").split("/")[1]
|
|
const data = await Deno.readFile(formData.files[0].filename)
|
|
|
|
Deno.writeFileSync(`${Deno.env.get("TMPPATH")}${hash}.${ctx.request.headers.get("content-number")}.temp`, data)
|
|
|
|
ctx.response.status = 200
|
|
}
|
|
|
|
export const mergeChunks = async (ctx: RouterContext) => {
|
|
const body = await ctx.request.body({ type: 'json'}).value;
|
|
|
|
const ts = new Date();
|
|
let newname = `${ts.valueOf()}${allowedFiletypes.get(body.type)}`
|
|
|
|
let files = []
|
|
for await (const dirEntry of Deno.readDir(Deno.env.get("TMPPATH"))) {
|
|
if(dirEntry.name.includes(body.hash) && dirEntry.isFile){
|
|
files.push(dirEntry.name)
|
|
}
|
|
|
|
}
|
|
|
|
const tempFile = await Deno.makeTempFile();
|
|
|
|
for (let i = 0; i < files.length; i++) {
|
|
let file = files.find(elem => elem.includes(`.${i}.temp`))
|
|
const data = await Deno.readFileSync(`${Deno.env.get("TMPPATH")}${file}`)
|
|
|
|
await Deno.writeFileSync(tempFile, data, {"append": true})
|
|
Deno.remove(`${Deno.env.get("TMPPATH")}${file}`);
|
|
}
|
|
|
|
await copy(tempFile, `${Deno.env.get("IMAGEPATH")}${newname}`)
|
|
|
|
const id = await imageCollection.insertOne({
|
|
hash:body.hash,
|
|
mime:body.type,
|
|
filename:newname,
|
|
usercode:body.usercode,
|
|
time:ts
|
|
});
|
|
|
|
|
|
const newhash = await getFileHash(tempFile)
|
|
if(body.hash == newhash){
|
|
ctx.response.body = {"file":newname}
|
|
ctx.response.status = 201
|
|
}else{
|
|
ctx.response.status = 418
|
|
}
|
|
}
|
|
|
|
export const getImage = async (ctx: RouterContext) => {
|
|
const identifier = ctx.params.filename;
|
|
|
|
const info = await imageCollection.findOne({filename:identifier});
|
|
|
|
if(!info){
|
|
ctx.response.status = 404;
|
|
ctx.response.body = {message: 'image does not exist'};
|
|
return
|
|
}else{
|
|
const img = await Deno.readFile(`${Deno.env.get("IMAGEPATH")}${identifier}`);
|
|
|
|
ctx.response.type = info.mime;
|
|
ctx.response.body = img;
|
|
}
|
|
}
|
|
|
|
export const deleteImage = async (ctx: RouterContext) => {
|
|
const identifier = ctx.params.filename;
|
|
|
|
const count = await imageCollection.findOne({filename:identifier});
|
|
|
|
if(!count){
|
|
ctx.response.status = 404;
|
|
ctx.response.body = {message: 'image does not exist'};
|
|
return
|
|
}else{
|
|
console.log(count)
|
|
|
|
if(ctx.request.headers.get("usercode")==count.usercode){
|
|
const deleted = await imageCollection.deleteOne({_id:count._id})
|
|
if(!deleted){
|
|
ctx.response.status = 500;
|
|
}else{
|
|
await Deno.remove(`${Deno.env.get("IMAGEPATH")}${count.filename}`);
|
|
ctx.response.status = 204
|
|
}
|
|
|
|
}else{
|
|
ctx.response.body = {message: 'Unauthorized'};
|
|
ctx.response.status = 401
|
|
}
|
|
}
|
|
}
|
|
|
|
export const uploadImage = async (ctx: RouterContext) => {
|
|
const body = await ctx.request.body({ type: 'form-data'}).value;
|
|
const formData = await body.read();
|
|
|
|
const usercode = ctx.request.headers.get("usercode") ? ctx.request.headers.get("usercode") : "anonymous";
|
|
|
|
let promises = [];
|
|
let files = [];
|
|
|
|
formData.files.forEach(file => promises.push(new Promise(async (resolve, reject)=>{
|
|
if(!allowedFiletypes.get(file.contentType)){
|
|
reject("rejected filetype")
|
|
}else{
|
|
const timestamp = new Date()
|
|
const hash = getFileHash(file.filename)
|
|
|
|
const count = await imageCollection.findOne({hash:hash});
|
|
|
|
if(!count){
|
|
const newFilename = `${timestamp.valueOf()}${allowedFiletypes.get(file.contentType)}`
|
|
copy(file.filename, `${Deno.env.get("IMAGEPATH")}${newFilename}`, {overwrite: true})
|
|
const id = await imageCollection.insertOne({
|
|
hash:hash,
|
|
mime:file.contentType,
|
|
filename:newFilename,
|
|
usercode:usercode,
|
|
time:timestamp
|
|
});
|
|
|
|
files.push(newFilename)
|
|
resolve(newFilename)
|
|
}else{
|
|
files.push(count.filename)
|
|
resolve(count.filename)
|
|
}
|
|
}
|
|
})))
|
|
|
|
const result = await Promise.allSettled(promises)
|
|
|
|
const rejected = await result.filter(obj => Object.keys(obj).some(key => obj[key].includes("rejected")))
|
|
|
|
if(rejected.length >= 1){
|
|
ctx.response.status = 405;
|
|
ctx.response.body = {message:rejected[0].reason}
|
|
}else{
|
|
if(files.length > 1){
|
|
ctx.response.body = files
|
|
}else{
|
|
ctx.response.body = {"img":files[0]}
|
|
}
|
|
|
|
ctx.response.status = 201
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|