dok/app.js
2026-03-12 09:58:27 +00:00

208 lines
4.6 KiB
JavaScript

require("dotenv").config();
const express = require("express");
const path = require("path");
const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
const http = require("http");
const { Server } = require("socket.io");
const serverRoutes = require("./routes/servers");
const registerRoutes = require("./routes/register");
const verifyRoutes = require("./routes/verify");
const characterRoutes = require("./routes/character");
const session = require("express-session");
const loginRoutes = require("./routes/login");
const launcherRoutes = require("./routes/launcher");
const buildingRoutes = require("./routes/buildings");
const app = express();
const PORT = process.env.PORT || 3000;
/* ========================
Chatserver
======================== */
const server = http.createServer(app);
const io = new Server(server);
/* ========================
Security Middleware
======================== */
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
connectSrc: ["'self'", "ws:", "wss:"],
},
},
}),
);
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
});
app.use(limiter);
app.use(
session({
secret: "dynastyofknights_secret",
resave: false,
saveUninitialized: false,
}),
);
/* ========================
Express Settings
======================== */
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));
/* ========================
Route für Ajax
======================== */
app.get("/api/building/:id", (req, res) => {
const data = {
name: "Burg",
level: 3,
description: "Das Herz deiner Stadt.",
upgradeCost: "500 Holz, 200 Stein",
history: "Die Burg wurde vor Jahrhunderten erbaut.",
};
res.json(data);
});
/* ========================
Body Parser
======================== */
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
/* ========================
Static Files
======================== */
app.use(express.static(path.join(__dirname, "public")));
/* ========================
Routes
======================== */
app.use("/", serverRoutes);
app.use("/register", registerRoutes);
app.use("/verify", verifyRoutes);
app.use("/create-character", characterRoutes);
app.use("/login", loginRoutes);
app.use("/launcher", launcherRoutes);
app.use("/", buildingRoutes);
/* ========================
404 Handler
======================== */
app.use((req, res) => {
res.status(404).send("Seite nicht gefunden");
});
/* ========================
Webseite beschleunigen
======================== */
const compression = require("compression");
app.use(compression());
/* ========================
Chat System
======================== */
let onlineUsers = {};
io.on("connection", (socket) => {
console.log("Spieler verbunden");
socket.on("register", (username) => {
socket.user = username;
onlineUsers[username] = socket.id;
io.emit("onlineUsers", Object.keys(onlineUsers));
});
socket.on("disconnect", () => {
if (socket.user) {
delete onlineUsers[socket.user];
io.emit("onlineUsers", Object.keys(onlineUsers));
}
});
socket.on("chatMessage", (data) => {
if (data.channel === "global") {
io.emit("chatMessage", {
user: socket.user,
message: data.message,
channel: "global",
});
}
if (data.channel === "guild") {
io.to("guild_" + data.guild).emit("chatMessage", {
user: socket.user,
message: data.message,
channel: "guild",
});
}
});
socket.on("whisper", (data) => {
const targetSocket = onlineUsers[data.to];
if (!targetSocket) {
socket.emit("systemMessage", {
message: data.to + " ist offline",
});
return;
}
io.to(targetSocket).emit("chatMessage", {
user: socket.user,
message: data.message,
channel: "private",
});
socket.emit("chatMessage", {
user: "(an " + data.to + ")",
message: data.message,
channel: "private",
});
});
socket.on("privateMessage", (data) => {
const target = onlineUsers[data.to];
if (target) {
io.to(target).emit("chatMessage", {
user: socket.user,
message: data.message,
channel: "private",
});
}
});
});
/* ========================
Server Start
======================== */
server.listen(PORT, () => {
console.log(`Dynasty of Knights Server läuft auf http://localhost:${PORT}`);
});