refactor: ♻️ Use .replaceAll instead of /g

This commit is contained in:
Jack W. 2023-10-24 16:33:15 -04:00
parent 365aace294
commit b135dc79ea
No known key found for this signature in database
4 changed files with 137 additions and 101 deletions

View file

@ -1,14 +1,14 @@
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser"
import { IntentsBitField, Client } from "discord.js" import { IntentsBitField, Client } from "discord.js"
import express from "express" import express from "express"
import fs from "fs" import fs from "fs"
import bytes from "bytes"; import bytes from "bytes"
import ServeError from "./lib/errors" import ServeError from "./lib/errors"
import Files from "./lib/files" import Files from "./lib/files"
import * as auth from "./lib/auth" import * as auth from "./lib/auth"
import * as Accounts from "./lib/accounts" import * as Accounts from "./lib/accounts"
import { getAccount } from "./lib/middleware"; import { getAccount } from "./lib/middleware"
import APIRouter from "./routes/api" import APIRouter from "./routes/api"
@ -18,9 +18,9 @@ let pkg = require(`${process.cwd()}/package.json`)
let app = express() let app = express()
let config = require(`${process.cwd()}/config.json`) let config = require(`${process.cwd()}/config.json`)
app.use("/static/assets",express.static("assets")) app.use("/static/assets", express.static("assets"))
app.use("/static/style",express.static("out/style")) app.use("/static/style", express.static("out/style"))
app.use("/static/js",express.static("out/client")) app.use("/static/js", express.static("out/client"))
//app.use(bodyParser.text({limit:(config.maxDiscordFileSize*config.maxDiscordFiles)+1048576,type:["application/json","text/plain"]})) //app.use(bodyParser.text({limit:(config.maxDiscordFileSize*config.maxDiscordFiles)+1048576,type:["application/json","text/plain"]}))
@ -29,34 +29,41 @@ app.use(cookieParser())
// check for ssl, if not redirect // check for ssl, if not redirect
if (config.trustProxy) app.enable("trust proxy") if (config.trustProxy) app.enable("trust proxy")
if (config.forceSSL) { if (config.forceSSL) {
app.use((req,res,next) => { app.use((req, res, next) => {
if (req.protocol == "http") res.redirect(`https://${req.get("host")}${req.originalUrl}`) if (req.protocol == "http")
res.redirect(`https://${req.get("host")}${req.originalUrl}`)
else next() else next()
}) })
} }
app.get("/server",(req,res) => { app.get("/server", (req, res) => {
res.send(JSON.stringify({ res.send(
...config, JSON.stringify({
version:pkg.version, ...config,
files:Object.keys(files.files).length version: pkg.version,
})) files: Object.keys(files.files).length,
})
)
}) })
// funcs // funcs
// init data // init data
if (!fs.existsSync(__dirname+"/../.data/")) fs.mkdirSync(__dirname+"/../.data/") if (!fs.existsSync(__dirname + "/../.data/"))
fs.mkdirSync(__dirname + "/../.data/")
// discord // discord
let client = new Client({intents:[ let client = new Client({
IntentsBitField.Flags.GuildMessages, intents: [
IntentsBitField.Flags.MessageContent IntentsBitField.Flags.GuildMessages,
],rest:{timeout:config.requestTimeout}}) IntentsBitField.Flags.MessageContent,
],
rest: { timeout: config.requestTimeout },
})
let files = new Files(client,config) let files = new Files(client, config)
let apiRouter = new APIRouter(files) let apiRouter = new APIRouter(files)
apiRouter.loadAPIMethods().then(() => { apiRouter.loadAPIMethods().then(() => {
@ -66,88 +73,118 @@ apiRouter.loadAPIMethods().then(() => {
// index, clone // index, clone
app.get("/", function(req,res) { app.get("/", function (req, res) {
res.sendFile(process.cwd()+"/pages/index.html") res.sendFile(process.cwd() + "/pages/index.html")
}) })
// serve download page // serve download page
app.get("/download/:fileId", getAccount, (req,res) => { app.get("/download/:fileId", getAccount, (req, res) => {
let acc = res.locals.acc as Accounts.Account let acc = res.locals.acc as Accounts.Account
if (files.getFilePointer(req.params.fileId)) { if (files.getFilePointer(req.params.fileId)) {
let file = files.getFilePointer(req.params.fileId) let file = files.getFilePointer(req.params.fileId)
if (file.visibility == "private" && acc?.id != file.owner) { if (file.visibility == "private" && acc?.id != file.owner) {
ServeError(res,403,"you do not own this file") ServeError(res, 403, "you do not own this file")
return return
} }
fs.readFile(process.cwd()+"/pages/download.html",(err,buf) => { fs.readFile(process.cwd() + "/pages/download.html", (err, buf) => {
let fileOwner = file.owner ? Accounts.getFromId(file.owner) : undefined; let fileOwner = file.owner
if (err) {res.sendStatus(500);console.log(err);return} ? Accounts.getFromId(file.owner)
: undefined
if (err) {
res.sendStatus(500)
console.log(err)
return
}
res.send( res.send(
buf.toString() buf
.replace(/\$FileId/g,req.params.fileId) .toString()
.replace(/\$Version/g,pkg.version) .replaceAll("$FileId", req.params.fileId)
.replace(/\$FileSize/g,file.sizeInBytes ? bytes(file.sizeInBytes) : "[File size unknown]") .replaceAll("$Version", pkg.version)
.replace(/\$FileName/g, .replaceAll(
file.filename "$FileSize",
.replace(/\&/g,"&") file.sizeInBytes
.replace(/\</g,"&lt;") ? bytes(file.sizeInBytes)
.replace(/\>/g,"&gt;") : "[File size unknown]"
) )
.replace(/\<\!\-\-metaTags\-\-\>/g, .replaceAll(
( "$FileName",
file.mime.startsWith("image/") file.filename
? `<meta name="og:image" content="https://${req.headers.host}/file/${req.params.fileId}" />` .replaceAll("&", "&amp;")
: ( .replaceAll("<", "&lt;")
file.mime.startsWith("video/") .replaceAll(">", "&gt;")
? ( )
`<meta property="og:video:url" content="https://${req.headers.host}/cpt/${req.params.fileId}/video.${file.mime.split("/")[1] == "quicktime" ? "mov" : file.mime.split("/")[1]}" /> .replace(
<meta property="og:video:secure_url" content="https://${req.headers.host}/cpt/${req.params.fileId}/video.${file.mime.split("/")[1] == "quicktime" ? "mov" : file.mime.split("/")[1]}" /> "<!--metaTags-->",
(file.mime.startsWith("image/")
? `<meta name="og:image" content="https://${req.headers.host}/file/${req.params.fileId}" />`
: file.mime.startsWith("video/")
? `<meta property="og:video:url" content="https://${
req.headers.host
}/cpt/${req.params.fileId}/video.${
file.mime.split("/")[1] == "quicktime"
? "mov"
: file.mime.split("/")[1]
}" />
<meta property="og:video:secure_url" content="https://${
req.headers.host
}/cpt/${req.params.fileId}/video.${
file.mime.split("/")[1] == "quicktime"
? "mov"
: file.mime.split("/")[1]
}" />
<meta property="og:type" content="video.other"> <meta property="og:type" content="video.other">
<!-- honestly probably good enough for now --> <!-- honestly probably good enough for now -->
<meta property="twitter:image" content="0">` <meta property="twitter:image" content="0">` +
// quick lazy fix as a fallback // quick lazy fix as a fallback
// maybe i'll improve this later, but probably not. // maybe i'll improve this later, but probably not.
+ ((file.sizeInBytes||0) >= 26214400 ? ` ((file.sizeInBytes || 0) >= 26214400
? `
<meta property="og:video:width" content="1280"> <meta property="og:video:width" content="1280">
<meta property="og:video:height" content="720">` : "") <meta property="og:video:height" content="720">`
) : "")
: "" : "") +
) (fileOwner?.embed?.largeImage &&
file.visibility != "anonymous" &&
file.mime.startsWith("image/")
? `<meta name="twitter:card" content="summary_large_image">`
: "") +
`\n<meta name="theme-color" content="${
fileOwner?.embed?.color &&
file.visibility != "anonymous" &&
(req.headers["user-agent"] || "").includes(
"Discordbot"
)
? `#${fileOwner.embed.color}`
: "rgb(30, 33, 36)"
}">`
) )
+ ( .replace(
fileOwner?.embed?.largeImage && file.visibility!="anonymous" && file.mime.startsWith("image/") "<!--preview-->",
? `<meta name="twitter:card" content="summary_large_image">` file.mime.startsWith("image/")
: "" ? `<div style="min-height:10px"></div><img src="/file/${req.params.fileId}" />`
) : file.mime.startsWith("video/")
+ `\n<meta name="theme-color" content="${fileOwner?.embed?.color && file.visibility!="anonymous" && (req.headers["user-agent"]||"").includes("Discordbot") ? `#${fileOwner.embed.color}` : "rgb(30, 33, 36)"}">` ? `<div style="min-height:10px"></div><video src="/file/${req.params.fileId}" controls></video>`
) : file.mime.startsWith("audio/")
.replace(/\<\!\-\-preview\-\-\>/g,
file.mime.startsWith("image/")
? `<div style="min-height:10px"></div><img src="/file/${req.params.fileId}" />`
: (
file.mime.startsWith("video/")
? `<div style="min-height:10px"></div><video src="/file/${req.params.fileId}" controls></video>`
: (
file.mime.startsWith("audio/")
? `<div style="min-height:10px"></div><audio src="/file/${req.params.fileId}" controls></audio>` ? `<div style="min-height:10px"></div><audio src="/file/${req.params.fileId}" controls></audio>`
: "" : ""
)
) )
) .replaceAll(
.replace(/\$Uploader/g,!file.owner||file.visibility=="anonymous" ? "Anonymous" : `@${fileOwner?.username || "Deleted User"}`) "$Uploader",
!file.owner || file.visibility == "anonymous"
? "Anonymous"
: `@${fileOwner?.username || "Deleted User"}`
)
) )
}) })
} else { } else {
ServeError(res,404,"file not found") ServeError(res, 404, "file not found")
} }
}) })
/* /*
routes should be in this order: routes should be in this order:
@ -159,7 +196,7 @@ app.get("/download/:fileId", getAccount, (req,res) => {
// listen on 3000 or MONOFILE_PORT // listen on 3000 or MONOFILE_PORT
app.listen(process.env.MONOFILE_PORT || 3000,function() { app.listen(process.env.MONOFILE_PORT || 3000, function () {
console.log("Web OK!") console.log("Web OK!")
}) })

View file

@ -31,8 +31,8 @@ export default async function ServeError(
res.header("x-backup-status-message", reason) // glitch default nginx configuration res.header("x-backup-status-message", reason) // glitch default nginx configuration
res.send( res.send(
errorPage errorPage
.replace(/\$code/g,code.toString()) .replaceAll("$code",code.toString())
.replace(/\$text/g,reason) .replaceAll("$text",reason)
) )
} }
/** /**
@ -45,4 +45,4 @@ export function Redirect(res:Response,url:string) {
res.status(302) res.status(302)
res.header("Location",url) res.header("Location",url)
res.send() res.send()
} }

View file

@ -1,21 +1,16 @@
import { createTransport } from "nodemailer"; import { createTransport } from "nodemailer"
// required i guess // required i guess
require("dotenv").config() require("dotenv").config()
let let mailConfig = require(process.cwd() + "/config.json").mail,
mailConfig = transport = createTransport({
require( process.cwd() + "/config.json" ).mail, ...mailConfig.transport,
transport = auth: {
createTransport( user: process.env.MAIL_USER,
{ pass: process.env.MAIL_PASS,
...mailConfig.transport, },
auth: { })
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS
}
}
)
// lazy but // lazy but
@ -30,11 +25,15 @@ export function sendMail(to: string, subject: string, content: string) {
return transport.sendMail({ return transport.sendMail({
to, to,
subject, subject,
"from": mailConfig.send.from, from: mailConfig.send.from,
"html": `<span style="font-size:x-large;font-weight:600;">monofile <span style="opacity:0.5">accounts</span></span><br><span style="opacity:0.5">Gain control of your uploads.</span><hr><br>${ html: `<span style="font-size:x-large;font-weight:600;">monofile <span style="opacity:0.5">accounts</span></span><br><span style="opacity:0.5">Gain control of your uploads.</span><hr><br>${content
content .replaceAll(
.replace(/\<span username\>/g, `<span code><span style="color:#DDAA66;padding-right:3px;">@</span>`) "<span username>",
.replace(/\<span code\>/g,`<span style="font-family:monospace;padding:3px 5px 3px 5px;border-radius:8px;background-color:#1C1C1C;color:#DDDDDD;">`) `<span code><span style="color:#DDAA66;padding-right:3px;">@</span>`
}<br><br><span style="opacity:0.5">If you do not believe that you are the intended recipient of this email, please disregard this message.</span>` )
.replaceAll(
"<span code>",
`<span style="font-family:monospace;padding:3px 5px 3px 5px;border-radius:8px;background-color:#1C1C1C;color:#DDDDDD;">`
)}<br><br><span style="opacity:0.5">If you do not believe that you are the intended recipient of this email, please disregard this message.</span>`,
}) })
} }

View file

@ -12,7 +12,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */ /* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */ // "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */