forked from malee31/Slack-to-Discord-Bridge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfileServer.js
110 lines (99 loc) · 4.02 KB
/
fileServer.js
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
const fileManager = require("./fileManager.js");
const mime = require("mime-types");
const http = require("http");
const path = require("path");
const fs = require("fs");
/**
* An adapter for Slack’s Events API.
* @external SlackEventAdapter
* @see https://slack.dev/node-slack-sdk/reference/events-api
*/
/**
* Creates the simple file server for downloads and adds in the Slack events listener to the server
* @param {SlackEventAdapter} slackEvents The event adapter for Slack from {@link https://slack.dev/node-slack-sdk/reference/events-api|require("@slack/events-api").createEventAdapter}
* @module fileServer
*/
module.exports = fsMake;
function fsMake(slackEvents) {
return http.createServer((req, res) => {
// Default Slack endpoint for all Slack events
if(req.url === "/slack/events") {
slackEvents.requestListener()(req, res);
return;
}
const fileName = decodeURIComponent(req.url.split("?")[0]);
const filePath = getRequestedPath(fileName, req, res);
if(!filePath) return;
if(filePath === fileManager.DOWNLOADS_FOLDER) {
showFileList(filePath, res);
return;
}
fs.readFile(filePath, (err, data) => {
if(err) {
console.warn(`Error reading file from downloads: ${err}`);
res.writeHead(200, { "Content-Type": "text/plain" });
res.write(`Error reading file from downloads (${filePath}): \n${err}`);
res.end();
return;
}
const contentType = mime.lookup(filePath);
res.writeHead(200, {
"Content-Type": contentType ?? false,
"Content-Disposition": req.url.toLowerCase().split("?")[1]?.includes("download") ? "attachment" : "inline"
});
res.end(data, "UTF-8");
});
});
}
/**
* Takes in the file path and request data and resolves it to a file path in the downloads folder<br>
* May be disabled with environment variables
* @param {string} fileName Name of the file. Originates from req.url so it must start with a /
* @param {IncomingMessage} req Request object from http or any other server request
* @param {ServerResponse} res Response object from http or any other server request
* @return {string|boolean} Returns the absolute path to a file in the downloads folder or false if access should be denied
*/
function getRequestedPath(fileName, req, res) {
const filePath = path.resolve(fileManager.DOWNLOADS_FOLDER, "." + fileName);
console.log(`[${new Date().toLocaleString()}] Accessing ${filePath} from ${req.url}`);
if(!filePath.startsWith(fileManager.DOWNLOADS_FOLDER)) {
console.warn(`Attempt to access ${filePath} detected and denied`);
return false;
}
if(process.env.DISABLE_FILE_SERVER?.trim().toLowerCase() === "true") {
console.warn("File Server is Disabled. File Request Denied");
res.writeHead(500, { "Content-Type": "text/plain" });
res.write(`The file server is set to private and disabled.\nYour files are most likely still stored on the server so ask the server owner for it if you need it!`);
res.end();
return false;
}
return filePath;
}
/**
* Lists the names of all files in the downloads folder. Can be disabled with environment variables.
* @param {string} filePath Absolute path to a file in the downloads folder. May be a file that does not exist
* @param {ServerResponse} res Response object from http or any other server request
*/
function showFileList(filePath, res) {
if(process.env.DISABLE_FILE_SERVER_LIST?.trim().toLowerCase() !== "true") {
fs.readdir(filePath, (err, files) => {
if(err) {
console.warn("Error Reading Downloads Folder");
res.writeHead(500, { "Content-Type": "text/plain" });
res.write(`Error Reading Downloads Folder: \n${err}`);
res.end();
return;
}
res.writeHead(200, { "Content-Type": "text/plain" });
res.write(`Download Folder Contents:\n`);
files.forEach(file => {
res.write(`${file}\n`);
});
res.end();
});
} else {
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("List of files stored on the server will not be listed because DISABLE_FILE_SERVER_LIST is set to TRUE.\nEach specific file is still accessible through their respective urls");
res.end();
}
}