From 3ef9eeaf4c9868155216dc86c515c6192961023b Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:12:44 -0800 Subject: [PATCH] this code actually sucks ass god bless anyone who reads this 1.2.1 i'll need to clean this shit up lmao --- .vscode/tasks.json | 2 +- README.md | 9 ++- assets/script/clone_file.js | 30 +++++++ assets/script/upload_file.js | 37 +++++++++ pages/{upload.html => base.html} | 117 ++++++++++++++++----------- pages/clone.html | 135 ------------------------------- src/index.ts | 73 ++++++++++++----- src/lib/SlashCommandManager.ts | 95 ---------------------- 8 files changed, 199 insertions(+), 299 deletions(-) create mode 100644 assets/script/clone_file.js create mode 100644 assets/script/upload_file.js rename pages/{upload.html => base.html} (59%) delete mode 100644 pages/clone.html delete mode 100644 src/lib/SlashCommandManager.ts diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 005ad9c..eacc6c8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,7 +12,7 @@ }, { "type": "shell", - "command":"npx tsc\nnode ./out/index.js\ndel ./server_out/* -Recurse", + "command":"npx tsc\nnode ./out/index.js\ndel ./out/* -Recurse", "group": { "kind": "build", "isDefault": true diff --git a/README.md b/README.md index 6ffa716..42019f8 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,11 @@ TOKEN=KILL-YOURSELF.NOW - [X] 1.1.2 fix file cloning with binary data - [X] 1.1.3 display current version on pages - [X] 1.1.4 serve /assets as static files & make /server endpoint -- [ ] 1.2.0 add simple moderation tools -- [ ] 1.2.1 prevent cloning of local/private ip addresses -- [ ] 1.3.0 allow custom file ids -- [ ] 1.4.0 accounts??? maybe?? (this probably won't happen) +- [X] 1.2.0 add file parameters section + custom ids +- [ ] 1.2.1 clean up this shitty code +- [ ] 1.2.2 add id locks, allowing you to set a key for a file that allows you to overwrite the file in the future +- [ ] 1.2.3 prevent cloning of local/private ip addresses +- [ ] 1.3.0 add simple moderation tools - [ ] 2.0.0 rewrite using theUnfunny's code as a base/rewrite using monofile-core also todo: monofile-core (written in eris) diff --git a/assets/script/clone_file.js b/assets/script/clone_file.js new file mode 100644 index 0000000..5b31f64 --- /dev/null +++ b/assets/script/clone_file.js @@ -0,0 +1,30 @@ +document.getElementById("uploadButton").addEventListener("click",() => { + let ask = prompt("Input a URL to clone.") + + if (ask) { + let opt = getOptionsForUploading() + updateBtnTxt("Requesting clone. Please wait.") + + let xmlhttp = new XMLHttpRequest() + + xmlhttp.addEventListener("error",function(e) { + updateBtnTxt(`Upload failed.
${e.toString()}`) + console.error(e) + }) + + xmlhttp.addEventListener("load",function() { + if (xmlhttp.status == 200) { + document.getElementById("CopyTB").value = `https://${location.hostname}/download/${xmlhttp.responseText}` + updateBtnTxt(`Upload complete.
Copy URL View URL`) + } else { + updateBtnTxt(`Upload failed.
${xmlhttp.responseText}`) + } + }) + + xmlhttp.open("POST","/clone") + xmlhttp.send(JSON.stringify({ + url: ask, + ...opt + })) + } +}) \ No newline at end of file diff --git a/assets/script/upload_file.js b/assets/script/upload_file.js new file mode 100644 index 0000000..9bf54c3 --- /dev/null +++ b/assets/script/upload_file.js @@ -0,0 +1,37 @@ +let FileUpload = document.createElement("input") +FileUpload.setAttribute("type","file") + +document.getElementById("uploadButton").addEventListener("click",() => FileUpload.click()) + +FileUpload.addEventListener("input",() => { + if (FileUpload.files[0]) { + let opt = getOptionsForUploading() + let file = FileUpload.files[0] + + updateBtnTxt("Uploading file. This may take a while, so stay put.") + + let xmlhttp = new XMLHttpRequest() + + xmlhttp.addEventListener("error",function(e) { + updateBtnTxt(`Upload failed.
${e.toString()}`) + console.error(e) + }) + + xmlhttp.addEventListener("load",function() { + if (xmlhttp.status == 200) { + document.getElementById("CopyTB").value = `https://${location.hostname}/download/${xmlhttp.responseText}` + updateBtnTxt(`Upload complete.
Copy URL View URL`) + } else { + updateBtnTxt(`Upload failed.
${xmlhttp.responseText}`) + } + }) + + let fd = new FormData() + fd.append('file',file) + + xmlhttp.open("POST","/upload") + xmlhttp.setRequestHeader("monofile-upload-id",opt.uploadId) + xmlhttp.send(fd) + + } +}) \ No newline at end of file diff --git a/pages/upload.html b/pages/base.html similarity index 59% rename from pages/upload.html rename to pages/base.html index c132c51..a495e1d 100644 --- a/pages/upload.html +++ b/pages/base.html @@ -37,31 +37,70 @@ left:50%; transform:translate(-50%,0); } - #uploadButton { - width:100%; - height:100%; - background-color: #66AAFF; + + button { color:black; font-weight:bold; border:none; position:absolute; - left:0px; - top:0px; font-size:20px; } - #uploadButton:hover { + + button:hover { border: 1px solid gray; } + + #uploadButton { + width:calc( 100% - 50px ); + height:100%; + background-color: #66AAFF; + left:0px; + top:0px; + } + + #optionsButton { + width:50px; + height:100%; + background-color: #AAAAAA; + left:calc( 100% - 50px ); + top:0px; + font-size:15px; + } + .note { padding:5px; position:relative; - width:calc( 100% - 60px ); + width:calc( 100% - 62px ); left:25px; border:1px solid #AAAAAAFF; border-radius: 8px; background-color: #AAAAAA66; } + /* this is horrible css lmao */ + + #options > input { + font-family:monospace; + width:250px; + font-size:14px; + border: 1px solid #777777; + background-color:#AAAAAA; + outline:none; + text-align:center; + } + + #options { + height:30px; + display:none; + } + + #customId { + position:absolute; + left:50%; + top:50%; + transform:translate(-50%,-50%) + } + @media only screen and (max-width: 450px) { #content { position:fixed; @@ -92,53 +131,41 @@
-
+
+ + +
+
+ +

Max filesize on instance: $MaxInstanceFilesize

-

made by nbitzz — githubclone from url...

+

made by nbitzz — github$otherText

+ + + + \ No newline at end of file diff --git a/pages/clone.html b/pages/clone.html deleted file mode 100644 index ad0cfa4..0000000 --- a/pages/clone.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - monofile - - - - - - - - - -
-

- monofile $Version -

-

Discord-based file sharing

-
- Before sharing files, please remember: - -
-
-
-

- Max filesize on instance: $MaxInstanceFilesize -

-

made by nbitzz — githubupload a file...

-
-
- - - - - \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 0735bc0..7530bfb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,7 @@ +/* + i really should split this up into different modules +*/ + import bodyParser from "body-parser" import multer, {memoryStorage} from "multer" import Discord, { IntentsBitField, Client } from "discord.js" @@ -55,9 +59,11 @@ let uploadFile = (settings:FileUploadSettings,fBuffer:Buffer) => { return new Promise(async (resolve,reject) => { if (!settings.name || !settings.mime) {reject({status:400,message:"missing name/mime"});return} - let uploadId = settings.uploadId || Math.random().toString().slice(2) + let uploadId = (settings.uploadId || Math.random().toString().slice(2)).toString(); + + if ((uploadId.match(/[A-Za-z0-9_\-]+/)||[])[0] != uploadId || uploadId.length > 30) {reject({status:400,message:"invalid id"});return} - if (files[uploadId]) {reject({status:500,message:"please try again"});return} + if (files[uploadId]) {reject({status:400,message:"a file with this id already exists"});return} if (settings.name.length > 128) {reject({status:400,message:"name too long"}); return} if (settings.name.length > 128) {reject({status:400,message:"mime too long"}); return} @@ -104,24 +110,45 @@ let uploadFile = (settings:FileUploadSettings,fBuffer:Buffer) => { } app.get("/", function(req,res) { - fs.readFile(__dirname+"/../pages/upload.html",(err,buf) => { + fs.readFile(__dirname+"/../pages/base.html",(err,buf) => { if (err) {res.sendStatus(500);console.log(err);return} - res.send(buf.toString().replace("$MaxInstanceFilesize",`${(config.maxDiscordFileSize*config.maxDiscordFiles)/1048576}MB`).replace(/\$Version/g,pkg.version)) + res.send( + buf.toString() + .replace("$MaxInstanceFilesize",`${(config.maxDiscordFileSize*config.maxDiscordFiles)/1048576}MB`) + .replace(/\$Version/g,pkg.version) + .replace(/\$Handler/g,"upload_file") + .replace(/\$UploadButtonText/g,"Upload file") + .replace(/\$otherPath/g,"/clone") + .replace(/\$otherText/g,"clone from url...") + ) }) }) app.get("/clone", function(req,res) { - fs.readFile(__dirname+"/../pages/clone.html",(err,buf) => { + fs.readFile(__dirname+"/../pages/base.html",(err,buf) => { if (err) {res.sendStatus(500);console.log(err);return} - res.send(buf.toString().replace("$MaxInstanceFilesize",`${(config.maxDiscordFileSize*config.maxDiscordFiles)/1048576}MB`).replace(/\$Version/g,pkg.version)) + res.send( + buf.toString() + .replace("$MaxInstanceFilesize",`${(config.maxDiscordFileSize*config.maxDiscordFiles)/1048576}MB`) + .replace(/\$Version/g,pkg.version) + .replace(/\$Handler/g,"clone_file") + .replace(/\$UploadButtonText/g,"Input a URL") + .replace(/\$otherPath/g,"/") + .replace(/\$otherText/g,"upload file...") + ) }) }) app.post("/upload",multerSetup.single('file'),async (req,res) => { if (req.file) { - uploadFile({name:req.file.originalname,mime:req.file.mimetype},req.file.buffer) - .then((uID) => res.send(uID)) - .catch((stat) => {res.status(stat.status);res.send(`[err] ${stat.message}`)}) + try { + uploadFile({name:req.file.originalname,mime:req.file.mimetype,uploadId:req.header("monofile-upload-id")},req.file.buffer) + .then((uID) => res.send(uID)) + .catch((stat) => {res.status(stat.status);res.send(`[err] ${stat.message}`)}) + } catch { + res.status(400) + res.send("[err] bad request") + } } else { res.status(400) res.send("[err] bad request") @@ -129,14 +156,24 @@ app.post("/upload",multerSetup.single('file'),async (req,res) => { }) app.post("/clone",(req,res) => { - axios.get(req.body,{responseType:"arraybuffer"}).then((data:AxiosResponse) => { - uploadFile({name:req.body.split("/")[req.body.split("/").length-1] || "generic",mime:data.headers["content-type"]},Buffer.from(data.data)) - .then((uID) => res.send(uID)) - .catch((stat) => {res.status(stat.status);res.send(`[err] ${stat.message}`)}) - }).catch((err) => { - res.status(400) - res.send(`[err] failed to fetch data`) - }) + try { + let j = JSON.parse(req.body) + if (!j.url) { + res.status(400) + res.send("[err] invalid url") + } + axios.get(j.url,{responseType:"arraybuffer"}).then((data:AxiosResponse) => { + uploadFile({name:req.body.split("/")[req.body.split("/").length-1] || "generic",mime:data.headers["content-type"],uploadId:j.uploadId},Buffer.from(data.data)) + .then((uID) => res.send(uID)) + .catch((stat) => {res.status(stat.status);res.send(`[err] ${stat.message}`)}) + }).catch((err) => { + res.status(400) + res.send(`[err] failed to fetch data`) + }) + } catch { + res.status(500) + res.send("[err] an error occured") + } }) app.get("/download/:fileId",(req,res) => { @@ -192,8 +229,6 @@ app.get("*",(req,res) => { ThrowError(res,404,"Page not found.") }) - - client.on("ready",() => { console.log("Discord OK!") diff --git a/src/lib/SlashCommandManager.ts b/src/lib/SlashCommandManager.ts deleted file mode 100644 index 3236ace..0000000 --- a/src/lib/SlashCommandManager.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - hi, this is a port of nbitzz/theUnfunny@fb57d8d65f - so the code is pretty bad - (but let's be real, all of my code is bad lmao) -*/ - -import { Client, SlashCommandBuilder, Routes, ChatInputCommandInteraction } from "discord.js"; - -export class SlashCommand { - readonly builder: SlashCommandBuilder|Omit|Omit - readonly assetPath: string - readonly type:string = "SCM.SlashCommand" - action?: (interaction:ChatInputCommandInteraction) => Promise - - ephmeralReply?:boolean - allowInDMs?:boolean - - constructor(command:SlashCommandBuilder|Omit|Omit) { - this.builder = command - this.assetPath = `${process.cwd()}/assets/commands/${command.name}/` - } -} - -export class SlashCommandManager { - private commands:SlashCommand[] = [] - private readonly client: Client - readonly type:string = "SCM.SlashCommandManager" - - constructor(client: Client) { - this.client = client - } - - /** - * @description Register slash commands - */ - register() { - return new Promise(async (resolve,reject) => { - console.log("[SlashCommandManager] Registering commands...") - - if (this.client.user) { - this.commands.forEach((e) => { - e.builder.setDMPermission(e.allowInDMs) - }) - - let result = await this.client.rest.put( - Routes.applicationCommands(this.client.user.id), - { body: this.commands.map(e => e.builder.toJSON()) } - ) - - console.log(`[SlashCommandManager] Slash commands registered.`) - resolve(result) - } else { - console.error("[SlashCommandManager] Not logged in") - reject("Not logged in") - } - }) - } - - /** - * @description Process a command - */ - - call(int:ChatInputCommandInteraction) { - let command = this.commands.find(e => e.builder.name == int.commandName) - if (command && command.action) { - int.deferReply({ - ephemeral:command.ephmeralReply - }).then(() => { - if (command && command.action) { - command.action(int).catch((err) => { - // error handling - int.editReply({ - embeds:[ - {description:"Oops, something broke. Maybe try that again?",color:0xff0000} - ] - }) - console.error(err) - }) - } - }) - - } - } - - /** - * @description Add a slash command to the manager - */ - add(command:SlashCommand) { - this.commands.push(command) - } -} - -// type guard - -export let isSlashCommand = (sc: any): sc is SlashCommand => {return sc&&sc.type=="SCM.SlashCommand"} \ No newline at end of file