more websocket stuff
This commit is contained in:
parent
15c0d2403f
commit
09f7b700ca
@ -1,6 +1,6 @@
|
|||||||
import SQLiteDatabase from "better-sqlite3";
|
import SQLiteDatabase from "better-sqlite3";
|
||||||
import cron from "node-cron";
|
import cron from "node-cron";
|
||||||
import Server, { PingResponse } from "../server/server";
|
import Server from "../server/server";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { getFormattedDate } from "../utils/timeUtils";
|
import { getFormattedDate } from "../utils/timeUtils";
|
||||||
|
|
||||||
@ -125,14 +125,13 @@ export default class Database {
|
|||||||
* @param ip the IP address of the server
|
* @param ip the IP address of the server
|
||||||
* @param playerCount the number of players online
|
* @param playerCount the number of players online
|
||||||
*/
|
*/
|
||||||
public insertPing(server: Server, response: PingResponse) {
|
public insertPing(server: Server, response: Ping) {
|
||||||
const { timestamp, players } = response;
|
const { timestamp, playerCount } = response;
|
||||||
const id = server.getID();
|
const id = server.getID();
|
||||||
const ip = server.getIP();
|
const ip = server.getIP();
|
||||||
const onlineCount = players.online;
|
|
||||||
|
|
||||||
const statement = this.db.prepare(INSERT_PING);
|
const statement = this.db.prepare(INSERT_PING);
|
||||||
statement.run(id, timestamp, ip, onlineCount); // Insert the ping into the database
|
statement.run(id, timestamp, ip, playerCount); // Insert the ping into the database
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,14 +139,20 @@ export default class Database {
|
|||||||
*
|
*
|
||||||
* @param server the server to insert
|
* @param server the server to insert
|
||||||
* @param response the response to insert
|
* @param response the response to insert
|
||||||
|
* @returns true if the a new record was set, false otherwise
|
||||||
*/
|
*/
|
||||||
public insertRecord(server: Server, response: PingResponse) {
|
public insertRecord(server: Server, response: Ping): boolean {
|
||||||
const { timestamp, players } = response;
|
const { timestamp, playerCount } = response;
|
||||||
const id = server.getID();
|
const id = server.getID();
|
||||||
const ip = server.getIP();
|
const ip = server.getIP();
|
||||||
const onlineCount = players.online;
|
|
||||||
|
const oldRecord = this.getRecord(id);
|
||||||
|
if (oldRecord && oldRecord.playerCount >= playerCount) {
|
||||||
|
return false; // Don't update the record if the player count is lower
|
||||||
|
}
|
||||||
|
|
||||||
const statement = this.db.prepare(INSERT_RECORD);
|
const statement = this.db.prepare(INSERT_RECORD);
|
||||||
statement.run(id, timestamp, ip, onlineCount); // Insert the record into the database
|
statement.run(id, timestamp, ip, playerCount); // Insert the record into the database
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,16 @@ export const database = new Database();
|
|||||||
*/
|
*/
|
||||||
export const serverManager = new ServerManager();
|
export const serverManager = new ServerManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The websocket server instance.
|
||||||
|
*/
|
||||||
|
export const websocketServer = new WebsocketServer(Config.websocket.port);
|
||||||
|
|
||||||
// The scanner is responsible for scanning all servers
|
// The scanner is responsible for scanning all servers
|
||||||
new Scanner();
|
new Scanner();
|
||||||
|
|
||||||
// The websocket server is responsible for
|
// The websocket server is responsible for
|
||||||
// sending data to the client in real time
|
// sending data to the client in real time
|
||||||
new WebsocketServer(Config.websocket.port);
|
|
||||||
|
|
||||||
// serverManager.getServers().forEach((server) => {
|
// serverManager.getServers().forEach((server) => {
|
||||||
// const record = database.getRecord(server.getID());
|
// const record = database.getRecord(server.getID());
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import cron from "node-cron";
|
import cron from "node-cron";
|
||||||
import { database, serverManager } from "..";
|
import { database, serverManager, websocketServer } from "..";
|
||||||
import Server from "../server/server";
|
import Server, { ServerStatus } from "../server/server";
|
||||||
|
|
||||||
import Config from "../../data/config.json";
|
import Config from "../../data/config.json";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
@ -48,6 +48,7 @@ export default class Scanner {
|
|||||||
online = true;
|
online = true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.info(`Failed to ping ${server.getIP()}`, err);
|
logger.info(`Failed to ping ${server.getIP()}`, err);
|
||||||
|
websocketServer.sendServerError(server, ServerStatus.OFFLINE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +57,9 @@ export default class Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
database.insertPing(server, response);
|
database.insertPing(server, response);
|
||||||
database.insertRecord(server, response);
|
const isNewRecord = database.insertRecord(server, response);
|
||||||
|
|
||||||
|
// todo: send all server pings at once
|
||||||
|
websocketServer.sendNewPing(server, response, isNewRecord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { ResolvedServer, resolveDns } from "../utils/dnsResolver";
|
|||||||
const bedrockPing = require("mcpe-ping-fixed"); // Doesn't have typescript definitions
|
const bedrockPing = require("mcpe-ping-fixed"); // Doesn't have typescript definitions
|
||||||
|
|
||||||
import Config from "../../data/config.json";
|
import Config from "../../data/config.json";
|
||||||
|
import { Ping } from "../types/ping";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of server.
|
* The type of server.
|
||||||
@ -11,18 +12,9 @@ import Config from "../../data/config.json";
|
|||||||
*/
|
*/
|
||||||
export type ServerType = "PC" | "PE";
|
export type ServerType = "PC" | "PE";
|
||||||
|
|
||||||
/**
|
export enum ServerStatus {
|
||||||
* The response from a ping request to a server.
|
OFFLINE = "Unable to reach host",
|
||||||
*/
|
}
|
||||||
export type PingResponse = {
|
|
||||||
timestamp: number;
|
|
||||||
ip: string;
|
|
||||||
version?: string;
|
|
||||||
players: {
|
|
||||||
online: number;
|
|
||||||
max?: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type ServerOptions = {
|
type ServerOptions = {
|
||||||
id: number;
|
id: number;
|
||||||
@ -90,7 +82,7 @@ export default class Server {
|
|||||||
* @param server the server to ping
|
* @param server the server to ping
|
||||||
* @returns the ping response or undefined if the server is offline
|
* @returns the ping response or undefined if the server is offline
|
||||||
*/
|
*/
|
||||||
public pingServer(server: Server): Promise<PingResponse | undefined> {
|
public pingServer(server: Server): Promise<Ping | undefined> {
|
||||||
switch (server.getType()) {
|
switch (server.getType()) {
|
||||||
case "PC": {
|
case "PC": {
|
||||||
return this.pingPCServer(server);
|
return this.pingPCServer(server);
|
||||||
@ -112,9 +104,7 @@ export default class Server {
|
|||||||
* @param server the server to ping
|
* @param server the server to ping
|
||||||
* @returns the ping response or undefined if the server is offline
|
* @returns the ping response or undefined if the server is offline
|
||||||
*/
|
*/
|
||||||
private async pingPCServer(
|
private async pingPCServer(server: Server): Promise<Ping | undefined> {
|
||||||
server: Server
|
|
||||||
): Promise<PingResponse | undefined> {
|
|
||||||
if (this.dnsInfo.resolvedServer == undefined && !this.dnsInfo.hasResolved) {
|
if (this.dnsInfo.resolvedServer == undefined && !this.dnsInfo.hasResolved) {
|
||||||
try {
|
try {
|
||||||
const resolvedServer = await resolveDns(server.getIP());
|
const resolvedServer = await resolveDns(server.getIP());
|
||||||
@ -149,13 +139,10 @@ export default class Server {
|
|||||||
|
|
||||||
this.favicon = res.favicon; // Set the favicon
|
this.favicon = res.favicon; // Set the favicon
|
||||||
resolve({
|
resolve({
|
||||||
|
id: server.getID(),
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
ip: ip,
|
ip: ip,
|
||||||
version: res.version.name,
|
playerCount: res.players.online,
|
||||||
players: {
|
|
||||||
online: res.players.online,
|
|
||||||
max: res.players.max,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -167,9 +154,7 @@ export default class Server {
|
|||||||
* @param server the server to ping
|
* @param server the server to ping
|
||||||
* @returns the ping response or undefined if the server is offline
|
* @returns the ping response or undefined if the server is offline
|
||||||
*/
|
*/
|
||||||
private async pingPEServer(
|
private async pingPEServer(server: Server): Promise<Ping | undefined> {
|
||||||
server: Server
|
|
||||||
): Promise<PingResponse | undefined> {
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
bedrockPing(
|
bedrockPing(
|
||||||
server.getIP(),
|
server.getIP(),
|
||||||
@ -180,11 +165,10 @@ export default class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
|
id: server.getID(),
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
ip: server.getIP(),
|
ip: server.getIP(),
|
||||||
players: {
|
playerCount: res.currentPlayers,
|
||||||
online: res.currentPlayers,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,17 +1,61 @@
|
|||||||
import { Server } from "socket.io";
|
import { Server as SocketServer } from "socket.io";
|
||||||
|
import Server, { ServerStatus } from "../server/server";
|
||||||
|
import { Ping } from "../types/ping";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
export default class WebsocketServer {
|
export default class WebsocketServer {
|
||||||
private server: Server;
|
private server: SocketServer;
|
||||||
|
|
||||||
constructor(port: number) {
|
constructor(port: number) {
|
||||||
logger.info(`Starting websocket server on port ${port}`);
|
logger.info(`Starting websocket server on port ${port}`);
|
||||||
this.server = new Server(port);
|
this.server = new SocketServer(port);
|
||||||
|
|
||||||
this.server.on("connection", (socket) => {
|
this.server.on("connection", (socket) => {
|
||||||
logger.info("ws: Client connected");
|
logger.debug("ws: Client connected");
|
||||||
|
|
||||||
// todo: send ping data to client
|
// todo: send ping data to client
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the latest ping data for the given server to all clients.
|
||||||
|
*
|
||||||
|
* @param server the server to send the ping for
|
||||||
|
* @param pingResponse the ping data to send
|
||||||
|
* @param isNewRecord whether a new record has been set
|
||||||
|
*/
|
||||||
|
public sendNewPing(
|
||||||
|
server: Server,
|
||||||
|
pingResponse: Ping,
|
||||||
|
isNewRecord: boolean
|
||||||
|
): void {
|
||||||
|
logger.debug(`ws: Sending new ping for ${server.getName()}`);
|
||||||
|
this.server.emit("newPing", {
|
||||||
|
server: server.getID(),
|
||||||
|
timestamp: pingResponse.timestamp,
|
||||||
|
playerCount: pingResponse.playerCount,
|
||||||
|
});
|
||||||
|
if (isNewRecord) {
|
||||||
|
logger.debug(`ws: Sending new record for ${server.getName()}`);
|
||||||
|
this.server.emit("newRecord", {
|
||||||
|
server: server.getID(),
|
||||||
|
timestamp: pingResponse.timestamp,
|
||||||
|
playerCount: pingResponse.playerCount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the server status for the given server to all clients.
|
||||||
|
*
|
||||||
|
* @param server the server to send the status for
|
||||||
|
* @param status the status to send
|
||||||
|
*/
|
||||||
|
public sendServerError(server: Server, status: ServerStatus): void {
|
||||||
|
logger.debug(`ws: Sending server status for ${server.getName()}`);
|
||||||
|
this.server.emit("serverStatus", {
|
||||||
|
server: server.getID(),
|
||||||
|
status: status,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user