filehost/routes.ts

224 lines
6.0 KiB
TypeScript
Raw Normal View History

2023-08-12 06:15:32 +03:00
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');
2023-08-12 06:24:35 +03:00
export const site = async (ctx: RouterContext) => {
if(ctx.params.filename == "sw.js" || ctx.params.filename == "script.js"){
ctx.response.type = "text/javascript"
}
ctx.response.body = await renderFileToString(`${Deno.cwd()}/site/${ctx.params.filename}`, {})
}
2023-08-12 06:15:32 +03:00
export const icons = async (ctx: RouterContext, next: any) => {
const identifier = ctx.params.filename
console.log(["t_192.png", "t_48.png", "t_96.png"].indexOf(identifier))
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
}
}