summary refs log tree commit diff
diff options
context:
space:
mode:
authorWlodekM <[email protected]>2024-11-26 09:51:39 +0200
committerWlodekM <[email protected]>2024-11-26 09:51:39 +0200
commitae159f6d6cb2d5ab933730a3c07903452df8c1ef (patch)
treeeb289275e861578632003e5b983213aeb320cedb
parent2fb9a1cae1e2b2dc59f529e46965719367f53964 (diff)
begin rewrite
-rw-r--r--.vscode/settings.json3
-rw-r--r--config.ini6
-rw-r--r--newindex.js1
-rw-r--r--oldindex.js (renamed from index.js)0
-rw-r--r--package.json1
-rw-r--r--pnpm-lock.yaml27
-rw-r--r--server.ts (renamed from server.js)184
-rw-r--r--user.js8
8 files changed, 137 insertions, 93 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b943dbc
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "deno.enable": true
+}
\ No newline at end of file
diff --git a/config.ini b/config.ini
index ffd91e1..5fc55eb 100644
--- a/config.ini
+++ b/config.ini
@@ -19,11 +19,11 @@ annonFormat = "Anonymous#[num]"
 
 [profanity]
 filter = true
-removeWords = ["butt", "arse", "balls", "dick"]
-addWords = ["kys"]
+removeWords = butt, arse, balls, dick
+addWords = kys
 
 [channels]
-channels = ["home", "off-topic", "random", "safe"]
+channels = home, off-topic, random, safe
 
 [channel-home]
 ; You can set settings like profanity for specific channels
diff --git a/newindex.js b/newindex.js
index 536264f..a2d2763 100644
--- a/newindex.js
+++ b/newindex.js
@@ -1,4 +1,5 @@
 import Server from './server.js';
 import ini from "ini"
+import fs from "fs"
 
 const server = new Server(ini.parse(String(fs.readFileSync("config.ini"))))
diff --git a/index.js b/oldindex.js
index 6c17622..6c17622 100644
--- a/index.js
+++ b/oldindex.js
diff --git a/package.json b/package.json
index 06f596a..344cf6b 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
     },
     "dependencies": {
         "@2toad/profanity": "^2.2.0",
+        "@types/node": "^22.10.0",
         "cuid": "^3.0.0",
         "ini": "^5.0.0",
         "ws": "^8.17.1"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3a57313..be20854 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,12 +11,18 @@ importers:
       '@2toad/profanity':
         specifier: ^2.2.0
         version: 2.5.0
+      '@types/node':
+        specifier: ^22.10.0
+        version: 22.10.0
       cuid:
         specifier: ^3.0.0
         version: 3.0.0
       ini:
         specifier: ^5.0.0
         version: 5.0.0
+      typescript:
+        specifier: ^5.0.0
+        version: 5.6.3
       ws:
         specifier: ^8.17.1
         version: 8.18.0
@@ -40,6 +46,9 @@ packages:
   '@types/[email protected]':
     resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==}
 
+  '@types/[email protected]':
+    resolution: {integrity: sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==}
+
   '@types/[email protected]':
     resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==}
 
@@ -59,9 +68,17 @@ packages:
     engines: {node: '>=14'}
     hasBin: true
 
+  [email protected]:
+    resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
   [email protected]:
     resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
 
+  [email protected]:
+    resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
+
   [email protected]:
     resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
     engines: {node: '>=10.0.0'}
@@ -86,9 +103,13 @@ snapshots:
     dependencies:
       undici-types: 5.26.5
 
+  '@types/[email protected]':
+    dependencies:
+      undici-types: 6.20.0
+
   '@types/[email protected]':
     dependencies:
-      '@types/node': 20.12.14
+      '@types/node': 22.10.0
 
   [email protected]:
     dependencies:
@@ -101,6 +122,10 @@ snapshots:
 
   [email protected]: {}
 
+  [email protected]: {}
+
   [email protected]: {}
 
+  [email protected]: {}
+
   [email protected]: {}
diff --git a/server.js b/server.ts
index e5653c8..f47abb2 100644
--- a/server.js
+++ b/server.ts
@@ -2,107 +2,79 @@ import { WebSocketServer } from "ws";
 import { profanity } from "@2toad/profanity";
 import { commands } from "./commands.js";
 import * as accounts from "./accounts.js";
-import fs from "fs";
+import fs from "node:fs";
 import User from "./user.js";
 import handleJsonMessage from './jsondata.js'
+import { EventEmitter } from "node:events";
 
-export default class Server {
-    sendInChannel(msg, channel, server=this) {
-        // console.log('this is a', this)
-        for (const userID in server.users) {
-            const user = server.users[userID];
-            if (user.channel == channel) user.socket.send(msg);
-        }
-    }
+class Events { // JSON events for clients
     
-    format(txt) {
-        txt = String(txt);
-        txt = txt.replaceAll("$(serverName)$", this.config.name);
-        txt = txt.replaceAll("$(userCount)$", Object.keys(this.users).length);
-        for (const configName in this.config) {
-            if (Object.prototype.hasOwnProperty.call(this.config, configName)) {
-                const configValue = this.config[configName];
-                if(typeof configValue != 'string' && typeof configValue != 'number') continue;
-                txt = txt.replaceAll(`$(${configName})$`, configValue);
-            }
-        }
-        return txt;
-    }
-    
-    updateUsers() {
-        Object.keys(this.users).forEach((user) => {
-            if (user.subscribedToUsers) {
-                user.socket.send(
-                    `:json.sub<users>:${JSON.stringify(
-                        Object.values(this.users).map((usr) => {
-                            return {
-                                username: usr.username,
-                                nickname: usr.nickname,
-                                t: usr.t,
-                                channel: user.channel,
-                                displayName: user.name(),
-                            };
-                        })
-                    )}`
-                );
-            }
-        });
-    }
+}
 
-    /**
-     * @typedef ServerConfig
-     * @property {Number} port
-     * @property {String} name
-     * @property {String} motd
-     * @property {String} fullMessage
-     * @property {Number} max
-     * 
-     * @typedef Config
-     * @property {ServerConfig} server
-     */
+type ServerConfig = {
+    port: number
+    name: string
+    motd: string
+    fullMessage: string
+    max: number
+}
+
+type AccountsConfig = {
+    owner: string
+    saveIP: boolean
+    requireLogin: boolean
+    annonFormat: boolean
+}
+
+type ProfanityConfig = {
+    filter: boolean
+    removeWords: string
+    addWords: string
+}
+
+type ChannelsConfig = {
+    channels: string
+}
 
+type Config = {
+    server: ServerConfig
+    accounts: AccountsConfig
+    channels: ChannelsConfig
+    profanity: ProfanityConfig
+}
+
+export default class Server {
+    config: Config;
+    channels: string[];
+    users: Map<string, User> = new Map();
+    accounts = accounts;
+    ws: WebSocketServer&EventEmitter;
     /**
      * A wsChat server
-     * @param {{
-     *  name: String,
-     *  motd: String,
-     *  max: Number,
-     *  owner: String,
-     *  saveIP: Boolean,
-     *  requireLogin: Boolean,
-     *  profanity: Boolean,
-     *  profanityRemoveWords: String[],
-     *  profanityAddWords: String[],
-     *  fullMessage: String,
-     *  annonFormat: String,
-     *  port: Number,
-     *  channels: String[],
-     *  annonChannels: String[]
-     * }} config
      */
-    constructor (config) {
+    constructor (config: Config) {
         this.config = config;
-        this.channels = this.config.channels;
-        this.annonChannels = this.config.annonChannels;
-        this.users = []
-        this.accounts = accounts;
+        this.channels = this.config.channels.channels.split(/, */g);
+        // this.annonChannels = this.config.annonChannels.split(/, */g);
         this.ws = new WebSocketServer({
-            port: this.config.port,
+            port: this.config.server.port,
         });
 
-        if (this.config.profanityRemoveWords) profanity.removeWords(this.config.profanityRemoveWords);
-        if (this.config.profanityAddWords) profanity.addWords(this.config.profanityAddWords);
+        if (this.config.profanity.removeWords) profanity.removeWords(this.config.profanity.removeWords.split(/, */g));
+        if (this.config.profanity.addWords) profanity.addWords(this.config.profanity.addWords.split(/, */g));
+
+        let server = this;
 
-        let server = this
+        if (!fs.existsSync("db/bannedIps.json")) fs.writeFileSync("db/bannedIps.json", "{}");
 
-        this.ws.on("connection", (socket, request) => {
+        this.ws.on("connection", (socket: WebSocket, request) => {
             try {
-                if (server.config.max && Object.keys(server.users).length >= server.config.max) {
-                    socket.send(server.format(server.config.fullMessage ?? "Sorry, but the server is full right now, come back later"));
+                if (server.config.server.max && Object.keys(server.users).length >= server.config.server.max) {
+                    socket.send(server.format(server.config.server.fullMessage ?? "Sorry, but the server is full right now, come back later"));
                     socket.close(1001, "Server full");
                     return;
                 }
-                const user = new User(request, socket, server)
+                const user: User = new User(request, socket, server)
                 server.users[user.id] = user
                 let ipBanList = JSON.parse(String(fs.readFileSync("db/bannedIps.json")));
                 if (ipBanList[user.ip]) {
@@ -110,7 +82,7 @@ export default class Server {
                     socket.close(1002, "Banned");
                     return;
                 }
-                socket.send(server.format(server.config.motd));
+                socket.send(server.format(server.config.server.motd));
                 console.info(`${user.name()}[${user.id}] joined the server!`);
                 server.sendInChannel(`${user.name()} joined.`, server.users[user.id].channel);
                 server.updateUsers();
@@ -153,9 +125,9 @@ export default class Server {
                         return;
                     }
                     if(handleJsonMessage(server, rawData, user)) return;
-                    if (server.config.requireLogin && user.guest && !server.annonChannels.includes(user.channel)) return socket.send("This server requires you to log in, use /login <username> <password> to log in or /register <username> <password> to make an account.");
+                    if (server.config.accounts.requireLogin && user.guest && !server.annonChannels.includes(user.channel)) return socket.send("This server requires you to log in, use /login <username> <password> to log in or /register <username> <password> to make an account.");
                     profanity.options.grawlixChar = "*";
-                    if (!server.config.profanity) rawData = profanity.censor(String(rawData));
+                    if (server.config.profanity.filter) rawData = profanity.censor(String(rawData));
                     if (rawData.length < 1) return socket.send("Error: message too short!");
                     if (rawData.length >= 2000) return socket.send("Error: message too long!");
                     server.sendInChannel(`${user.admin ? '[ADMIN] ' : ''}<${user.name()}${user.guest ? " (guest)" : ""}> ${rawData}`, user.channel);
@@ -170,4 +142,46 @@ export default class Server {
             console.info("Server started!");
         });
     }
+
+    sendInChannel(msg, channel, server=this) {
+        // console.log('this is a', this)
+        for (const userID in server.users) {
+            const user = server.users[userID];
+            if (user.channel == channel) user.socket.send(msg);
+        }
+    }
+    
+    format(txt) {
+        txt = String(txt);
+        txt = txt.replaceAll("$(serverName)$", this.config.server.name);
+        txt = txt.replaceAll("$(userCount)$", Object.keys(this.users).length);
+        for (const configName in this.config.server) {
+            if (Object.prototype.hasOwnProperty.call(this.config.server, configName)) {
+                const configValue = this.config.server[configName];
+                if(typeof configValue != 'string' && typeof configValue != 'number') continue;
+                txt = txt.replaceAll(`$(${configName})$`, configValue);
+            }
+        }
+        return txt;
+    }
+    
+    updateUsers() {
+        Object.keys(this.users).forEach((user) => {
+            if (user.subscribedToUsers) {
+                user.socket.send(
+                    `:json.sub<users>:${JSON.stringify(
+                        Object.values(this.users).map((usr) => {
+                            return {
+                                username: usr.username,
+                                nickname: usr.nickname,
+                                t: usr.t,
+                                channel: user.channel,
+                                displayName: user.name(),
+                            };
+                        })
+                    )}`
+                );
+            }
+        });
+    }
 }
\ No newline at end of file
diff --git a/user.js b/user.js
index d3254f7..c801659 100644
--- a/user.js
+++ b/user.js
@@ -6,14 +6,14 @@ import cuid from "cuid";
 export default class User {
     /**
      * the user class
-     * @param {import("http").IncomingMessage} request request
+     * @param {import("node:http").IncomingMessage} request request
      * @param {WebSocket} socket socket
-     * @param {import("./server.js").Server} server the server
+     * @param {import("./server.ts").Server} server the server
      */
     constructor (request, socket, server) {
         this.id = cuid();
-        let anonID = getRandomInt(0, 99999);
-        let annonNum = "0".repeat(5 - anonID.toString().length) + anonID.toString()
+        const anonID = getRandomInt(0, 99999);
+        const annonNum = "0".repeat(5 - anonID.toString().length) + anonID.toString()
         this.username = server.config.annonFormat ? server.config.annonFormat.replace('[num]', annonNum) : 'Anonymous' + annonNum;
         this.nickname = server.config.annonFormat ? server.config.annonFormat.replace('[num]', annonNum) : 'Anonymous' + annonNum;
         this.guest = true;