2025-01-01 02:18:50 +00:00
import Fastify from "fastify" ;
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
} ) ;
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 ( "IMAGE" ) ;
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 ) ;
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 ) = > {
// @ts-ignore
2025-01-06 06:53:13 +00:00
Console . printInfo ( ` [ ${ req . logType } ] [ ${ req . method . toUpperCase ( ) } ] [ ${ ConsoleUtility . StatusColor ( res . statusCode ) } ] [ ${ blue ( ` ${ Date . now ( ) - req . startTime } ms ` ) } ] > ${ req . url } ` ) ;
2025-01-03 03:11:00 +00:00
2025-01-26 04:22:59 +00:00
//console.log(res.getHeaders());
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
} ) ;