-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
120 lines (104 loc) · 3.41 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import type { IModule, moduleReq } from "./interfaces/IModule";
import { promises as fs } from "fs";
import path from "path";
import express from "express";
import type { Response } from "express-serve-static-core";
import multer from "multer";
import { red, yellow, green, lightRed, white, blue, cyan } from "kolorist";
import config from "./config.json";
/**
* Loads modules from provided directory.
*
* @param dir - directory to the modules
* @returns instances of classes from modules
*/
async function loadClasses(dir: string): Promise<{ module: IModule }[]> {
const files = await fs.readdir(dir);
const classes: { module: IModule }[] = [];
console.log("Loading modules...");
for (const file of files) {
if (file.endsWith(".ts")) {
const filePath = path.join(dir, file);
const importedModule = await import(filePath);
classes.push(importedModule);
}
}
console.log("Loaded", green(`${classes.length}`), "modules:");
console.log(
blue(
`${classes
.map((c) => c.module.emoji + " " + c.module.name)
.join(white(","))}`
)
);
// TODO: validate duplicate paths
return classes;
}
function colorForStatus(status: number, text: string): string {
if (status >= 500) {
return red(text);
} else if (status >= 400) {
return yellow(text);
} else {
return green(text);
}
}
/**
* Main function. Runs the Express server and handles requests and response formatting in the console
*/
async function main() {
console.log(`💻 PC Remote Control v0.1`);
// modules stuff
const dir = path.resolve("./modules");
const classes = await loadClasses(dir);
// multer stuff
const storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, config.uploadsPath); // Upload folder. Change to yours
},
filename: function (req, file, callback) {
callback(null, file.originalname);
},
});
const upload = multer({ storage: storage });
// express stuff
const app = express();
const port = 3000;
const host = "0.0.0.0";
app.use(express.json());
app.all("/wish/:path", upload.single("file"), (req, res) =>
handleRequest(req, classes, res)
);
app.listen(port, host, () => {
console.log("Listening on 🌍", cyan(`http://localhost:${port}`));
});
}
main();
function handleRequest(
req: moduleReq,
classes: { module: IModule }[],
res: Response<any, Record<string, any>, number>
) {
const path = req.params.path;
const matchingClass = classes.filter((p) => path === p.module.path);
const requestedModule = matchingClass[0]?.module;
if (requestedModule) {
const moduleResult = requestedModule.fn(req); // req validation is a module responsibility.
Promise.resolve(moduleResult).then((mr) => {
console.log(
`${requestedModule.emoji} /wish/${path} • ${colorForStatus(
mr.status,
mr.response
)}`
);
res.send(mr.response).status(mr.status);
});
} else {
console.log(
`❌ ${red("Module on path:")} ${lightRed("/wish/${path}")} ${red(
"not found."
)}`
);
res.send("Requested module not found").status(404);
}
}