mirror of
https://github.com/mollersuite/monofile.git
synced 2024-11-25 07:06:25 -08:00
this code sucks but oh well
This commit is contained in:
parent
7531515e78
commit
d30de18d26
|
@ -22,8 +22,9 @@ TOKEN=KILL-YOURSELF.NOW
|
||||||
- [X] 1.2.2 clean up this shitty code
|
- [X] 1.2.2 clean up this shitty code
|
||||||
- [X] 1.2.3 bugfixes
|
- [X] 1.2.3 bugfixes
|
||||||
- [ ] 1.3.0 new ui; accounts; utility endpoints; multi file uploads
|
- [ ] 1.3.0 new ui; accounts; utility endpoints; multi file uploads
|
||||||
- [ ] 1.3.1 self-destruct option
|
- [ ] 1.3.1 organize svelte code
|
||||||
- [ ] 1.3.2 disable cloning of local ips
|
- [ ] 1.3.2 self-destructing files
|
||||||
|
- [ ] 1.3.3 disable cloning of local ips
|
||||||
- [ ] 1.4.0 admin panel
|
- [ ] 1.4.0 admin panel
|
||||||
- [ ] 2.0.0 rewrite using theUnfunny's code as a base/rewrite using monofile-core
|
- [ ] 2.0.0 rewrite using theUnfunny's code as a base/rewrite using monofile-core
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,13 @@ app.get("/", function(req,res) {
|
||||||
app.post("/upload",multerSetup.single('file'),async (req,res) => {
|
app.post("/upload",multerSetup.single('file'),async (req,res) => {
|
||||||
if (req.file) {
|
if (req.file) {
|
||||||
try {
|
try {
|
||||||
files.uploadFile({name:req.file.originalname,mime:req.file.mimetype,uploadId:req.header("monofile-upload-id")},req.file.buffer)
|
let prm = req.header("monofile-params")
|
||||||
|
let params:{[key:string]:any} = {}
|
||||||
|
if (prm) {
|
||||||
|
params = JSON.parse(prm)
|
||||||
|
}
|
||||||
|
|
||||||
|
files.uploadFile({uploadId:params.uploadId,name:req.file.originalname,mime:req.file.mimetype},req.file.buffer)
|
||||||
.then((uID) => res.send(uID))
|
.then((uID) => res.send(uID))
|
||||||
.catch((stat) => {
|
.catch((stat) => {
|
||||||
res.status(stat.status);
|
res.status(stat.status);
|
||||||
|
|
|
@ -4,10 +4,6 @@
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
padding: 0px 0px 10px 0px;
|
padding: 0px 0px 10px 0px;
|
||||||
|
|
||||||
@media screen and (max-width: 500px) {
|
|
||||||
width:100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-family: "Fira Code", monospace;
|
font-family: "Fira Code", monospace;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
@ -77,6 +73,7 @@
|
||||||
position:relative;
|
position:relative;
|
||||||
|
|
||||||
background-color:#262626;
|
background-color:#262626;
|
||||||
|
transition-duration:250ms;
|
||||||
|
|
||||||
input[type=file] {
|
input[type=file] {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -98,6 +95,11 @@
|
||||||
padding:0px;
|
padding:0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transition-duration:250ms;
|
||||||
|
background-color:#292929;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
59
src/style/app/uploader/file.scss
Normal file
59
src/style/app/uploader/file.scss
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// should probably start using mixins for thingss like this
|
||||||
|
|
||||||
|
#uploadWindow {
|
||||||
|
.file {
|
||||||
|
background-color:#191919;
|
||||||
|
border: 1px solid gray;
|
||||||
|
padding: 10px;
|
||||||
|
overflow:clip;
|
||||||
|
position:relative;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0px;
|
||||||
|
font-weight:600;
|
||||||
|
width:calc( 100% - 20px );
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
background-color:#333333;
|
||||||
|
color:#DDDDDD;
|
||||||
|
border:none;
|
||||||
|
outline:none;
|
||||||
|
padding:5px;
|
||||||
|
position:relative;
|
||||||
|
|
||||||
|
width:100%;
|
||||||
|
transition-duration:250ms;
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
font-size:16px;
|
||||||
|
padding:10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonContainer {
|
||||||
|
display:flex;
|
||||||
|
column-gap:10px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex-basis: 50%;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding:5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploadingContainer {
|
||||||
|
color: #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hitbox {
|
||||||
|
opacity:0;
|
||||||
|
position:absolute;
|
||||||
|
left:0px;
|
||||||
|
top:0px;
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
@use "uploader/add_new_files";
|
@use "uploader/add_new_files";
|
||||||
|
@use "uploader/file";
|
||||||
|
|
||||||
#uploadWindow {
|
#uploadWindow {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
|
@ -6,8 +7,13 @@
|
||||||
top:50%;
|
top:50%;
|
||||||
transform:translate(-50%,-50%);
|
transform:translate(-50%,-50%);
|
||||||
padding:10px 15px 10px 15px;
|
padding:10px 15px 10px 15px;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
width:350px;
|
width:350px;
|
||||||
|
@media screen and (min-width:500px) {
|
||||||
|
max-height: calc( 100% - 80px );
|
||||||
|
}
|
||||||
|
|
||||||
background-color:#222222;
|
background-color:#222222;
|
||||||
color:#ddd;
|
color:#ddd;
|
||||||
|
@ -30,6 +36,32 @@
|
||||||
font-family: "Inconsolata", monospace;
|
font-family: "Inconsolata", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uploadContainer {
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor:pointer;
|
||||||
|
background-color:#393939;
|
||||||
|
color:#DDDDDD;
|
||||||
|
border:none;
|
||||||
|
outline:none;
|
||||||
|
padding:5px;
|
||||||
|
transition-duration: 250ms;
|
||||||
|
/*overflow:clip;*/
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
font-size:16px;
|
||||||
|
padding:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transition-duration: 250ms;
|
||||||
|
background-color:#434343;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 500px) {
|
@media screen and (max-width: 500px) {
|
||||||
width: calc( 100% - 20px );
|
width: calc( 100% - 20px );
|
||||||
height: calc( 100% - 20px );
|
height: calc( 100% - 20px );
|
||||||
|
|
|
@ -1,19 +1,145 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { _void } from "./transition/_void.js";
|
||||||
// stats
|
import { fade } from "svelte/transition";
|
||||||
|
import { circIn, circOut } from "svelte/easing";
|
||||||
|
|
||||||
import AttachmentZone from "./uploader/AttachmentZone.svelte";
|
import AttachmentZone from "./uploader/AttachmentZone.svelte";
|
||||||
|
|
||||||
|
// stats
|
||||||
|
|
||||||
let ServerStats = {}
|
let ServerStats = {}
|
||||||
|
|
||||||
fetch("/server").then(async (data) => {
|
let refresh_stats = () => {
|
||||||
ServerStats = await data.json()
|
fetch("/server").then(async (data) => {
|
||||||
})
|
ServerStats = await data.json()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh_stats()
|
||||||
|
|
||||||
// uploads
|
// uploads
|
||||||
|
|
||||||
let attachmentZone;
|
let attachmentZone;
|
||||||
let uploads = new Map()
|
let uploads = {};
|
||||||
|
let uploadInProgress = false;
|
||||||
|
|
||||||
|
let handle_file_upload = (ev) => {
|
||||||
|
if (ev.detail.type == "clone") {
|
||||||
|
uploads[Math.random().toString().slice(2)] = {
|
||||||
|
type: "clone",
|
||||||
|
name: ev.detail.url,
|
||||||
|
url: ev.detail.url,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
uploadId: ""
|
||||||
|
},
|
||||||
|
|
||||||
|
uploadStatus:{
|
||||||
|
fileId: null,
|
||||||
|
error: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uploads = uploads
|
||||||
|
} else if (ev.detail.type == "upload") {
|
||||||
|
ev.detail.files.forEach((v,x) => {
|
||||||
|
uploads[Math.random().toString().slice(2)] = {
|
||||||
|
type: "upload",
|
||||||
|
name: v.name,
|
||||||
|
file: v,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
uploadId: ""
|
||||||
|
},
|
||||||
|
|
||||||
|
uploadStatus:{
|
||||||
|
fileId: null,
|
||||||
|
error: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
uploads = uploads
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let handle_fetch_promise = (x,prom) => {
|
||||||
|
return prom.then(async (res) => {
|
||||||
|
let txt = await res.text()
|
||||||
|
if (txt.startsWith("[err]")) uploads[x].uploadStatus.error = txt;
|
||||||
|
else {
|
||||||
|
uploads[x].uploadStatus.fileId = txt;
|
||||||
|
|
||||||
|
refresh_stats();
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
uploads[x].uploadStatus.error = err.toString();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let upload_files = () => {
|
||||||
|
uploadInProgress = true
|
||||||
|
|
||||||
|
// go through all files
|
||||||
|
Object.entries(uploads).forEach(([x,v]) => {
|
||||||
|
switch(v.type) {
|
||||||
|
case "upload":
|
||||||
|
let fd = new FormData()
|
||||||
|
fd.append("file",v.file)
|
||||||
|
|
||||||
|
handle_fetch_promise(x,fetch("/upload",{
|
||||||
|
headers: {
|
||||||
|
"monofile-params": JSON.stringify(v.params)
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
body: fd
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
case "clone":
|
||||||
|
handle_fetch_promise(x,fetch("/clone",{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
url: v.url,
|
||||||
|
...v.params
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// animation
|
||||||
|
|
||||||
|
function padding_scaleY(node, { duration, easingFunc, padY, padX, op }) {
|
||||||
|
let rect = node.getBoundingClientRect()
|
||||||
|
|
||||||
|
return {
|
||||||
|
duration: duration||300,
|
||||||
|
css: t => {
|
||||||
|
let eased = (easingFunc || circOut)(t)
|
||||||
|
|
||||||
|
return `
|
||||||
|
height: ${eased*(rect.height-(padY||0))}px;
|
||||||
|
${padX&&padY ? `padding: ${(eased)*(padY)}px ${(padX)}px;` : ""}
|
||||||
|
${op ? `opacity: ${eased};` : ""}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fileTransition(node) {
|
||||||
|
return {
|
||||||
|
duration: 300,
|
||||||
|
css: t => {
|
||||||
|
let eased = circOut(t)
|
||||||
|
|
||||||
|
return `
|
||||||
|
height: ${eased*(node.offsetHeight-20)}px;
|
||||||
|
padding: ${eased*10}px 10px;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -23,21 +149,75 @@
|
||||||
<span class="number">{ServerStats.version ? `v${ServerStats.version}` : "•••"}</span>  — Discord based file sharing
|
<span class="number">{ServerStats.version ? `v${ServerStats.version}` : "•••"}</span>  — Discord based file sharing
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div style:min-height="10px" />
|
||||||
{#each Array.from(uploads.entries()) as upload (upload[0])}
|
|
||||||
<div class="file">
|
<!-- consider splitting the file thing into a separate element maybe -->
|
||||||
|
|
||||||
|
<div class="uploadContainer">
|
||||||
|
{#each Object.entries(uploads) as upload (upload[0])}
|
||||||
|
<!-- container to allow for animate directive -->
|
||||||
|
<div>
|
||||||
|
<div class="file" transition:fileTransition style:border={upload[1].uploadStatus.error ? "1px solid #BB7070" : ""}>
|
||||||
|
<h2>{upload[1].name} <span style:color="#999999" style:font-weight="400">{upload[1].type}{@html upload[1].type == "upload" ? ` (${Math.round(upload[1].file.size/1048576)}MB)` : ""}</span></h2>
|
||||||
|
|
||||||
|
{#if upload[1].maximized && !uploadInProgress}
|
||||||
|
<div transition:padding_scaleY|local>
|
||||||
|
<div style:height="10px" />
|
||||||
|
<input placeholder="custom id" type="text" bind:value={ uploads[upload[0]].params.uploadId }>
|
||||||
|
<div style:height="10px" />
|
||||||
|
<div class="buttonContainer">
|
||||||
|
<button on:click={() => {delete uploads[upload[0]];uploads=uploads;}}>
|
||||||
|
delete
|
||||||
|
</button>
|
||||||
|
<button on:click={() => uploads[upload[0]].maximized = false}>
|
||||||
|
minimize
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else if !uploadInProgress}
|
||||||
|
<button on:click={() => uploads[upload[0]].maximized = true} class="hitbox"></button>
|
||||||
|
{:else}
|
||||||
|
<div transition:padding_scaleY|local class="uploadingContainer">
|
||||||
|
{#if !upload[1].uploadStatus.fileId}
|
||||||
|
<p in:fade={{duration:300, delay:400, easingFunc:circOut}} out:padding_scaleY={{easingFunc:circIn,op:true}}>{upload[1].uploadStatus.error ?? "Uploading..."}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if upload[1].uploadStatus.fileId}
|
||||||
|
<div style:height="10px" transition:padding_scaleY />
|
||||||
|
{#if !upload[1].viewingUrl}
|
||||||
|
<div class="buttonContainer" out:_void in:_void={{easingFunc:circOut}}>
|
||||||
|
<button on:click={() => uploads[upload[0]].viewingUrl = true}>
|
||||||
|
view url
|
||||||
|
</button>
|
||||||
|
<button on:click={() => navigator.clipboard.writeText(`https://${window.location.host}/download/${upload[1].uploadStatus.fileId}`)}>
|
||||||
|
copy url
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="buttonContainer" out:_void in:_void={{easingFunc:circOut}}>
|
||||||
|
<input type="text" readonly value={`https://${window.location.host}/download/${upload[1].uploadStatus.fileId}`} style:flex-basis="80%">
|
||||||
|
<button on:click={() => uploads[upload[0]].viewingUrl = false} style:flex-basis="20%">
|
||||||
|
ok
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div style:height="10px" transition:padding_scaleY />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style:height="10px" />
|
|
||||||
|
|
||||||
{#if uploads.size < 1}
|
{#if uploadInProgress == false}
|
||||||
<AttachmentZone bind:this={attachmentZone}/>
|
<AttachmentZone bind:this={attachmentZone} on:addFiles={handle_file_upload}/>
|
||||||
|
<div style:min-height="10px" transition:padding_scaleY />
|
||||||
|
{#if Object.keys(uploads).length > 0}
|
||||||
|
<button in:padding_scaleY={{easingFunc:circOut}} out:_void on:click={upload_files}>upload</button>
|
||||||
|
<div transition:_void style:min-height="10px" />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div style:height="10px" />
|
|
||||||
|
|
||||||
<p style:color="#999999" style:text-align="center">
|
<p style:color="#999999" style:text-align="center">
|
||||||
Hosting <span class="number" style:font-weight="600">{ServerStats.files || "•••"}</span> files
|
Hosting <span class="number" style:font-weight="600">{ServerStats.files || "•••"}</span> files
|
||||||
|
@ -47,7 +227,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p style:color="#999999" style:text-align="center" style:font-size="12px">
|
<p style:color="#999999" style:text-align="center" style:font-size="12px">
|
||||||
Made with ❤ by <a href="https://github.com/nbitzz" style:font-size="12px">@nbitzz</a> — <a href="https://github.com/nbitzz/monofile" style:font-size="12px">source</a>
|
Made with {Math.floor(Math.random()*10)==0 ? "🐟" : "❤"} by <a href="https://github.com/nbitzz" style:font-size="12px">@nbitzz</a> — <a href="https://github.com/nbitzz/monofile" style:font-size="12px">source</a>
|
||||||
</p>
|
</p>
|
||||||
<div style:height="10px" />
|
<div style:height="10px" />
|
||||||
</div>
|
</div>
|
20
src/svelte/elem/transition/_void.js
Normal file
20
src/svelte/elem/transition/_void.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { circIn, circOut } from "svelte/easing"
|
||||||
|
|
||||||
|
export function _void(node, { duration, easingFunc, op }) {
|
||||||
|
let rect = node.getBoundingClientRect()
|
||||||
|
|
||||||
|
return {
|
||||||
|
duration: duration||300,
|
||||||
|
css: t => {
|
||||||
|
let eased = (easingFunc || circIn)(t)
|
||||||
|
|
||||||
|
return `
|
||||||
|
white-space: nowrap;
|
||||||
|
height: ${(eased)*(rect.height)}px;
|
||||||
|
padding: 0px;
|
||||||
|
opacity:${eased};
|
||||||
|
overflow: clip;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
import { circIn, circOut } from "svelte/easing"
|
import { circIn, circOut } from "svelte/easing"
|
||||||
|
import { _void } from "../transition/_void"
|
||||||
|
|
||||||
let uploadTypes = {
|
let uploadTypes = {
|
||||||
files: 1,
|
files: 1,
|
||||||
|
@ -7,32 +9,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
let uploadType = undefined
|
let uploadType = undefined
|
||||||
|
let dispatch = createEventDispatcher();
|
||||||
function _void(node, { duration, easingFunc, op }) {
|
|
||||||
let rect = node.getBoundingClientRect()
|
|
||||||
|
|
||||||
return {
|
|
||||||
duration: duration||300,
|
|
||||||
css: t => {
|
|
||||||
let eased = (easingFunc || circIn)(t)
|
|
||||||
|
|
||||||
return `
|
|
||||||
white-space: nowrap;
|
|
||||||
height: ${(eased)*(rect.height)}px;
|
|
||||||
padding: 0px;
|
|
||||||
opacity:${eased};
|
|
||||||
overflow: clip;
|
|
||||||
`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// file upload
|
// file upload
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLInputElement
|
||||||
|
*/
|
||||||
let fileUpload;
|
let fileUpload;
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if (fileUpload) {
|
if (fileUpload) {
|
||||||
fileUpload.addEventListener("change",() => {
|
fileUpload.addEventListener("change",() => {
|
||||||
|
dispatch("addFiles",{
|
||||||
|
type: "upload",
|
||||||
|
files: Array.from(fileUpload.files)
|
||||||
|
})
|
||||||
uploadType = undefined
|
uploadType = undefined
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -53,6 +45,10 @@
|
||||||
if (cloneButton && cloneUrlTextbox) {
|
if (cloneButton && cloneUrlTextbox) {
|
||||||
cloneButton.addEventListener("click",() => {
|
cloneButton.addEventListener("click",() => {
|
||||||
if (cloneUrlTextbox.value) {
|
if (cloneUrlTextbox.value) {
|
||||||
|
dispatch("addFiles",{
|
||||||
|
type: "clone",
|
||||||
|
url: cloneUrlTextbox.value
|
||||||
|
})
|
||||||
uploadType = undefined;
|
uploadType = undefined;
|
||||||
} else {
|
} else {
|
||||||
cloneUrlTextbox.animate([
|
cloneUrlTextbox.animate([
|
||||||
|
|
Loading…
Reference in a new issue