EUS/index.ts

149 lines
4.3 KiB
TypeScript
Raw Permalink Normal View History

import Fastify, { type FastifyReply, type FastifyRequest } from "fastify";
2025-01-01 02:18:50 +00:00
import FastifyFormBody from "@fastify/formbody";
import FastifyMultipart from "@fastify/multipart";
import FastifyCookie from "@fastify/cookie";
import FastifyView from "@fastify/view";
import FastifyStatic from "@fastify/static";
import Config from "./objects/Config";
import EJS from "ejs";
import { Console } from "hsconsole";
import Controller from "./controllers/Controller";
import HomeController from "./controllers/HomeController";
import Database from "./objects/Database";
import { join } from "path";
2025-01-03 03:11:00 +00:00
import AccountController from "./controllers/AccountController";
2025-01-05 14:22:18 +00:00
import { magenta, blue, cyan, green, red } from "dyetty";
2025-01-03 03:11:00 +00:00
import ConsoleUtility from "./utilities/ConsoleUtility";
2025-01-05 14:22:18 +00:00
import HashFS from "./objects/HashFS";
2025-01-06 06:53:13 +00:00
import FunkyArray from "funky-array";
import MediaService from "./services/MediaService";
import Media from "./entities/Media";
2025-01-25 12:21:55 +00:00
import HeaderUtility from "./utilities/HeaderUtility";
2025-01-26 04:22:59 +00:00
import { createReadStream } from "fs";
2025-01-01 02:18:50 +00:00
2025-01-01 22:03:59 +00:00
Console.customHeader(`EUS server started at ${new Date()}`);
2025-01-01 02:18:50 +00:00
const fastify = Fastify({
logger: false
});
fastify.register(FastifyView, {
engine: {
ejs: EJS
}
});
fastify.register(FastifyFormBody);
2025-01-26 10:34:56 +00:00
fastify.register(FastifyMultipart, {
limits: {
files: 1,
fileSize: 104857600
}
});
2025-01-01 02:18:50 +00:00
fastify.register(FastifyCookie, {
secret: Config.session.secret,
parseOptions: {
path: "/",
secure: true
}
});
fastify.register(FastifyStatic, {
root: join(__dirname, "wwwroot"),
2025-01-25 12:21:55 +00:00
preCompressed: true,
decorateReply: false,
redirect: false
2025-01-01 02:18:50 +00:00
});
function printReqInfo(req: FastifyRequest, res: FastifyReply) {
// @ts-ignore
Console.printInfo(`[ ${req.logType} ] [ ${req.method.toUpperCase()} ] [ ${ConsoleUtility.StatusColor(res.statusCode)} ] [ ${blue(`${Date.now() - req.startTime}ms`)} ] > ${req.url}`);
}
2025-01-06 06:53:13 +00:00
const hashLookupCache = new FunkyArray<string, Media>();
fastify.addHook("preHandler", (req, res, done) => {
(async () => {
2025-01-03 03:11:00 +00:00
// @ts-ignore
2025-01-06 06:53:13 +00:00
req.startTime = Date.now();
2025-01-03 03:11:00 +00:00
2025-01-06 06:53:13 +00:00
// * Take usual controller path if this path is registered.
if (Controller.RegisteredPaths.includes(req.url)) {
// @ts-ignore
req.logType = cyan("CONTROLLER");
2025-01-26 04:22:59 +00:00
HeaderUtility.AddBakedHeaders(res);
2025-01-06 06:53:13 +00:00
return done();
} else {
const urlParts = req.url.split("/");
2025-01-26 16:40:40 +00:00
if (urlParts.length === 2 && urlParts[1].length <= 16) {
2025-01-06 06:53:13 +00:00
let media = hashLookupCache.get(urlParts[1]) ?? null;
if (!media) {
media = await MediaService.GetByTag(urlParts[1]);
if (media) {
hashLookupCache.set(urlParts[1], media);
}
}
if (media) {
// @ts-ignore
req.logType = cyan("MEDIA");
2025-01-06 06:53:13 +00:00
const fileStore = HashFS.GetHashFSInstance("images");
2025-01-26 04:22:59 +00:00
const readStream = createReadStream(join(fileStore.path, fileStore.GetRelativePath(media.Hash)));
res.raw.writeHead(200, HeaderUtility.CombineHeaders({
"content-type": media.MediaType,
"content-length": media.FileSize,
}));
readStream.pipe(res.raw);
printReqInfo(req, res);
2025-01-26 04:22:59 +00:00
return;
2025-01-25 12:21:55 +00:00
}
2025-01-26 04:22:59 +00:00
} else {
HeaderUtility.AddBakedHeaders(res);
2025-01-06 06:53:13 +00:00
}
// @ts-ignore
req.logType = magenta("STATIC");
}
2025-01-26 04:22:59 +00:00
return done();
2025-01-06 06:53:13 +00:00
})();
2025-01-03 03:11:00 +00:00
});
fastify.addHook("onSend", (req, res, _payload, done) => {
printReqInfo(req, res);
2025-01-26 04:22:59 +00:00
2025-01-03 03:11:00 +00:00
done();
});
2025-01-08 14:50:10 +00:00
fastify.setNotFoundHandler(async (_req, res) => {
2025-01-05 14:22:18 +00:00
2025-01-08 08:19:11 +00:00
return res.status(404).view("views/404.ejs");
2025-01-01 02:18:50 +00:00
});
2025-01-05 14:22:18 +00:00
HashFS.STARTUP_DIR = __dirname;
new HashFS("images");
if (Config.database.enabled) {
new Database(Config.database.address, Config.database.port, Config.database.username, Config.database.password, Config.database.name);
} else {
Console.printInfo(`[ ${red("DATABASE")} ] Database is disabled.`);
}
2025-01-01 02:18:50 +00:00
2025-01-05 14:22:18 +00:00
if (Config.controllers.enabled && Config.database.enabled) {
Controller.FastifyInstance = fastify;
new AccountController();
new HomeController();
} else {
Console.printInfo(`[ ${red("CONTROLLER")} ] Controllers are disabled${Config.controllers.enabled && !Config.database.enabled ? " because the database is disabled but required by the controllers." : "."} Server will operate in static mode only.`);
}
2025-01-01 02:18:50 +00:00
2025-01-05 14:22:18 +00:00
fastify.listen({ port: Config.hosts.webPort, host: Config.hosts.webHost }, (err, address) => {
2025-01-01 02:18:50 +00:00
if (err) {
Console.printError(`Error occured while spinning up fastify:\n${err}`);
process.exit(1);
}
2025-01-05 14:22:18 +00:00
Console.printInfo(`[ ${green("MAIN")} ] Listening at ${address.replace("0.0.0.0", "localhost").replace("127.0.0.1", "localhost")}`);
2025-01-01 02:18:50 +00:00
});