Files
mc-tracker/src/scanner/scanner.ts

147 lines
4.1 KiB
TypeScript
Raw Normal View History

2024-01-01 03:45:00 +00:00
import Database from "better-sqlite3";
import cron from "node-cron";
import { serverManager } from "..";
import Config from "../../data/config.json";
import Server, { PingResponse } from "../server/server";
const DATA_DIR = "data";
const PINGS_TABLE = "pings";
const RECORD_TABLE = "record";
/**
* SQL Queries
*/
2024-01-01 04:11:22 +00:00
const CREATE_PINGS_TABLE = `
CREATE TABLE IF NOT EXISTS pings (
id INTEGER NOT NULL,
timestamp BIGINT NOT NULL,
ip TINYTEXT NOT NULL,
player_count MEDIUMINT NOT NULL
);
`;
const CREATE_RECORD_TABLE = `
CREATE TABLE IF NOT EXISTS record (
id INTEGER PRIMARY KEY,
2024-01-01 03:45:00 +00:00
timestamp BIGINT NOT NULL,
ip TINYTEXT NOT NULL,
player_count MEDIUMINT NOT NULL
);
`;
2024-01-01 04:11:22 +00:00
const CREATE_PINGS_INDEX = `CREATE INDEX IF NOT EXISTS ip_index ON pings (id, ip, player_count)`;
const CREATE_TIMESTAMP_INDEX = `CREATE INDEX IF NOT EXISTS timestamp_index on PINGS (id, timestamp)`;
2024-01-01 03:45:00 +00:00
const INSERT_PING = `
2024-01-01 04:11:22 +00:00
INSERT INTO ${PINGS_TABLE} (id, timestamp, ip, player_count)
VALUES (?, ?, ?, ?)
2024-01-01 03:45:00 +00:00
`;
const INSERT_RECORD = `
2024-01-01 04:11:22 +00:00
INSERT INTO ${RECORD_TABLE} (id, timestamp, ip, player_count)
VALUES (?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
timestamp = excluded.timestamp,
player_count = excluded.player_count,
ip = excluded.ip
2024-01-01 03:45:00 +00:00
`;
export default class Scanner {
private db: Database.Database;
constructor() {
console.log("Loading scanner database");
this.db = new Database(`${DATA_DIR}/db.sqlite`);
console.log("Ensuring tables exist");
this.db.exec(CREATE_PINGS_TABLE); // Ensure the pings table exists
this.db.exec(CREATE_RECORD_TABLE); // Ensure the record table exists
console.log("Ensuring indexes exist");
this.db.exec(CREATE_PINGS_INDEX); // Ensure the pings index exists
this.db.exec(CREATE_TIMESTAMP_INDEX); // Ensure the timestamp index exists
console.log("Starting server scan");
cron.schedule(Config.scanner.updateCron, () => {
this.scanServers();
});
}
/**
* Start a server scan to ping all servers.
*/
private async scanServers(): Promise<void> {
console.log(`Scanning servers ${serverManager.getServers().length}`);
// ping all servers in parallel
await Promise.all(
serverManager.getServers().map((server) => this.scanServer(server))
);
console.log("Finished scanning servers");
}
/**
* Scans a server and inserts the ping into the database.
*
* @param server the server to scan
* @returns a promise that resolves when the server has been scanned
*/
async scanServer(server: Server): Promise<void> {
//console.log(`Scanning server ${server.getIP()} - ${server.getType()}`);
let response;
let online = false;
try {
response = await server.pingServer(server);
if (response == undefined) {
return; // Server is offline
}
online = true;
} catch (err) {
console.log(`Failed to ping ${server.getIP()}`, err);
return;
}
if (!online || !response) {
return; // Server is offline
}
2024-01-01 04:11:22 +00:00
this.insertPing(server, response);
2024-01-01 03:45:00 +00:00
this.insertRecord(server, response);
}
/**
* Inserts a ping into the database.
*
* @param timestamp the timestamp of the ping
* @param ip the IP address of the server
* @param playerCount the number of players online
*/
2024-01-01 04:11:22 +00:00
private insertPing(server: Server, response: PingResponse): void {
const { timestamp, players } = response;
const id = server.getID();
const ip = server.getIP();
const onlineCount = players.online;
2024-01-01 03:45:00 +00:00
const statement = this.db.prepare(INSERT_PING);
2024-01-01 04:11:22 +00:00
statement.run(id, timestamp, ip, onlineCount); // Insert the ping into the database
2024-01-01 03:45:00 +00:00
}
/**
* Inserts a record into the database.
*
* @param server the server to insert
* @param response the response to insert
*/
private insertRecord(server: Server, response: PingResponse): void {
const { timestamp, players } = response;
2024-01-01 04:11:22 +00:00
const id = server.getID();
2024-01-01 03:45:00 +00:00
const ip = server.getIP();
const onlineCount = players.online;
const statement = this.db.prepare(INSERT_RECORD);
2024-01-01 04:11:22 +00:00
statement.run(id, timestamp, ip, onlineCount); // Insert the record into the database
2024-01-01 03:45:00 +00:00
}
}