1905 lines
63 KiB
JavaScript
1905 lines
63 KiB
JavaScript
const express = require("express");
|
|
const app = express();
|
|
const cookieParser = require("cookie-parser");
|
|
const cors = require("cors");
|
|
|
|
const config = require("./config.json");
|
|
const utils = require("./utils.js");
|
|
|
|
const zxcvbn = require("zxcvbn");
|
|
const bcrypt = require("bcrypt");
|
|
const du = require("du");
|
|
const ffmpegStatic = require("ffmpeg-static");
|
|
const {spawn} = require("child_process");
|
|
|
|
const formidable = require("formidable");
|
|
const {MongoClient} = require("mongodb");
|
|
const client = new MongoClient(config["db-url"], {useUnifiedTopology: true});
|
|
const fs = require("fs");
|
|
const hcaptcha = require("hcaptcha");
|
|
|
|
const sd = require("showdown");
|
|
const mk = new sd.Converter();
|
|
const istor = require("is-tor");
|
|
|
|
if (!config["media-folder"].startsWith("/")) config["media-folder"] = `${__dirname}/${config["media-folder"]}`;
|
|
if (config?.["remux"]?.["folder"] && !config?.["remux"]?.["folder"].startsWith("/")) config["remux"]["folder"] = `${__dirname}/${config?.["remux"]?.["folder"]}`;
|
|
|
|
app.set("view engine", "ejs");
|
|
app.use(cookieParser());
|
|
app.use(cors());
|
|
app.use(express.static("static/"));
|
|
if (config?.["remux"]?.["folder"]) app.use("/transcoded/", express.static(config?.["remux"]?.["folder"]));
|
|
app.use("/temp", express.static(`temp/`));
|
|
|
|
app.use(async function(req, res, next) {
|
|
let db = client.db("mediahost");
|
|
let blocks = db.collection("blockedIPs");
|
|
let userIp = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
let ip = await blocks.findOne({ip: userIp});
|
|
|
|
if (ip == null) next();
|
|
else {
|
|
let isBlocked = utils.isBlockedHere(ip.status, req.path);
|
|
|
|
if (!ip?.status) ip.status = "*";
|
|
if (!ip?.reason) ip.reason = "of your continued abuse of our website";
|
|
|
|
if (isBlocked) {
|
|
res.render("pages/blocked", {config: config, account: null, status: utils.toBlockedStatus(ip.status), reason: ip.reason, ip: ip.ip});
|
|
return;
|
|
} else next();
|
|
}
|
|
});
|
|
|
|
app.use("/f/:id/raw", async function(req, res, next) {
|
|
try {
|
|
let id = req.params.id;
|
|
let loc = `${config["media-folder"]}${id}/${fs.readdirSync(`${config["media-folder"]}${id}`)[0]}`;
|
|
if (fs.existsSync(loc)) {
|
|
let db = client.db("mediahost");
|
|
let file = await (await db.collection("uploads")).findOne({id: id});
|
|
if (file.mime.startsWith("text/")) res.setHeader("content-type", "text/plain");
|
|
if (file.mime.startsWith("image/svg")) res.setHeader("content-disposition", `attachment; filename="${fs.readdirSync(`${config["media-folder"]}${id}`)[0]}"`);
|
|
res.sendFile(loc);
|
|
} else {
|
|
next();
|
|
}
|
|
} catch(err) {
|
|
next();
|
|
}
|
|
});
|
|
|
|
app.use("/f/:id/dl", function(req, res, next) {
|
|
try {
|
|
let id = req.params.id;
|
|
let loc = `${config["media-folder"]}${id}/${fs.readdirSync(`${config["media-folder"]}${id}`)[0]}`;
|
|
if (fs.existsSync(loc)) {
|
|
res.setHeader("content-disposition", `attachment; filename="${fs.readdirSync(`${config["media-folder"]}${id}`)[0]}"`);
|
|
res.sendFile(loc);
|
|
} else {
|
|
next();
|
|
}
|
|
} catch(err) {
|
|
next();
|
|
}
|
|
});
|
|
|
|
if (!fs.existsSync(config["media-folder"])) fs.mkdirSync(config["media-folder"])
|
|
if (!fs.existsSync(config?.["remux"]?.["folder"])) fs.mkdirSync(config?.["remux"]?.["folder"])
|
|
|
|
start();
|
|
|
|
app.get("/", async function (req, res, next) {
|
|
let db = client.db("mediahost");
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
let uploads = await (await (await db.collection("uploads").find({})).toArray()).length;
|
|
let size = utils.humanSize((await du(config["media-folder"])));
|
|
|
|
res.render("pages/home", {config: config, account: acc, message: utils.toMessage(req.query["from"]), fileCount: uploads, fileSize: size});
|
|
});
|
|
|
|
app.get("/register", async function (req, res, next) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && config["allow-signup"] == true) {
|
|
res.render("pages/register", {config: config, account: acc});
|
|
} else {
|
|
res.render("pages/not-allowed", {config: config, account: acc})
|
|
}
|
|
});
|
|
|
|
app.post("/register", async function (req, res, next) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
|
|
const form = formidable();
|
|
let db = client.db("mediahost");
|
|
let collection = await db.collection("accounts");
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (config["allow-signup"] == false || acc !== null && acc !== undefined) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
|
|
form.parse(req, async function(err, fields, files) {
|
|
if (err) {
|
|
res.render("pages/register", {config: config, err: err});
|
|
} else {
|
|
if (fields.username && fields.password) {
|
|
if (config["captcha"]["enabled"] == true && config["captcha"]["show-at-signup"]) {
|
|
if (!fields["h-captcha-response"]) {
|
|
res.render("pages/register", {config: config, err: "CAPTCHA needs to be solved."});
|
|
return;
|
|
} else {
|
|
let h = await hcaptcha.verify(config["captcha"]["secret"], fields["h-captcha-response"]);
|
|
if (!h.success) {
|
|
res.render("pages/register", {config: config, err: "CAPTCHA came back invalid."});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
let zx = zxcvbn(fields.password);
|
|
if (zx.score >= 2.5) {
|
|
let p = bcrypt.hashSync(fields.password, 10);
|
|
let a = await collection.findOne({username: fields.username});
|
|
if (a !== null && fields.username !== "Anonymous") {
|
|
res.render("pages/register", {config: config, err: "Account already exists with that username."});
|
|
} else {
|
|
if (utils.validateUsername(fields.username)) {
|
|
let n = await collection.insertOne({username: fields.username, password: p, id: utils.generateString(10)});
|
|
if (n.acknowledged == true) {
|
|
res.redirect("/login?from=register");
|
|
} else {
|
|
res.render("pages/register", {config: config, err: "Insertion of account into MongoDB failed."});
|
|
}
|
|
} else {
|
|
res.render("pages/register", {config: config, err: "Invalid username, please try a different one."});
|
|
}
|
|
}
|
|
} else {
|
|
res.render("pages/register", {config: config, err: "The password scored below 2.5 on zxcvbn. Give a better password."});
|
|
}
|
|
} else {
|
|
res.render("pages/register", {config: config, err: "A username and password is required to register."});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
app.get("/signup-with-code", async function (req, res, next) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
res.render("pages/signup-code", {config: config, account: acc, code: req.query.code});
|
|
});
|
|
|
|
app.post("/signup-with-code", async function (req, res, next) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
|
|
const form = formidable();
|
|
let db = client.db("mediahost");
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
let collection = await db.collection("accounts");
|
|
let signup = await db.collection("codes");
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) {
|
|
res.render("pages/signup-code", {config: config, err: err, code: req.query.code});
|
|
} else {
|
|
if (fields.username && fields.password && fields["signup-code"]) {
|
|
if (config["captcha"]["enabled"] == true && config["captcha"]["show-at-signup"]) {
|
|
if (!fields["h-captcha-response"]) {
|
|
res.render("pages/signup-code", {config: config, err: "CAPTCHA needs to be solved.", code: req.query.code, account: acc});
|
|
return;
|
|
} else {
|
|
let h = await hcaptcha.verify(config["captcha"]["secret"], fields["h-captcha-response"]);
|
|
if (!h.success) {
|
|
res.render("pages/signup-code", {config: config, err: "CAPTCHA came back invalid.", code: req.query.code, account: acc});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
let zx = zxcvbn(fields.password);
|
|
if (zx.score >= 2.5) {
|
|
let p = bcrypt.hashSync(fields.password, 10);
|
|
let a = await collection.findOne({username: fields.username});
|
|
if (a !== null && fields.username !== "Anonymous") {
|
|
res.render("pages/signup-code", {config: config, err: "Account already exists with that username.", code: req.query.code, account: acc});
|
|
} else {
|
|
let code = await signup.findOne({code: fields["signup-code"]});
|
|
if (code == null) {
|
|
res.render("pages/signup-code", {config: config, err: "Signup code is invalid.", account: acc});
|
|
} else {
|
|
if (utils.validateUsername(fields.username)) {
|
|
let t1 = await collection.insertOne({username: fields.username, password: p, id: utils.generateString(10)});
|
|
|
|
if (t1.acknowledged == true) {
|
|
await signup.findOneAndDelete({code: fields["signup-code"]});
|
|
res.redirect("/login?from=register");
|
|
} else {
|
|
res.render("pages/signup-code", {config: config, err: "Insertion of the new account into MongoDB database have failed.", account: acc});
|
|
}
|
|
} else {
|
|
res.render("pages/signup-code", {config: config, err: "Invalid username, please try a different one."});
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
res.render("pages/signup-code", {config: config, err: "The password scored below 2.5 on zxcvbn. Give a better password.", code: req.query.code, account: acc});
|
|
}
|
|
} else {
|
|
res.render("pages/signup-code", {config: config, err: "A signup code, username, and password is required to register.", code: req.query.code, account: acc});
|
|
}
|
|
}
|
|
});
|
|
})
|
|
|
|
app.get("/login", async function (req, res, next) {
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc == null) {
|
|
res.render("pages/login", {config: config, account: acc, message: utils.toMessage(req.query["from"])});
|
|
} else {
|
|
res.redirect("/");
|
|
}
|
|
});
|
|
|
|
app.get("/logout", async function (req, res, next) {
|
|
if (req.cookies["session"]) res.clearCookie("session");
|
|
if (req.headers["referer"]) {
|
|
res.redirect(req.headers["referer"]);
|
|
} else {
|
|
res.redirect("/");
|
|
}
|
|
});
|
|
|
|
app.post("/login", function(req, res, next) {
|
|
if (req.cookies["session"]) {
|
|
res.clearCookie("session");
|
|
res.redirect("/login");
|
|
} else {
|
|
const form = formidable();
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) {
|
|
res.render("pages/login", {config: config, err: err});
|
|
} else {
|
|
if (fields.username && fields.password) {
|
|
if (config["captcha"]["enabled"] == true && config["captcha"]["show-at-login"]) {
|
|
if (!fields["h-captcha-response"]) {
|
|
res.render("pages/login", {config: config, err: "CAPTCHA needs to be solved.", message: null});
|
|
return;
|
|
} else {
|
|
let h = await hcaptcha.verify(config["captcha"]["secret"], fields["h-captcha-response"]);
|
|
if (!h.success) {
|
|
res.render("pages/login", {config: config, err: "CAPTCHA came back invalid.", message: null});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
let db = client.db("mediahost");
|
|
let collection = await db.collection("accounts");
|
|
let a = await collection.findOne({username: fields.username});
|
|
if (a == null) {
|
|
res.render("pages/login", {config: config, err: "Username doesn't exist in our database.", message: null});
|
|
} else {
|
|
|
|
let c = bcrypt.compareSync(fields.password, a.password);
|
|
if (c == true) {
|
|
if (!a.session) {
|
|
let s = utils.generateString(50)
|
|
let acc = a;
|
|
acc.session = s;
|
|
res.cookie("session", s);
|
|
await collection.findOneAndReplace({_id: a._id}, acc);
|
|
res.redirect("/");
|
|
} else {
|
|
res.cookie("session", a.session);
|
|
res.redirect("/");
|
|
}
|
|
} else {
|
|
res.render("pages/login", {config: config, err: "Password is incorrect.", message: null});
|
|
}
|
|
}
|
|
} else {
|
|
res.render("pages/login", {config: config, err: "A username and password is required to login.", message: null});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
app.get("/dummy", function(req, res, next) {
|
|
res.send({marco: "polo"});
|
|
});
|
|
|
|
app.get("/upload", async function (req, res, next) {
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (config["allow-anon-uploads"] == false && acc == null) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
} else {
|
|
if (acc == null) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
}
|
|
|
|
if (acc == null && config["max-anon-file-size"] !== 0) res.render("pages/upload", {config: config, account: acc, maxsize: utils.humanSize(config["max-anon-file-size"])});
|
|
else res.render("pages/upload", {config: config, account: acc, maxsize: utils.humanSize(config["max-file-size"])});
|
|
}
|
|
});
|
|
|
|
app.post("/upload", async function (req, res, next) {
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
let form;
|
|
if (acc == null && config["max-anon-file-size"] !== 0) {
|
|
form = formidable({maxFileSize: config["max-anon-file-size"], allowEmptyFiles: false, multiples: true});
|
|
} else {
|
|
form = formidable({maxFileSize: config["max-file-size"], allowEmptyFiles: false, multiples: true});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (!config["allow-anon-uploads"] && acc == null) {
|
|
if (req.query["json"] !== "1") res.render("pages/not-allowed", {config: config, account: null});
|
|
else {
|
|
res.send({
|
|
success: false,
|
|
err: "Anonymous uploads are not allowed on this instance."
|
|
})
|
|
}
|
|
return;
|
|
}
|
|
|
|
form.parse(req, async function(err, fields, files) {
|
|
if (err) {
|
|
let error;
|
|
|
|
if (err.httpCode && !err.message) error = `HTTP Error Code ${err.httpCode}`;
|
|
else error = (err.message || err);
|
|
|
|
if (req.query["json"] !== "1") res.render("pages/upload", {config: config, err: error, maxsize: utils.humanSize(config["max-file-size"]), account: acc});
|
|
else {
|
|
res.send({
|
|
success: false,
|
|
err: error
|
|
});
|
|
}
|
|
} else {
|
|
if (!files.file) {
|
|
if (req.query["json"] !== "1") res.render("pages/upload", {config: config, account: acc, err: "File was empty.", maxsize: utils.humanSize(config["max-file-size"])});
|
|
else {
|
|
res.send({
|
|
success: false,
|
|
err: "File was empty."
|
|
});
|
|
}
|
|
} else {
|
|
try {
|
|
let id = utils.generateString(5);
|
|
//console.log(`[media-host] Uploaded file to "${id}".`);
|
|
fs.mkdirSync(`${config["media-folder"]}${id}/`);
|
|
fs.copyFileSync(files.file.filepath, `${config["media-folder"]}${id}/${files.file.originalFilename}`);
|
|
let db = client.db("mediahost");
|
|
let col = await db.collection("uploads");
|
|
let type = utils.getType(files.file.mimetype);
|
|
|
|
let data = {
|
|
id,
|
|
direct: `/f/${id}/raw`,
|
|
name: files.file.originalFilename,
|
|
type,
|
|
size: fs.statSync(`${config["media-folder"]}${id}/${files.file.originalFilename}`).size,
|
|
humanSize: utils.humanSize(fs.statSync(`${config["media-folder"]}${id}/${files.file.originalFilename}`).size),
|
|
date: new Date().toISOString(),
|
|
privacy: (parseInt(fields.privacy) || 0),
|
|
mime: files.file.mimetype,
|
|
};
|
|
|
|
if (data.mime.startsWith("video/") && data.mime != "video/mp4" && data.mime != "video/webm") data.needsTranscode = true;
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
data.uploader = acc._id;
|
|
data.approved = true;
|
|
} else {
|
|
data.uploader = "Anonymous";
|
|
|
|
if (config["captcha"]["show-at-anon-upload"] == true) data.approved = false;
|
|
else data.approved = true;
|
|
}
|
|
|
|
if (data.uploader == "Anonymous" && config["captcha"]["enabled"] && config["captcha"]["show-at-anon-upload"] == true) {
|
|
col.insertOne(data);
|
|
|
|
if (data.uploader == "Anonymous" && config["store-anon-ips"] == true) {
|
|
data["ip"] = (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip);
|
|
}
|
|
|
|
res.send({
|
|
success: true,
|
|
requireCaptcha: true,
|
|
data
|
|
});
|
|
|
|
setTimeout(async function() {
|
|
let file = await col.findOne({id});
|
|
if (file.approved == false) await removeUpload(id);
|
|
}, 300000);
|
|
|
|
if (data.needsTranscode == true) initTranscode(id, data.mime);
|
|
return;
|
|
}
|
|
|
|
if (data.uploader == "Anonymous" && config["store-anon-ips"] == true) {
|
|
data["ip"] = (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip);
|
|
}
|
|
|
|
col.insertOne(data);
|
|
|
|
if (req.query["json"] !== "1") {
|
|
res.redirect(`/f/${id}`);
|
|
} else {
|
|
res.send({
|
|
success: true,
|
|
requireCaptcha: false,
|
|
data
|
|
});
|
|
}
|
|
|
|
if (data.needsTranscode == true) initTranscode(id, data.mime);
|
|
} catch(e) {
|
|
res.send({
|
|
success: false,
|
|
error: (e.stack || e.message || e.code || e)
|
|
})
|
|
}
|
|
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
app.post("/f/:id/confirm", async function(req, res) {
|
|
let form = formidable();
|
|
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) {
|
|
let error;
|
|
|
|
if (err.httpCode && !err.message) error = `HTTP Error Code ${err.httpCode}`;
|
|
else error = (err.message || err);
|
|
|
|
res.send({
|
|
success: false,
|
|
err: error
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
if (fields["h-captcha-response"]) {
|
|
let {success} = await hcaptcha.verify(config.captcha.secret, fields["h-captcha-response"]);
|
|
if (success) {
|
|
let db = client.db("mediahost");
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id: req.params.id});
|
|
|
|
if (file.approved == false) {
|
|
file.approved = true;
|
|
await files.findOneAndReplace({id: req.params.id}, file);
|
|
res.send({
|
|
success: true
|
|
});
|
|
} else {
|
|
res.send({
|
|
success: false,
|
|
err: "File already approved."
|
|
});
|
|
}
|
|
} else {
|
|
res.send({
|
|
success: false,
|
|
err: "Invalid CAPTCHA."
|
|
});
|
|
}
|
|
} else {
|
|
res.send({
|
|
success: false,
|
|
err: "Invalid CAPTCHA."
|
|
});
|
|
}
|
|
})
|
|
});
|
|
|
|
app.get("/f/:id", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id: req.params.id});
|
|
|
|
if (file == null) next();
|
|
else {
|
|
let fn = (file.name || file.direct.split("/")[file.direct.split("/").length - 1]);
|
|
let accName = (await accs.findOne({_id: file.uploader}));
|
|
|
|
if (accName == null) {
|
|
accName = "Anonymous";
|
|
} else {
|
|
accName = accName.username;
|
|
}
|
|
|
|
if (file.type !== "video" && file.type !== "audio" && file.type !== "image" && file.type !== "text") {
|
|
file.type = "generic";
|
|
await files.findOneAndReplace({id: req.params.id}, file);
|
|
}
|
|
|
|
if (file.direct.length !== 12) {
|
|
file.direct = `/f/${file.id}/raw`;
|
|
await files.findOneAndReplace({id: req.params.id}, file);
|
|
}
|
|
|
|
let ds = {
|
|
account: acc,
|
|
file: file,
|
|
config: config,
|
|
isOwned: isOwned(file, acc),
|
|
name: fn,
|
|
uploaderName: accName
|
|
};
|
|
|
|
if (file.type == "text") {
|
|
if (fs.existsSync(`${config["media-folder"]}${file.id}/${file.name}`)) {
|
|
ds.raw = (fs.readFileSync(`${config["media-folder"]}${file.id}/${file.name}`)?.toString() || "null");
|
|
} else {
|
|
ds.raw = "null";
|
|
}
|
|
}
|
|
|
|
res.render(`pages/file-types/${file.type}`, ds);
|
|
}
|
|
});
|
|
|
|
app.get("/d/:id", async function(req, res, next) {
|
|
res.redirect(`/f/${req.params.id}/delete`);
|
|
});
|
|
|
|
app.get("/f/:id/delete", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id: req.params.id});
|
|
if (file == null || acc == null) {
|
|
res.redirect("/");
|
|
} else {
|
|
let owned = isOwned(file, acc);
|
|
if (owned == false) {
|
|
res.redirect("/?from=no-permission");
|
|
} else {
|
|
res.render("pages/delete-file", {account: acc, config: config});
|
|
}
|
|
}
|
|
});
|
|
|
|
app.post("/f/:id/delete", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id: req.params.id});
|
|
if (file == null || acc == null) res.redirect("/?from=rejected-delete");
|
|
else {
|
|
if (fs.existsSync(`${config["media-folder"]}${file.id}`)) fs.rmSync(`${config["media-folder"]}${file.id}`, {recursive: true});
|
|
await files.findOneAndDelete({id: file.id});
|
|
let reports = db.collection("reports");
|
|
let reportList = await reports.find({upload: req.params.id}).toArray();
|
|
for (let a in reportList) {
|
|
let update = reportList[a];
|
|
delete update._id;
|
|
update.unread = false;
|
|
update.systemNotice = "Automatically marked as read, due to the file's deletion.";
|
|
await reports.findOneAndReplace({id: reportList[a].id}, update);
|
|
}
|
|
res.redirect("/?from=deleted-file");
|
|
}
|
|
});
|
|
|
|
app.get("/rn/:id", function (req, res, next) {
|
|
res.redirect(`/f/${req.params.id}/rename`);
|
|
});
|
|
|
|
app.get("/f/:id/rename", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id: req.params.id});
|
|
if (file == null || acc == null) next()
|
|
else {
|
|
let s = isOwned(file, acc);
|
|
if (s == false) {
|
|
res.redirect("/");
|
|
} else {
|
|
res.render("pages/rename-file", {account: acc, config: config, fn: file.name, err: null});
|
|
}
|
|
}
|
|
});
|
|
|
|
app.post("/f/:id/rename", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) {
|
|
res.clearCookie("session");
|
|
res.render("pages/not-allowed", {account: acc, config: config});
|
|
}
|
|
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id: req.params.id});
|
|
let form = formidable();
|
|
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) {
|
|
res.render("pages/rename-file", {account: acc, config: config, fn: file.name, err: err});
|
|
return;
|
|
}
|
|
|
|
if (fields.filename == "") {
|
|
res.render("pages/rename-file", {account: acc, config: config, fn: file.name, err: "Invalid file name."});
|
|
} else {
|
|
try {
|
|
fs.renameSync(`${config["media-folder"]}/${file.id}/${file.name}`, `${config["media-folder"]}/${file.id}/${fields.filename}`)
|
|
file.name = fields.filename;
|
|
await files.findOneAndReplace({id: file.id}, file);
|
|
res.redirect(`/f/${file.id}`);
|
|
} catch(err) {
|
|
res.render("pages/rename-file", {account: acc, config: config, fn: file.name, err: "Error renaming file."});
|
|
}
|
|
}
|
|
})
|
|
});
|
|
|
|
app.get("/u/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let a = await accs.findOne({username: req.params.user});
|
|
if (a == null) next();
|
|
else {
|
|
let p = {uploader: a._id};
|
|
if (acc == undefined || acc.id !== a.id && acc.admin !== true) {
|
|
p.privacy = 1;
|
|
}
|
|
let files = await db.collection("uploads");
|
|
let uploaded = await (await files.find(p).toArray()).reverse();
|
|
res.render("pages/user", {uploads: uploaded, account: acc, user: a, config: config});
|
|
}
|
|
});
|
|
|
|
app.get("/admin-dashboard", function(req, res, next) {
|
|
res.redirect("/admin");
|
|
});
|
|
|
|
app.get("/admin", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let files = await db.collection("uploads");
|
|
let reps = await db.collection("reports");
|
|
let ups = await (await files.find({}).toArray()).reverse().slice(0, 5);
|
|
let reg = await (await accs.find({}).toArray()).reverse().slice(0, 5);
|
|
let rep = await (await reps.find({unread: true}).toArray()).reverse();
|
|
res.render("pages/admin-panel", {config: config, account: acc, uploads: ups, register: reg, reports: rep, message: utils.toMessage(req.query["from"])});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/files", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let files = await db.collection("uploads");
|
|
let ups = await (await files.find({}).toArray()).reverse();
|
|
|
|
res.render("pages/admin-actions/all-files", {uploads: ups, account: acc, config: config});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/kill/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
let a = await accs.findOne({username: req.params.user});
|
|
|
|
if (a == null || acc.admin !== true) next();
|
|
else {
|
|
res.render("pages/admin-actions/delete-acc", {account: acc, config: config, user: a});
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/kill/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
let ac = await accs.findOne({username: req.params.user});
|
|
let u = await (await db.collection("uploads").find({uploader: ac._id})).toArray();
|
|
for (let a in u) {
|
|
removeUpload(u[a].id);
|
|
}
|
|
let a = await accs.findOneAndDelete({username: req.params.user});
|
|
if (a.ok == 1) {
|
|
if (ac.session == acc.session) {
|
|
res.clearCookie("session");
|
|
res.redirect("/?from=self-delete");
|
|
} else {
|
|
res.redirect("/admin-dashboard?from=kill-done");
|
|
}
|
|
} else {
|
|
res.end(a);
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/promote/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
let a = await accs.findOne({username: req.params.user});
|
|
if (a == null || acc.admin !== true) next();
|
|
else {
|
|
res.render("pages/admin-actions/promote-user", {account: acc, config: config, user: a});
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/promote/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
let ac = await accs.findOne({username: req.params.user});
|
|
ac.admin = true;
|
|
let a = await accs.findOneAndReplace({username: req.params.user}, ac);
|
|
if (a.ok == 1) {
|
|
if (ac.session == acc.session) res.clearCookie("session");
|
|
res.redirect("/admin-dashboard?from=promote-done");
|
|
} else {
|
|
res.send(a);
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/demote/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
let a = await accs.findOne({username: req.params.user});
|
|
if (a == null || acc.admin !== true) next();
|
|
else {
|
|
res.render("pages/admin-actions/demote-user", {account: acc, config: config, user: a});
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/demote/:user", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
let a = await accs.findOne({username: req.params.user});
|
|
if (a == null || acc.admin !== true) next();
|
|
else {
|
|
res.render("pages/admin-actions/block-ip", {account: acc, config: config});
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/block/ip", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
let obj = {config: config, account: acc};
|
|
if (req.query.ip) obj.ip = req.query.ip;
|
|
if (req.query.reason) obj.reason = req.query.reason;
|
|
|
|
res.render("pages/admin-actions/block-ip", obj);
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/block/ip", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
let form = formidable({maxFileSize: 0});
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
form.parse(req, async function(err, fields) {
|
|
let obj = {
|
|
config: config,
|
|
account: acc
|
|
};
|
|
|
|
if (req.query.ip) obj.ip = req.query.ip;
|
|
if (req.query.reason) obj.reason = req.query.reason;
|
|
|
|
if (err) {
|
|
obj.err = (err.message || err.code || err);
|
|
res.render("pages/admin-actions/block-ip", obj);
|
|
return;
|
|
}
|
|
|
|
if (fields.reason == "") {
|
|
obj.err = "Invalid reason to block.";
|
|
res.render("pages/admin-actions/block-ip", obj);
|
|
return;
|
|
}
|
|
|
|
let status = utils.convertToBlockedStatus(fields);
|
|
let block = fields.ip;
|
|
|
|
if (block == ip) {
|
|
obj.err = "You cannot block your own IP.";
|
|
res.render("pages/admin-actions/block-ip", obj);
|
|
return;
|
|
}
|
|
|
|
let db = client.db("mediahost");
|
|
let blocks = db.collection("blockedIPs");
|
|
let d = await blocks.insertOne({
|
|
ip: block,
|
|
status: status,
|
|
reason: fields.reason,
|
|
blockedBy: {
|
|
account: acc._id,
|
|
ip: ip
|
|
},
|
|
date: new Date().toUTCString()
|
|
});
|
|
|
|
if (d.acknowledged) {
|
|
obj.message = `Successfully blocked ${block}.`;
|
|
res.render("pages/admin-actions/block-ip", obj);
|
|
} else {
|
|
obj.err = `There was an error processing the block. Please try again later.`;
|
|
res.render("pages/admin-actions/block-ip", obj);
|
|
}
|
|
});
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/blocks/ip", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
let blocks = await db.collection("blockedIPs");
|
|
blocks = await blocks.find({}).toArray();
|
|
res.render("pages/admin-actions/all-ip-blocks", {config: config, account: acc, blocks: blocks});
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/blocks/ip/:ip", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
let blocks = await db.collection("blockedIPs");
|
|
let block = await blocks.findOne({ip: req.params.ip});
|
|
|
|
if (block == null) {
|
|
res.redirect("/admin/blocks");
|
|
return;
|
|
}
|
|
|
|
if (block.blockedBy?.account) block.blockedBy.account = (await accs.findOne({_id: block.blockedBy?.account}))?.username;
|
|
|
|
res.render("pages/admin-actions/view-ip-block", {config: config, account: acc, ip: block});
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/blocks/ip/:ip", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
let blocks = await db.collection("blockedIPs");
|
|
let block = await blocks.findOne({ip: req.params.ip});
|
|
let form = formidable({maxFileSize: 0});
|
|
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) {
|
|
err = (err.message || err.code || err);
|
|
res.render("pages/admin-actions/view-ip-block", {config: config, account: acc, err: err, ip: block});
|
|
return;
|
|
}
|
|
|
|
switch(fields.action) {
|
|
case "lift":
|
|
block = await blocks.findOneAndDelete({ip: req.params.ip});
|
|
if (block.ok == 1) {
|
|
res.redirect("/admin?from=lifted-block");
|
|
return;
|
|
} else {
|
|
res.render("pages/admin-actions/view-ip-block", {config: config, account: acc, err: "There was an issue lifting the block.", ip: block});
|
|
}
|
|
return;
|
|
|
|
default:
|
|
res.render("pages/admin-actions/view-ip-block", {config: config, account: acc, err: "Action is not available or does not exist.", ip: block});
|
|
return;
|
|
}
|
|
});
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/accounts", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let accounts = await (await accs.find({}).toArray()).reverse();
|
|
|
|
res.render("pages/admin-actions/all-accounts", {accounts: accounts, account: acc, config: config});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/reports", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let reports = await db.collection("reports");
|
|
reports = await (await reports.find({}).toArray()).reverse();
|
|
|
|
res.render("pages/admin-actions/all-reports", {reports: reports, account: acc, config: config});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.get("/admin/signup-code", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
|
|
res.render("pages/admin-actions/generate-code", {config: config, account: acc, code: null});
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/signup-code", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let signup = await db.collection("codes");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin !== true) {
|
|
next();
|
|
return;
|
|
}
|
|
let c = utils.generateString(12);
|
|
let code = await signup.insertOne({code: c});
|
|
if (code.acknowledged == true) {
|
|
res.render("pages/admin-actions/generate-code", {config: config, account: acc, code: c});
|
|
} else {
|
|
res.send(code);
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.get("/privacy", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let output = mk.makeHtml(fs.readFileSync("articles/privacy.md").toString());
|
|
|
|
res.render("pages/article", {config: config, account: acc, output: output, aName: "privacy policy"});
|
|
});
|
|
|
|
app.get("/terms", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let output = mk.makeHtml(fs.readFileSync("articles/terms.md").toString());
|
|
|
|
res.render("pages/article", {config: config, account: acc, output: output, aName: "terms"});
|
|
});
|
|
|
|
app.get("/sharex", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (config["sharex-support"] == false) {
|
|
res.setHeader("content-type", "text/html");
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
|
|
let json = fs.readFileSync(`${__dirname}/sharex.json`).toString();
|
|
json = JSON.parse(json);
|
|
|
|
json["Name"] = config.meta.name;
|
|
json["RequestURL"] = `http://${config.meta.domain}/upload?json=1`;
|
|
json["URL"] = `http://${config.meta.domain}$json:data.direct$`;
|
|
|
|
if (config["allow-anon-uploads"] == true && acc == null) {
|
|
delete json["Headers"];
|
|
} else {
|
|
if (!req.headers["cookie"]) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
|
|
json["Headers"]["Cookie"] = req.headers["cookie"];
|
|
}
|
|
|
|
res.setHeader("content-type", "text/plain");
|
|
res.setHeader("content-disposition", 'attachment; filename="sharex.sxcu"');
|
|
res.send(JSON.stringify(json, null, 2))
|
|
});
|
|
|
|
app.get("/paste", async function (req, res, next) {
|
|
let acc;
|
|
if (req.cookies["session"]) {
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (config["allow-anon-uploads"] == false && acc == null) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
} else {
|
|
if (acc == null) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
}
|
|
res.render("pages/paste", {config: config, account: acc, maxsize: utils.humanSize(config["max-file-size"])})
|
|
}
|
|
})
|
|
|
|
app.post("/paste", async function (req, res, next) {
|
|
const form = formidable({maxFileSize: config["max-file-size"], multiples: true});
|
|
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc == null) {
|
|
if (config["reject-tor"]) {
|
|
if (req.headers["x-real-ip"] || req.headers["X-Real-IP"] || req.ip) {
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
|
|
try {
|
|
let tor = istor(ip);
|
|
if (tor == true) {
|
|
res.render("pages/not-allowed", {config: config, account: acc});
|
|
return;
|
|
}
|
|
} catch(err) {
|
|
if (!err.message.includes("The given IP")) throw err;
|
|
}
|
|
} else console.log(`ERR! IP not found.`);
|
|
}
|
|
}
|
|
|
|
form.parse(req, async function(err, fields, files) {
|
|
if (err) {
|
|
if (req.query["json"] !== "1") {
|
|
let error;
|
|
if (err.httpCode && !err.message) {
|
|
error = `HTTP Error Code ${err.httpCode}`;
|
|
} else {
|
|
error = (err.message || err);
|
|
}
|
|
res.render("pages/paste", {config: config, err: error, maxsize: utils.humanSize(config["max-file-size"])});
|
|
} else {
|
|
let error;
|
|
if (err.httpCode && !err.message) {
|
|
error = `HTTP Error Code ${err.httpCode}`;
|
|
} else {
|
|
error = (err.message || err);
|
|
}
|
|
res.send({
|
|
success: false,
|
|
err: error
|
|
});
|
|
}
|
|
} else {
|
|
let u;
|
|
if (acc !== null && acc !== undefined) {
|
|
u = acc._id;
|
|
} else {
|
|
u = "Anonymous";
|
|
}
|
|
let id = utils.generateString(5);
|
|
//console.log(`[media-host] Uploaded file to "${id}".`);
|
|
fs.mkdirSync(`${config["media-folder"]}${id}/`);
|
|
let db = client.db("mediahost");
|
|
let col = await db.collection("uploads");
|
|
if (fields.text) {
|
|
fs.writeFileSync(`${config["media-folder"]}${id}/${fields.name}`, fields.text);
|
|
} else if (files.file) {
|
|
if (files.file.mimetype.startsWith("text")) {
|
|
fs.copyFileSync(files.file.filepath, `${config["media-folder"]}${id}/${files.file.originalFilename}`);
|
|
} else {
|
|
res.render("pages/paste", {config: config, account: acc, err: "Empty or invalid paste."})
|
|
return;
|
|
}
|
|
}
|
|
|
|
let data = {
|
|
id: id,
|
|
uploader: u,
|
|
direct: `/f/${id}/raw`,
|
|
name: (fields.name || "Paste"),
|
|
type: `text`,
|
|
size: utils.totalBytes(fields.text),
|
|
humanSize: utils.humanSize(utils.totalBytes(fields.text)),
|
|
date: new Date().toISOString(),
|
|
privacy: (parseInt(fields.privacy) || 0),
|
|
mime: `text/plain`
|
|
};
|
|
|
|
if (u == "Anonymous" && config["store-anon-ips"]) {
|
|
data["ip"] = (req.headers["x-real-ip"] || req.headers["X-Real-IP"]);
|
|
}
|
|
|
|
col.insertOne(data);
|
|
|
|
if (req.query["json"] == "1") {
|
|
res.send({
|
|
success: true,
|
|
data: data
|
|
});
|
|
} else {
|
|
res.redirect(`/f/${id}`);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
app.get("/r/:id", function(req, res, next) {
|
|
res.redirect(`/f/${req.params.id}/raw`);
|
|
});
|
|
|
|
app.get("/report", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
res.render("pages/report", {config: config, account: acc, upload: req.query["upload"], message: null, err: null});
|
|
});
|
|
|
|
app.post("/report", async function (req, res, next) {
|
|
const form = formidable({maxFileSize: 0, multiples: true});
|
|
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) {
|
|
let error;
|
|
if (err.httpCode && !err.message) {
|
|
error = `HTTP Error Code ${err.httpCode}`;
|
|
} else {
|
|
error = (err.message || err);
|
|
}
|
|
res.render("pages/report", {config: config, err: error, upload: req.query["upload"], message: null});
|
|
} else {
|
|
if (config["captcha"]["enabled"] == true && config["captcha"]["show-at-report"]) {
|
|
if (!fields["h-captcha-response"]) {
|
|
res.render("pages/report", {config: config, err: "CAPTCHA needs to be solved.", upload: req.query["upload"], message: null});
|
|
return;
|
|
} else {
|
|
let h = await hcaptcha.verify(config["captcha"]["secret"], fields["h-captcha-response"]);
|
|
if (!h.success) {
|
|
res.render("pages/report", {config: config, err: "CAPTCHA came back invalid.", upload: req.query["upload"], message: null});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fields.offense) {
|
|
res.render("pages/report", {config: config, err: "Offense field came back invalid.", upload: req.query["upload"], message: null});
|
|
return;
|
|
}
|
|
|
|
let ups = await db.collection("uploads");
|
|
let up = await ups.findOne({id: fields.upload});
|
|
if (up == null) {
|
|
res.render("pages/report", {config: config, err: "Upload ID is invalid. Make sure you didn't make a typo.", upload: req.query["upload"], message: null});
|
|
} else {
|
|
let reports = await db.collection("reports");
|
|
let ip = (req.headers["X-Real-IP"] || req.headers["x-real-ip"] || req.ip);
|
|
let report = {
|
|
id: utils.generateString(5),
|
|
type: fields.offense,
|
|
respond: fields.email,
|
|
upload: fields.upload,
|
|
comments: fields.comment,
|
|
ip: ip,
|
|
unread: true,
|
|
unsolved: true
|
|
};
|
|
await reports.insertOne(report);
|
|
res.render("pages/report", {config: config, err: null, upload: req.query["upload"], message: "Your report has been submitted and will be reviewed as soon as possible.", account: acc});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
app.get("/reports/:id", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let reports = await db.collection("reports");
|
|
let report = await reports.findOne({id: req.params.id});
|
|
|
|
if (report == null) next();
|
|
else {
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
report.actualType = utils.toFullReportString(report.type);
|
|
res.render("pages/admin-actions/view-report", {config: config, account: acc, report: report, message: null});
|
|
} else next();
|
|
} else next();
|
|
}
|
|
});
|
|
|
|
app.post("/reports/:id/read", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let reports = await db.collection("reports");
|
|
let report = await reports.findOne({id: req.params.id});
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let ar = report;
|
|
ar.unread = false;
|
|
await reports.findOneAndReplace({id: report.id}, ar);
|
|
res.render("pages/admin-actions/view-report", {config: config, account: acc, report: report, message: "Message marked as read."});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.post("/reports/:id/unread", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let reports = await db.collection("reports");
|
|
let report = await reports.findOne({id: req.params.id});
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let ar = report;
|
|
ar.unread = true;
|
|
report.actualType = utils.toFullReportString(report.type);
|
|
await reports.findOneAndReplace({id: report.id}, ar);
|
|
res.render("pages/admin-actions/view-report", {config: config, account: acc, report: report, message: "Message marked as unread."});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.post("/reports/:id/solved", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
let reports = await db.collection("reports");
|
|
let report = await reports.findOne({id: req.params.id});
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
let ar = report;
|
|
ar.unsolved = false;
|
|
await reports.findOneAndReplace({id: report.id}, ar);
|
|
if (config["transparent-reports"] == true) res.render("pages/admin-actions/redact-reports", {config: config, account: acc, originalComment: report.comments, id: report.id});
|
|
else res.render("pages/admin-actions/view-report", {config: config, account: acc, report: report, message: "Message marked as solved."});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.post("/admin/reports/redact", async function (req, res) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
let form = formidable({maxFileSize: 0});
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
if (acc.admin == true) {
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) res.render("pages/admin-actions/redact-reports", {config: config, account: acc, err: err});
|
|
else {
|
|
let publicReports = db.collection("publicReports");
|
|
let reports = db.collection("reports");
|
|
let report = await reports.findOne({id: fields.reportId});
|
|
let publicId = utils.generateString(5);
|
|
let publicReport = await publicReports.insertOne({
|
|
id: publicId,
|
|
originalReport: report.id,
|
|
comment: fields.originalComment,
|
|
emails: fields.emails,
|
|
adminComments: fields.comments,
|
|
date: new Date().toDateString()
|
|
});
|
|
|
|
if (publicReport.acknowledged) res.redirect(`/transparency/reports/${publicId}?from=done-redacting`);
|
|
else res.render("pages/admin-actions/redact-reports", {config: config, account: acc, err: err});
|
|
}
|
|
});
|
|
} else next();
|
|
} else next();
|
|
});
|
|
|
|
app.get("/transparency/reports/:id", async function (req, res) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
let reports = db.collection("publicReports");
|
|
let report = await reports.findOne({id: req.params.id});
|
|
|
|
res.render("pages/transparent-report", {
|
|
comment: report.comment,
|
|
report: report.originalReport,
|
|
emails: report.emails,
|
|
adminComments: report.adminComments,
|
|
date: report.date,
|
|
account: acc,
|
|
config: config
|
|
});
|
|
});
|
|
|
|
app.post("/reports/:id/unsolved", async function (req, res) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
let publicReports = db.collection("publicReports");
|
|
let reports = db.collection("reports");
|
|
let report = await reports.findOne({id: req.params.id});
|
|
report.unsolved = true;
|
|
let action = await reports.findOneAndReplace({id: req.params.id}, report);
|
|
if (action.ok == 1) {
|
|
if (config["transparent-reports"] == true) {
|
|
action = await publicReports.findOneAndDelete({originalReport: req.params.id});
|
|
}
|
|
res.render("pages/admin-actions/view-report", {config: config, account: acc, report: report, message: "Message marked as unsolved."});
|
|
} else res.render("pages/admin-actions/view-report", {config: config, account: acc, report: report, err: "Could not update report."});
|
|
});
|
|
|
|
app.get("/account/delete", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
res.render("pages/delete-acc", {config: config, account: acc});
|
|
} else next();
|
|
});
|
|
|
|
app.post("/account/delete", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
let accs = await db.collection("accounts");
|
|
if (req.cookies["session"]) {
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
let u = await (await db.collection("uploads").find({uploader: acc._id})).toArray();
|
|
for (let a in u) {
|
|
removeUpload(u[a].id);
|
|
}
|
|
let a = await accs.findOneAndDelete({_id: acc._id});
|
|
if (a.ok == 1) {
|
|
res.clearCookie("session");
|
|
res.redirect("/?from=self-delete");
|
|
} else {
|
|
res.end(a);
|
|
}
|
|
} else next();
|
|
});
|
|
|
|
app.get("/account/rename", async function(req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
if (acc !== null && acc !== undefined) {
|
|
res.render("pages/rename-acc", {config: config, account: acc, username: acc.username, err: null});
|
|
} else next();
|
|
});
|
|
|
|
app.post("/account/rename", async function(req, res, next) {
|
|
let acc, accs;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
let form = formidable();
|
|
|
|
form.parse(req, async function(err, fields) {
|
|
if (err) res.render("pages/rename-acc", {config: config, account: acc, username: acc.username, err: (err.message || err.code || err)});
|
|
else {
|
|
try {
|
|
if (fields.username) {
|
|
let preexist = accs.findOne({username: fields.username});
|
|
if (preexist == null || preexist !== "Anonymous") {
|
|
if (utils.validateUsername(fields.username)) {
|
|
acc.username = fields.username;
|
|
let account = await accs.findOneAndReplace({_id: acc._id}, acc);
|
|
if (account.ok == 1) {
|
|
res.redirect(`/u/${acc.username}`);
|
|
} else throw "Could not insert change into database";
|
|
} else throw "Invalid username, please try another one";
|
|
} else throw "Username is already taken";
|
|
} else throw "Need to specify username";
|
|
} catch(err) {
|
|
res.render("pages/rename-acc", {config: config, account: acc, username: acc.username, err: (err.message || err.code || err)});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
app.get("/transparency", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (config["transparent-reports"] == true) {
|
|
let reports = db.collection("publicReports");
|
|
reports = await reports.find({}).toArray();
|
|
|
|
res.render("pages/transparency", {config: config, account: acc, reports: reports})
|
|
} else next();
|
|
});
|
|
|
|
app.get("/*", async function (req, res, next) {
|
|
let acc;
|
|
let db = client.db("mediahost");
|
|
if (req.cookies["session"]) {
|
|
let accs = await db.collection("accounts");
|
|
acc = await accs.findOne({session: req.cookies["session"]});
|
|
}
|
|
|
|
if (acc == null && req.cookies["session"]) res.clearCookie("session");
|
|
|
|
res.render("pages/404", {config: config, account: acc});
|
|
});
|
|
|
|
async function start() {
|
|
console.log("[media-host] Connecting to DB.");
|
|
await client.connect();
|
|
console.log("[media-host] Connected to DB.");
|
|
app.listen(config["port"], "127.0.0.1", function() {
|
|
console.log(`[media-host] HTTP Server listening at ${config["port"]}`);
|
|
});
|
|
}
|
|
|
|
function isOwned(file, acc) {
|
|
try {
|
|
if (acc._id.toString() == file.uploader || acc.admin == true) {return true;} else {return false;}
|
|
} catch(e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function removeUpload(id) {
|
|
let db = await client.db("mediahost");
|
|
let files = await db.collection("uploads");
|
|
await files.findOneAndDelete({id: id});
|
|
if (fs.existsSync(`${config["media-folder"]}${id}`)) fs.rmSync(`${config["media-folder"]}${id}`, {recursive: true});
|
|
if (fs.existsSync(`${config?.["remux"]?.["folder"]}${id}`)) fs.rmSync(`${config["remux"]["folder"]}${id}`, {recursive: true});
|
|
}
|
|
|
|
async function initTranscode(id, mime) {
|
|
let db = await client.db("mediahost");
|
|
let files = await db.collection("uploads");
|
|
let file = await files.findOne({id});
|
|
|
|
if (mime != "video/mp4" && mime != "video/webm") {
|
|
if (config?.["remux"]?.["enabled"] == true) {
|
|
let originalFile = `${config["media-folder"]}/${id}/${file.name}`;
|
|
let transFile = `${config["remux"]["folder"]}/${id}/${file.name}.${config["remux"]["container"]}`; // based file
|
|
fs.mkdirSync(`${config["remux"]["folder"]}/${id}`);
|
|
let ffmpegProcess = spawn(ffmpegStatic, [`-i`, originalFile, `-vcodec`, config["remux"]["video-codec"], `-acodec`, config["remux"]["audio-codec"], `-preset`, `ultrafast`, transFile]);
|
|
|
|
ffmpegProcess.on("close", async function(code) {
|
|
if (code == 0) {
|
|
file.transcodedFile = `/transcoded/${id}/${file.name}.${config["remux"]["container"]}`;
|
|
await files.findOneAndReplace({id}, file);
|
|
} else console.log(`ffmpeg failed on ${id}`);
|
|
});
|
|
}
|
|
}
|
|
} |