Compare commits
10 Commits
7f57c0ed23
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| da1b0ab58c | |||
| ff8b626b8a | |||
| e7b770b177 | |||
| 5d203d2ca7 | |||
| 4e99509d96 | |||
| 16afa0abc5 | |||
| 794b84a152 | |||
| c09993d9bc | |||
| 2c0d3ef78e | |||
| 2448d69f1f |
@@ -8,3 +8,4 @@
|
|||||||
!/README.md
|
!/README.md
|
||||||
!/files/www/qonq.js
|
!/files/www/qonq.js
|
||||||
!/favicon.ico
|
!/favicon.ico
|
||||||
|
!/antiscrape.js
|
||||||
@@ -17,13 +17,12 @@ The following environment variables are optional.
|
|||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
|----------|-------------|---------|
|
|----------|-------------|---------|
|
||||||
| `HOSTNAME` | Overrides the hostname for generating URLs. | hostname of the upload request |
|
| `BASE_HOSTNAME` | Overrides the hostname for generating URLs. | host header on the upload request |
|
||||||
| `DISCORD_WEBHOOK` | Discord webhook url that newly-uploaded URLs will be sent to to pre-load their embed, which theoretically makes them embed again faster. | `undefined` (disabled) |
|
| `DISCORD_WEBHOOK` | Discord webhook url that newly-uploaded URLs will be sent to to pre-load their embed, which theoretically makes them embed again faster. | `undefined` (disabled) |
|
||||||
| `PORT` | TCP port to listen on | `8568` |
|
| `PORT` | TCP port to listen on | `8568` |
|
||||||
| `ADDRESS` | Address to bind to | `'0.0.0.0'` (all) |
|
| `ADDRESS` | Address to bind to | `'0.0.0.0'` (all) |
|
||||||
| `FILES_DIR` | Directory to store the files in | `'files'` (relative of working directory) |
|
| `FILES_DIR` | Directory to store the files in | `'files'` (relative of working directory) |
|
||||||
| `TMP_DIR` | Directory to store pending uploads in | `os.tmpdir()` |
|
| `TRUST_PROXY` | Value for express's [`'trust proxy'`](https://expressjs.com/en/5x/api.html#trust.proxy.options.table) setting | `'loopback'` |
|
||||||
| `TRUST_PROXY` | Value for express's [`'trust proxy'`](https://expressjs.com/en/5x/api.html#trust.proxy.options.table) setting | `'127.0.0.1'` |
|
|
||||||
|
|
||||||
|
|
||||||
Run with `node qonq.js` or your favorite init system.
|
Run with `node qonq.js` or your favorite init system.
|
||||||
@@ -35,12 +34,12 @@ Run with `node qonq.js` or your favorite init system.
|
|||||||
"Version": "12.4.1",
|
"Version": "12.4.1",
|
||||||
"DestinationType": "ImageUploader, TextUploader, FileUploader",
|
"DestinationType": "ImageUploader, TextUploader, FileUploader",
|
||||||
"RequestMethod": "POST",
|
"RequestMethod": "POST",
|
||||||
"RequestURL": "http://localhost:8568/upload",
|
"RequestURL": "https://qonq.gq/",
|
||||||
"Headers": {
|
"Headers": {
|
||||||
"authentication": "paste value of AUTH_TOKEN here"
|
"authentication": "paste value of AUTH_TOKEN here",
|
||||||
|
"filename": "$filename$"
|
||||||
},
|
},
|
||||||
"Body": "MultipartFormData",
|
"Body": "Binary"
|
||||||
"FileFormName": "file"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
You can import this custom uploader config and modify the Request URL and authentication fields as necessary.
|
You can import this custom uploader config and modify the Request URL and authentication fields as necessary.
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// someone could iterate over all ~1.6 million possible file codes to download all files.
|
||||||
|
// prevent this by banning IP addresses that request too many non-existant files.
|
||||||
|
|
||||||
|
var ip404 = {};
|
||||||
|
module.exports = (req, res, next) => {
|
||||||
|
if (ip404[req.ip]?.size > 10)
|
||||||
|
return res.status(403).send("Banned");
|
||||||
|
res.on("finish", () => {
|
||||||
|
if (res.statusCode == 404 && req.filecode) {
|
||||||
|
if (!ip404[req.ip]) ip404[req.ip] = new Set();
|
||||||
|
ip404[req.ip].add(req.filecode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
};
|
||||||
Generated
-14
@@ -8,7 +8,6 @@
|
|||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"formidable": "^1.2.2",
|
|
||||||
"serve-favicon": "^2.5.0",
|
"serve-favicon": "^2.5.0",
|
||||||
"serve-index": "^1.9.1"
|
"serve-index": "^1.9.1"
|
||||||
}
|
}
|
||||||
@@ -215,14 +214,6 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/formidable": {
|
|
||||||
"version": "1.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
|
|
||||||
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==",
|
|
||||||
"funding": {
|
|
||||||
"url": "https://ko-fi.com/tunnckoCore/commissions"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||||
@@ -743,11 +734,6 @@
|
|||||||
"unpipe": "~1.0.0"
|
"unpipe": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"formidable": {
|
|
||||||
"version": "1.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
|
|
||||||
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
|
|
||||||
},
|
|
||||||
"forwarded": {
|
"forwarded": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"formidable": "^1.2.2",
|
|
||||||
"serve-favicon": "^2.5.0",
|
"serve-favicon": "^2.5.0",
|
||||||
"serve-index": "^1.9.1"
|
"serve-index": "^1.9.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
require("dotenv").config();
|
require("dotenv").config();
|
||||||
var colors = require("colors");
|
var colors = require("colors");
|
||||||
var express = require("express");
|
var express = require("express");
|
||||||
var formidable = require("formidable");
|
|
||||||
var serveIndex = require("serve-index");
|
var serveIndex = require("serve-index");
|
||||||
var serveFavicon = require("serve-favicon");
|
var serveFavicon = require("serve-favicon");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
try {
|
try { var customGen = require("./customGen"); } catch(e) {}
|
||||||
var customUrlGen = require("./custom-urlgen");
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
var FILES_DIR = process.env.FILES_DIR || "files";
|
var FILES_DIR = process.env.FILES_DIR || "files";
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
app.set("env", "production");
|
app.set("env", "production");
|
||||||
app.set('trust proxy', process.env.TRUST_PROXY || "127.0.0.1");
|
app.set('trust proxy', process.env.TRUST_PROXY || "loopback");
|
||||||
app.listen(process.env.PORT || 8568, process.env.ADDRESS);
|
app.listen(process.env.PORT || 8568, process.env.ADDRESS);
|
||||||
|
app.use((req,res,next) => { res.header("Access-Control-Allow-Origin", '*'); next(); });
|
||||||
|
|
||||||
app.use((req, res, next)=>{
|
app.use((req, res, next)=>{
|
||||||
var d = new Date;
|
var d = new Date;
|
||||||
@@ -32,17 +29,12 @@ app.use(serveFavicon("favicon.ico"));
|
|||||||
|
|
||||||
app.post("*", (req, res, next) => {
|
app.post("*", (req, res, next) => {
|
||||||
if (req.headers.authentication != process.env.AUTH_TOKEN) return void res.status(403).send("Unauthorized");
|
if (req.headers.authentication != process.env.AUTH_TOKEN) return void res.status(403).send("Unauthorized");
|
||||||
var form = new formidable.IncomingForm({
|
|
||||||
maxFileSize: 2**30, // 1 GiB
|
|
||||||
maxFields: 1,
|
|
||||||
uploadDir: process.env.TMP_DIR
|
|
||||||
});
|
|
||||||
form.parse(req, function(err, fields, files) {
|
|
||||||
if (err) return void next(err);
|
|
||||||
var file = files.file;
|
|
||||||
if (!file) return void res.sendStatus(400);
|
|
||||||
(function trymkdir() {
|
(function trymkdir() {
|
||||||
var filecode = Math.random().toString(36).slice(2).substring(0,4);
|
if (customGen) {
|
||||||
|
var g = customGen(req);
|
||||||
|
var filecode = g.next().value;
|
||||||
|
}
|
||||||
|
filecode ||= Math.random().toString(36).slice(2).substring(0,4);
|
||||||
var webroot = path.join(FILES_DIR, filecode);
|
var webroot = path.join(FILES_DIR, filecode);
|
||||||
fs.mkdir(webroot, function (error) {
|
fs.mkdir(webroot, function (error) {
|
||||||
if (error) if (error.code == "EEXIST") {
|
if (error) if (error.code == "EEXIST") {
|
||||||
@@ -50,28 +42,30 @@ app.post("*", (req, res, next) => {
|
|||||||
trymkdir();
|
trymkdir();
|
||||||
} else next(error);
|
} else next(error);
|
||||||
else {
|
else {
|
||||||
fs.rename(file.path, path.join(webroot, file.name), function (error) {
|
var filename = req.headers.filename || "file";
|
||||||
if (error) return void next(error);
|
var filepath = path.join(webroot, filename);
|
||||||
var url = customUrlGen?.(filecode, req) || `${req.protocol}://${filecode}.${process.env.HOSTNAME || req.hostname}`;
|
req.pipe(fs.createWriteStream(filepath));
|
||||||
res.send(url);
|
req.on("close", () => {
|
||||||
|
var url = g?.next().value || `${req.protocol}://${filecode}.${process.env.BASE_HOSTNAME || req.hostname}`;
|
||||||
|
res.type('text').send(url);
|
||||||
require("./discord-preloader.js")(url);
|
require("./discord-preloader.js")(url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(require("./antiscrape"));
|
||||||
|
|
||||||
app.get(['/', '/:code/', '/:code/*'], function(req, res, next){
|
app.get(['/', '/:code/', '/:code/*'], function(req, res, next){
|
||||||
var subdomain = req.subdomains.at(-1);
|
var subdomain = req.subdomains.at(-1);
|
||||||
var filecode = subdomain || req.params.code;
|
req.filecode = subdomain || req.params.code;
|
||||||
if (!filecode) filecode = "www";
|
if (!req.filecode) req.filecode = "www";
|
||||||
var webroot = path.join(FILES_DIR, filecode);
|
var webroot = path.join(FILES_DIR, req.filecode);
|
||||||
fs.readdir(webroot, function(error, webrootdirlist) {
|
fs.readdir(webroot, function(error, webrootdirlist) {
|
||||||
if (error) return void next(error.code == "ENOENT" ? "route" : error);
|
if (error) return void next(error.code == "ENOENT" ? "route" : error);
|
||||||
if (webrootdirlist.length > 1) {
|
if (webrootdirlist.length > 1) {
|
||||||
if (subdomain) req.url = path.join(filecode, req.url);
|
if (subdomain) req.url = path.join(req.filecode, req.url);
|
||||||
next();
|
next();
|
||||||
} else if (webrootdirlist.length == 1) {
|
} else if (webrootdirlist.length == 1) {
|
||||||
res.sendFile(webrootdirlist[0], {
|
res.sendFile(webrootdirlist[0], {
|
||||||
@@ -83,9 +77,3 @@ app.get(['/', '/:code/', '/:code/*'], function(req, res, next){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, express.static(FILES_DIR), serveIndex(FILES_DIR, {icons: true}));
|
}, express.static(FILES_DIR), serveIndex(FILES_DIR, {icons: true}));
|
||||||
|
|
||||||
|
|
||||||
app.use((req, res) => {
|
|
||||||
if (req.method == "GET") res.status(404).send("This resource does not exist.");
|
|
||||||
else res.sendStatus(405);
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user