more limits
This commit is contained in:
parent
5df9a65ecf
commit
bb85b00b9c
@ -6,5 +6,4 @@ todo:
|
||||
|
||||
- better replies
|
||||
- mousing not in react?
|
||||
- fix scrollback issues
|
||||
- more limits
|
||||
- fix scrollback issues
|
16
server/package-lock.json
generated
16
server/package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"busboy": "^1.6.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"hash-through": "^0.1.16",
|
||||
"mime": "^3.0.0",
|
||||
"mongodb": "^6.3.0",
|
||||
@ -396,6 +397,15 @@
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express-async-errors": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
|
||||
"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"express": "^4.16.2"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/cookie": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||
@ -1684,6 +1694,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"express-async-errors": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
|
||||
"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
|
||||
"requires": {}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"busboy": "^1.6.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"hash-through": "^0.1.16",
|
||||
"mime": "^3.0.0",
|
||||
"mongodb": "^6.3.0",
|
||||
|
@ -1 +1,2 @@
|
||||
export const DATA_DIR = process.env.DATA_DIR || "data";
|
||||
export const DATA_DIR = process.env.DATA_DIR || "data";
|
||||
export const MIN_FREE_GB = process.env.MIN_FREE_GB ? Number(process.env.MIN_FREE_GB) : 10;
|
@ -1,4 +1,5 @@
|
||||
import express from "express";
|
||||
import "express-async-errors";
|
||||
import busboy from "busboy";
|
||||
import HashThrough from "hash-through";
|
||||
import { to36 } from "1636";
|
||||
@ -9,8 +10,8 @@ import mime from "mime";
|
||||
|
||||
import Message from "./models/Message.js";
|
||||
import Emoji from "./models/Emoji.js";
|
||||
import { DATA_DIR } from "./constants.js";
|
||||
import { shuffleArray } from "./util.js";
|
||||
import { DATA_DIR, MIN_FREE_GB } from "./constants.js";
|
||||
import { df } from "./util.js";
|
||||
|
||||
export var router = express.Router();
|
||||
|
||||
@ -32,7 +33,12 @@ router.get("/messages", (req, res, next) => {
|
||||
Message.getMessages({query, secret: req.query.secret}).then(messages => res.send(messages)).catch(next);
|
||||
});
|
||||
|
||||
router.post("/upload", (req, res, next) => {
|
||||
router.post("/upload", async (req, res, next) => {
|
||||
var free = await df(DATA_DIR);
|
||||
if (free < MIN_FREE_GB) {
|
||||
res.sendStatus(507);
|
||||
return;
|
||||
}
|
||||
var boi = busboy({headers: req.headers});
|
||||
var codes = [];
|
||||
boi.on("file", (name, file, info) => {
|
||||
@ -98,16 +104,19 @@ router.get("/emojis", (req, res, next) => {
|
||||
});
|
||||
|
||||
|
||||
router.put("/emoji/:name", express.raw({limit: "1mb", type: ()=>true}), async (req, res, next) => {
|
||||
try {
|
||||
var emoji = new Emoji({
|
||||
name: req.params.name,
|
||||
type: req.query.type,
|
||||
data: req.body
|
||||
});
|
||||
await emoji.save();
|
||||
res.sendStatus(201);
|
||||
} catch (error) {next(error)}
|
||||
router.put("/emoji/:name", express.raw({limit: "1mb", type: ()=>true}), async (req, res) => {
|
||||
var free = await df(DATA_DIR);
|
||||
if (free < MIN_FREE_GB) {
|
||||
res.sendStatus(507);
|
||||
return;
|
||||
}
|
||||
var emoji = new Emoji({
|
||||
name: req.params.name,
|
||||
type: req.query.type,
|
||||
data: req.body
|
||||
});
|
||||
await emoji.save();
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { Server as SocketIOServer } from "socket.io";
|
||||
import { randomUUID } from "crypto";
|
||||
import server from "./server.js";
|
||||
import Message from "./models/Message.js";
|
||||
import { Quota } from "./util.js";
|
||||
|
||||
export var io = new SocketIOServer(server, {
|
||||
cors: {origin: "*"},
|
||||
@ -11,8 +12,19 @@ export var io = new SocketIOServer(server, {
|
||||
|
||||
io.on("connection", socket => {
|
||||
socket.ip = socket.handshake.headers["x-forwarded-for"]?.split(',')[0] || socket.handshake.address;
|
||||
console.debug("connection from", socket.ip, "socket id", socket.id);
|
||||
console.log("connect", socket.ip, socket.id);
|
||||
socket.quotas = {
|
||||
user: new Quota(1000, 1000*60*60),
|
||||
message: new Quota(30, 60000)
|
||||
};
|
||||
socket.on("disconnect", reason => {
|
||||
console.log("disconnect", socket.id, reason);
|
||||
for (var quota in socket.quotas) {
|
||||
socket.quotas[quota].destroy();
|
||||
}
|
||||
})
|
||||
socket.on("user", user => {
|
||||
if (socket.quotas.user.spend()) return;
|
||||
user = {
|
||||
name: user.name?.toString().trim().substring(0,32),
|
||||
color: user.color?.toString().trim().substring(0,32),
|
||||
@ -23,7 +35,7 @@ io.on("connection", socket => {
|
||||
ip: socket.ip,
|
||||
agent: socket.handshake.headers["user-agent"]
|
||||
};
|
||||
console.debug("user", user);
|
||||
console.debug("user", JSON.stringify(user));
|
||||
socket.data.user = user;
|
||||
broadcastUsers();
|
||||
});
|
||||
@ -34,6 +46,7 @@ io.on("connection", socket => {
|
||||
broadcastUsers();
|
||||
});
|
||||
socket.on("message", message => {
|
||||
if (socket.quotas.message.spend()) return;
|
||||
newMessage({
|
||||
content: message.content?.toString().substring(0,10000),
|
||||
user: {...socket.data.user}
|
||||
|
@ -6,3 +6,31 @@ export function shuffleArray(array) {
|
||||
array[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
export class Quota {
|
||||
constructor(limit, resetInterval) {
|
||||
this.limit = limit;
|
||||
this.count = limit;
|
||||
this.interval = setInterval(() => {
|
||||
this.count = this.limit;
|
||||
}, resetInterval);
|
||||
}
|
||||
destroy () {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
spend() {
|
||||
return --this.count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import { execFile } from "child_process";
|
||||
import { promisify } from "util";
|
||||
var exec = promisify(execFile);
|
||||
var free, ldft;
|
||||
export async function df(path) {
|
||||
if (Date.now() - ldft < 1000*60) return free;
|
||||
ldft = Date.now();
|
||||
var {stdout} = await exec("df", ["--output=avail", "--block-size=1G", path]);
|
||||
return free = Number(stdout.toString().match(/\d+/)[0]);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user