Merge c52a57d486 into 9169a647cb
This commit is contained in:
commit
9df6dbe797
@ -770,56 +770,6 @@ class Monitor extends BeanModel {
|
||||
bean.duration = beatInterval;
|
||||
throw new Error("No heartbeat in the time window");
|
||||
}
|
||||
} else if (this.type === "steam") {
|
||||
const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/";
|
||||
const steamAPIKey = await setting("steamAPIKey");
|
||||
const filter = `addr\\${this.hostname}:${this.port}`;
|
||||
|
||||
if (!steamAPIKey) {
|
||||
throw new Error("Steam API Key not found");
|
||||
}
|
||||
|
||||
let res = await axios.get(steamApiUrl, {
|
||||
timeout: this.timeout * 1000,
|
||||
headers: {
|
||||
Accept: "*/*",
|
||||
},
|
||||
httpsAgent: new https.Agent({
|
||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
||||
rejectUnauthorized: !this.getIgnoreTls(),
|
||||
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
|
||||
}),
|
||||
httpAgent: new http.Agent({
|
||||
maxCachedSessions: 0,
|
||||
}),
|
||||
maxRedirects: this.maxredirects,
|
||||
validateStatus: (status) => {
|
||||
return checkStatusCode(status, this.getAcceptedStatuscodes());
|
||||
},
|
||||
params: {
|
||||
filter: filter,
|
||||
key: steamAPIKey,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.data.response && res.data.response.servers && res.data.response.servers.length > 0) {
|
||||
bean.status = UP;
|
||||
bean.msg = res.data.response.servers[0].name;
|
||||
|
||||
try {
|
||||
bean.ping = await ping(
|
||||
this.hostname,
|
||||
PING_COUNT_DEFAULT,
|
||||
"",
|
||||
true,
|
||||
this.packetSize,
|
||||
PING_GLOBAL_TIMEOUT_DEFAULT,
|
||||
PING_PER_REQUEST_TIMEOUT_DEFAULT
|
||||
);
|
||||
} catch (_) {}
|
||||
} else {
|
||||
throw new Error("Server not found on Steam");
|
||||
}
|
||||
} else if (this.type === "docker") {
|
||||
log.debug("monitor", `[${this.name}] Prepare Options for Axios`);
|
||||
|
||||
|
||||
84
server/monitor-types/steam.js
Normal file
84
server/monitor-types/steam.js
Normal file
@ -0,0 +1,84 @@
|
||||
const { MonitorType } = require("./monitor-type");
|
||||
const {
|
||||
UP,
|
||||
PING_COUNT_DEFAULT,
|
||||
PING_GLOBAL_TIMEOUT_DEFAULT,
|
||||
PING_PER_REQUEST_TIMEOUT_DEFAULT,
|
||||
} = require("../../src/util");
|
||||
const { ping, checkStatusCode, setting } = require("../util-server");
|
||||
const axios = require("axios");
|
||||
const https = require("https");
|
||||
const http = require("http");
|
||||
const crypto = require("crypto");
|
||||
|
||||
class SteamMonitorType extends MonitorType {
|
||||
name = "steam";
|
||||
steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async check(monitor, heartbeat, _server) {
|
||||
const res = await this.getServerList(monitor);
|
||||
if (res.data.response && res.data.response.servers && res.data.response.servers.length > 0) {
|
||||
heartbeat.status = UP;
|
||||
heartbeat.msg = res.data.response.servers[0].name;
|
||||
|
||||
try {
|
||||
heartbeat.ping = await ping(
|
||||
monitor.hostname,
|
||||
PING_COUNT_DEFAULT,
|
||||
"",
|
||||
true,
|
||||
monitor.packetSize,
|
||||
PING_GLOBAL_TIMEOUT_DEFAULT,
|
||||
PING_PER_REQUEST_TIMEOUT_DEFAULT
|
||||
);
|
||||
} catch (_) {}
|
||||
} else {
|
||||
throw new Error("Server not found on Steam");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server list from Steam API
|
||||
* @param {Monitor} monitor Monitor object
|
||||
* @returns {Promise<axios.AxiosResponse>} Axios response object containing server list data
|
||||
* @throws {Error} If Steam API Key is not configured
|
||||
*/
|
||||
async getServerList(monitor) {
|
||||
const steamAPIKey = await setting("steamAPIKey");
|
||||
const filter = `addr\\${monitor.hostname}:${monitor.port}`;
|
||||
|
||||
if (!steamAPIKey) {
|
||||
throw new Error("Steam API Key not found");
|
||||
}
|
||||
const options = {
|
||||
timeout: monitor.timeout * 1000,
|
||||
headers: {
|
||||
Accept: "*/*",
|
||||
},
|
||||
httpsAgent: new https.Agent({
|
||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
||||
rejectUnauthorized: !monitor.ignoreTls,
|
||||
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
|
||||
}),
|
||||
httpAgent: new http.Agent({
|
||||
maxCachedSessions: 0,
|
||||
}),
|
||||
maxRedirects: monitor.maxredirects,
|
||||
validateStatus: (status) => {
|
||||
return checkStatusCode(status, monitor.getAcceptedStatuscodes());
|
||||
},
|
||||
params: {
|
||||
filter: filter,
|
||||
key: steamAPIKey,
|
||||
},
|
||||
};
|
||||
return await axios.get(this.steamApiUrl, options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SteamMonitorType,
|
||||
};
|
||||
@ -114,6 +114,7 @@ class UptimeKumaServer {
|
||||
UptimeKumaServer.monitorTypeList["tailscale-ping"] = new TailscalePing();
|
||||
UptimeKumaServer.monitorTypeList["websocket-upgrade"] = new WebSocketMonitorType();
|
||||
UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType();
|
||||
UptimeKumaServer.monitorTypeList["steam"] = new SteamMonitorType();
|
||||
UptimeKumaServer.monitorTypeList["postgres"] = new PostgresMonitorType();
|
||||
UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType();
|
||||
UptimeKumaServer.monitorTypeList["smtp"] = new SMTPMonitorType();
|
||||
@ -564,6 +565,7 @@ const { RealBrowserMonitorType } = require("./monitor-types/real-browser-monitor
|
||||
const { TailscalePing } = require("./monitor-types/tailscale-ping");
|
||||
const { WebSocketMonitorType } = require("./monitor-types/websocket-upgrade");
|
||||
const { DnsMonitorType } = require("./monitor-types/dns");
|
||||
const { SteamMonitorType } = require("./monitor-types/steam");
|
||||
const { PostgresMonitorType } = require("./monitor-types/postgres");
|
||||
const { MqttMonitorType } = require("./monitor-types/mqtt");
|
||||
const { SMTPMonitorType } = require("./monitor-types/smtp");
|
||||
|
||||
104
test/backend-test/monitors/test-steam.js
Normal file
104
test/backend-test/monitors/test-steam.js
Normal file
@ -0,0 +1,104 @@
|
||||
process.env.UPTIME_KUMA_HIDE_LOG = ["info_db", "info_server"].join(",");
|
||||
|
||||
const { describe, test, before, after } = require("node:test");
|
||||
const assert = require("node:assert");
|
||||
const express = require("express");
|
||||
const { UP, PENDING } = require("../../../src/util");
|
||||
const { SteamMonitorType } = require("../../../server/monitor-types/steam");
|
||||
const { setSetting } = require("../../../server/util-server");
|
||||
const TestDB = require("../../mock-testdb");
|
||||
|
||||
const testDb = new TestDB();
|
||||
const TEST_PORT = 30158;
|
||||
let mockServer;
|
||||
|
||||
describe("Steam Monitor", () => {
|
||||
before(async () => {
|
||||
await testDb.create();
|
||||
await setSetting("steamAPIKey", "test-steam-api-key");
|
||||
|
||||
// Create shared mock Steam API server with different endpoints
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.get("/GetServerList/", (req, res) => {
|
||||
res.json({
|
||||
response: {
|
||||
servers: [
|
||||
{
|
||||
name: "Test Game Server",
|
||||
addr: "127.0.0.1:27015",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
app.get("/EmptyGetServerList/", (req, res) => {
|
||||
res.json({
|
||||
response: {
|
||||
servers: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
mockServer = await new Promise((resolve) => {
|
||||
const server = app.listen(TEST_PORT, () => resolve(server));
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
if (mockServer) {
|
||||
await new Promise((resolve) => mockServer.close(resolve));
|
||||
}
|
||||
await testDb.destroy();
|
||||
});
|
||||
|
||||
test("check() sets status to UP when Steam API returns valid server response", async () => {
|
||||
const steamMonitor = new SteamMonitorType();
|
||||
steamMonitor.steamApiUrl = `http://127.0.0.1:${TEST_PORT}/GetServerList/`;
|
||||
|
||||
const monitor = {
|
||||
hostname: "127.0.0.1",
|
||||
port: 27015,
|
||||
timeout: 2,
|
||||
packetSize: 56,
|
||||
ignoreTls: false,
|
||||
maxredirects: 10,
|
||||
getAcceptedStatuscodes: () => ["200-299"],
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
msg: "",
|
||||
status: PENDING,
|
||||
ping: null,
|
||||
};
|
||||
|
||||
await steamMonitor.check(monitor, heartbeat, {});
|
||||
|
||||
assert.strictEqual(heartbeat.status, UP);
|
||||
assert.strictEqual(heartbeat.msg, "Test Game Server");
|
||||
// Note: ping may be null or a value depending on if ICMP ping succeeds
|
||||
});
|
||||
|
||||
test("check() throws error when Steam API returns empty server list", async () => {
|
||||
const steamMonitor = new SteamMonitorType();
|
||||
steamMonitor.steamApiUrl = `http://127.0.0.1:${TEST_PORT}/EmptyGetServerList/`;
|
||||
|
||||
const monitor = {
|
||||
hostname: "127.0.0.1",
|
||||
port: 27015,
|
||||
timeout: 2,
|
||||
ignoreTls: false,
|
||||
maxredirects: 10,
|
||||
getAcceptedStatuscodes: () => ["200-299"],
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
msg: "",
|
||||
status: PENDING,
|
||||
};
|
||||
|
||||
await assert.rejects(steamMonitor.check(monitor, heartbeat, {}), {
|
||||
message: "Server not found on Steam",
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user