121 lines
3.6 KiB
JavaScript
121 lines
3.6 KiB
JavaScript
import express from "express";
|
|
import busboy from "busboy";
|
|
import HashThrough from "hash-through";
|
|
import { to36 } from "1636";
|
|
import { createHash } from "crypto";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import mime from "mime";
|
|
|
|
import Message from "./models/Message.js";
|
|
import Emoji from "./models/Emoji.js";
|
|
import { DATA_DIR } from "./constants.js";
|
|
import { shuffleArray } from "./util.js";
|
|
|
|
export var router = express.Router();
|
|
|
|
|
|
|
|
|
|
router.get("/messages", (req, res, next) => {
|
|
if (req.query.before) var beforeDate = new Date(req.query.before);
|
|
if (beforeDate == "Invalid Date") return res.status(400).send("`before` param is invalid date");
|
|
if (req.query.after) var afterDate = new Date(req.query.after);
|
|
if (afterDate == "Invalid Date") return res.status(400).send("`after` param is invalid date");
|
|
|
|
if (beforeDate || afterDate) {
|
|
var query = {timestamp:{}};
|
|
if (beforeDate) query.timestamp.$lt = beforeDate;
|
|
if (afterDate) query.timestamp.$gt = afterDate;
|
|
}
|
|
|
|
Message.getMessages({query, secret: req.query.secret}).then(messages => res.send(messages)).catch(next);
|
|
});
|
|
|
|
router.post("/upload", (req, res, next) => {
|
|
var boi = busboy({headers: req.headers});
|
|
var codes = [];
|
|
boi.on("file", (name, file, info) => {
|
|
var resolve;
|
|
codes.push(new Promise(r => resolve = r));
|
|
var hash = HashThrough(() => createHash("sha1"));
|
|
var tmpfilepath = path.join(DATA_DIR, "tmp", Math.random().toString());
|
|
var write = fs.createWriteStream(tmpfilepath);
|
|
file.pipe(hash).pipe(write);
|
|
write.on("error", error => next(error));
|
|
write.on("close", () => {
|
|
var code = to36(hash.digest("hex"));
|
|
var j = {name, code, type: info.mimeType};
|
|
var targetfilepath = path.join(DATA_DIR, "objects", code);
|
|
fs.exists(targetfilepath, exists => {
|
|
if (exists) {
|
|
resolve(j);
|
|
fs.unlink(tmpfilepath, e=>e&&console.error(e.stack));
|
|
}
|
|
else fs.rename(tmpfilepath, targetfilepath, error => {
|
|
if (error) console.error(error.stack);
|
|
resolve(j);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
boi.on("close", () => {
|
|
Promise.all(codes).then(codes => res.send(codes));
|
|
});
|
|
req.pipe(boi);
|
|
});
|
|
|
|
|
|
router.get("/objects/:code/:filename?", (req, res) => {
|
|
//var type = req.query.type?.trim().toLowerCase().replace(/[^a-z0-9\/; =-]/g,'');
|
|
//if (type?.startsWith("text/html")) type = type.replace("text/html", "text/plain");
|
|
if (req.params.filename) {
|
|
var type = mime.getType(req.params.filename);
|
|
}
|
|
res.header("Cache-Control", "max-age=31536000");
|
|
res.sendFile(req.params.code, {
|
|
root: path.join(DATA_DIR, "objects/"),
|
|
headers: type ? {"Content-Type": type} : undefined
|
|
});
|
|
});
|
|
|
|
|
|
router.get("/emoji/:emoji", (req, res, next) => {
|
|
Emoji.findOne({name: req.params.emoji}).then(emoji => {
|
|
if (!emoji) return res.sendStatus(404);
|
|
res.header("Cache-Control", "max-age=31536000");
|
|
res.type(emoji.type);
|
|
res.send(emoji.data);
|
|
}).catch(next);
|
|
});
|
|
|
|
|
|
router.get("/emojis", (req, res, next) => {
|
|
Emoji.find({}, "name").then(emojis => {
|
|
emojis = emojis.map(e => e.name);
|
|
res.send(emojis);
|
|
}).catch(next);
|
|
});
|
|
|
|
|
|
router.put("/emoji/:name", express.raw({limit: "1mb", type: ()=>true}), async (req, res, next) => {
|
|
try {
|
|
var emoji = new Emoji({
|
|
name: req.params.name,
|
|
type: req.query.type,
|
|
data: req.body
|
|
});
|
|
await emoji.save();
|
|
res.sendStatus(201);
|
|
} catch (error) {next(error)}
|
|
});
|
|
|
|
|
|
var favicon = fs.readFileSync(path.join(process.cwd(), "logo.svg"), "utf-8");
|
|
router.get("/favicon.svg", (req, res) => {
|
|
res.header("Cache-Control", "max-age=86400");
|
|
res.type("svg").send(favicon.replaceAll("{num}", Number(req.query.num || 0) || ""));
|
|
});
|
|
|
|
|
|
router.use(express.static(path.join(process.cwd(), "../app/build/"))); |