import { Point } from "@influxdata/influxdb-client"; import axios from "axios"; import { w3cwebsocket as WebsocketClient } from "websocket"; import { InfluxWriteAPI } from ".."; import { connectMongo } from "../db/mongo"; import { LeaderboardSchema } from "../db/schemas/leaderboard"; import { Headsets } from "../headsets"; import { normalizedRegionName } from "../utils/regionUtils"; let totalScores: number | undefined; async function update() { const response = await axios.get("https://scoresaber.com/api/players/count"); const count = response.data; const point = new Point("scoresaber") .tag("type", "player_count") .intField("value", parseInt(count)) .timestamp(new Date()); InfluxWriteAPI.writePoint(point); if (totalScores) { InfluxWriteAPI.writePoint( new Point("scoresaber") .tag("type", "score_count") .intField("value", totalScores) .timestamp(new Date()) ); } console.log(`Updated player count to ${count}`); } async function connectWebsocket() { await connectMongo(); const leaderboard = await LeaderboardSchema.findOne({ _id: "scoresaber" }); if (!leaderboard) { await LeaderboardSchema.create({ _id: "scoresaber", totalPlays: 0 }); } // set total scores to the current total plays in the database totalScores = leaderboard?.totalPlays || 0; const socket = new WebsocketClient("wss://scoresaber.com/ws"); socket.onopen = () => { console.log("Connected to websocket"); }; socket.onclose = () => { console.log("Disconnected from websocket"); setTimeout(connectWebsocket, 5000); }; socket.onerror = (error) => { console.error("Websocket error:", error); }; socket.onmessage = async (message) => { const data = message.data; let json; try { json = JSON.parse(data.toString()); } catch (e) { return; } const commandName = json.commandName; const commandData = json.commandData; if (commandName == "score") { const { score, leaderboard } = commandData; if (!totalScores) { throw new Error("totalScores is undefined"); } totalScores++; const { id, hmd, baseScore, missedNotes, badCuts, rank, maxCombo, leaderboardPlayerInfo: player, pp, } = score; const { maxScore, stars, id: leaderboardId } = leaderboard; const hmdName = Headsets[hmd] || "Unknown"; const countryId = normalizedRegionName(player.country) || "Unknown"; // Update the leaderboard data in the database await LeaderboardSchema.updateOne( { _id: "scoresaber" }, { $set: { totalPlays: totalScores, }, } ).exec(); const scorePoint = new Point("scoresaber") .tag("type", "score") .intField("id", id) .timestamp(new Date()); if (baseScore && maxScore) { scorePoint.floatField("acc", ((baseScore / maxScore) * 100).toFixed(2)); } if (stars) { scorePoint.floatField("stars", stars); } if (pp) { scorePoint.floatField("pp", pp.toFixed(2)); } if (missedNotes) { scorePoint.intField("missed_notes", missedNotes); } if (badCuts) { scorePoint.intField("bad_cuts", badCuts); } if (rank) { scorePoint.intField("rank", rank); } // if (leaderboardId) { // scorePoint.intField("leaderboard_id", leaderboardId); // } if (hmdName) { scorePoint.stringField("hmd", hmdName); } if (countryId) { scorePoint.stringField("country", countryId); } if (maxCombo) { scorePoint.intField("max_combo", maxCombo); } //scorePoint.intField("player_id", player.id); // Write the data to influx InfluxWriteAPI.writePoint(scorePoint); } }; } update(); connectWebsocket(); setInterval(update, 60_000); // 1 minute