/[sudobot]/branches/6.x/src/services/LogServer.ts
ViewVC logotype

Annotation of /branches/6.x/src/services/LogServer.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 4385 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 /**
2     * This file is part of SudoBot.
3     *
4     * Copyright (C) 2021-2023 OSN Developers.
5     *
6     * SudoBot is free software; you can redistribute it and/or modify it
7     * under the terms of the GNU Affero General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * SudoBot is distributed in the hope that it will be useful, but
12     * WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU Affero General Public License for more details.
15     *
16     * You should have received a copy of the GNU Affero General Public License
17     * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18     */
19    
20     import bcrypt from "bcrypt";
21     import chalk from "chalk";
22     import { Server, Socket } from "socket.io";
23     import Client from "../core/Client";
24     import Service from "../core/Service";
25     import { LogLevel, logInfo, logStringWithLevel, logWarn } from "../utils/logger";
26    
27     export const name = "logServer";
28    
29     export default class LogServer extends Service {
30     public readonly MAX_CONNECTIONS = 5;
31     protected connections = 0;
32     private _io?: Server;
33     public readonly sockets: Array<Socket> = [];
34     public readonly attributes: Array<{ colorize?: boolean }> = [];
35    
36     constructor(client: Client) {
37     super(client);
38    
39     if (!client.configManager.systemConfig.log_server?.auto_start) {
40     return;
41     }
42    
43     this.initialize();
44     }
45    
46     get io() {
47     return this._io;
48     }
49    
50     initialize() {
51     this._io = new Server();
52     this.setupListeners();
53     }
54    
55     start() {
56     this.initialize();
57     this.listen();
58     }
59    
60     close() {
61     this.io?.close();
62     this._io = undefined;
63     }
64    
65     isAuthorized(socket: Socket) {
66     const { authorization } = socket.request.headers;
67     const [type, password] = authorization?.split(/\s+/) ?? ["", ""];
68    
69     if (type !== "Bearer") {
70     socket.send("[error] Only bearer tokens are supported!");
71     socket.disconnect(true);
72     return false;
73     }
74    
75     if (!bcrypt.compareSync(password, process.env.LOG_SERVER_PASSWORD ?? Math.random().toString())) {
76     socket.send("[error] Authentication failed");
77     socket.disconnect(true);
78     return false;
79     }
80    
81     return true;
82     }
83    
84     setupListeners() {
85     this.io?.on("connection", socket => {
86     if (this.connections >= this.MAX_CONNECTIONS) {
87     socket.disconnect();
88     return;
89     }
90    
91     this.connections++;
92     logInfo("New client connected to the log server", socket.id);
93    
94     socket.on("disconnect", reason => {
95     this.connections--;
96     logInfo("Client Disonnected from log server: ", socket.id, reason);
97     const index = this.sockets.findIndex(s => s.id === socket.id);
98    
99     if (index !== -1) {
100     this.sockets.splice(index, 1);
101     this.attributes.splice(index, 1);
102     }
103     });
104    
105     if (!this.isAuthorized(socket)) {
106     logWarn("Unauthorized client attempted to connect to the log server", socket.id);
107     return;
108     }
109    
110     const colorize = socket.request.headers["x-colorize"] === "Yes";
111    
112     socket.write(`${colorize ? chalk.cyan("[info]") : "[info]"} Connection Accepted`);
113    
114     this.sockets.push(socket);
115     this.attributes.push({
116     colorize
117     });
118     });
119     }
120    
121     send(message: string) {
122     for (const socket of this.sockets) {
123     socket.send(message);
124     }
125     }
126    
127     log(level: LogLevel, message: string) {
128     this.sockets.forEach((socket, index) => {
129     const { colorize } = this.attributes[index] ?? {};
130    
131     if (colorize) {
132     socket.send(logStringWithLevel(level, message));
133     } else {
134     socket.send(`[system:${LogLevel[level].toLowerCase()}] ${message}`);
135     }
136     });
137     }
138    
139     listen() {
140     let port = process.env.LOG_SERVER_PORT ? parseInt(process.env.LOG_SERVER_PORT) : 3500;
141     port = isNaN(port) ? 3500 : port;
142    
143     this.io?.listen(port);
144     logInfo("The log server is running at port", port);
145     }
146     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26