diff --git a/Dockerfile b/Dockerfile index ee22342..49d1c20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,8 +59,6 @@ EXPOSE 3000 ENV PORT 3000 -RUN yarn add @beam-australia/react-env - ENTRYPOINT yarn react-env --env APP_ENV -CMD ["node", "server.js"] \ No newline at end of file +CMD yarn start \ No newline at end of file diff --git a/src/pages/overlayold.js b/src/pages/overlayold.js deleted file mode 100644 index ece5337..0000000 --- a/src/pages/overlayold.js +++ /dev/null @@ -1,517 +0,0 @@ -import { Link, Spinner } from "@nextui-org/react"; -import { NextSeo } from "next-seo"; -import { Component } from "react"; -import PlayerStats from "../components/PlayerStats"; -import ScoreStats from "../components/ScoreStats"; -import SongInfo from "../components/SongInfo"; -import LeaderboardType from "../consts/LeaderboardType"; -import Utils from "../utils/utils"; - -import styles from "../styles/overlay.module.css"; - -export default class Overlay extends Component { - #_beatSaverURL = ""; - - constructor(props) { - super(props); - - this.cutData = []; - this.cutData.SaberA = { - count: [0, 0, 0], - totalScore: [0, 0, 0], - }; - this.cutData.SaberB = { - count: [0, 0, 0], - totalScore: [0, 0, 0], - }; - - this._mounted = false; - this.state = { - hasError: false, - - // Steam ID - id: undefined, - - // Values from the query parameters - loadingPlayerData: true, - isConnectedToSocket: false, - isValidSteamId: false, - websiteType: "ScoreSaber", - showPlayerStats: true, - showScore: false, - showSongInfo: false, - shouldReplacePlayerInfoWithScore: false, - - // Internal - loadedDuringSong: false, - socket: undefined, - data: undefined, - beatSaverData: undefined, - songInfo: undefined, - mapStarCount: undefined, - - // UI elements - isPlayerInfoVisible: false, - isVisible: false, - - // Score data - paused: true, - failed: false, - currentSongTime: 0, - currentScore: 0, - percentage: "100.00%", - SaberA: { - cutDistanceScore: 0.0, - averagePreSwing: 0.0, - averagePostSwing: 0.0, - }, - SaberB: { - cutDistanceScore: 0.0, - averagePreSwing: 0.0, - averagePostSwing: 0.0, - }, - }; - this.setupTimer(); - } - - async componentDidMount() { - if (this._mounted === true) { - return; - } - this._mounted = true; - - if (this.state.hasError) { - // Reload the page if there has been an error - console.log("There has been an error and the page was reloaded."); - return Router.reload(window.location.pathname); - } - - console.log("Initializing..."); - this.#_beatSaverURL = - document.location.origin + "/api/beatsaver/map?hash=%s"; - const urlSearchParams = new URLSearchParams(window.location.search); - const params = Object.fromEntries(urlSearchParams.entries()); - - // Check what website the player wants to use - if (params.beatleader === "true" || params.beatLeader === "true") { - this.setState({ websiteType: "BeatLeader" }); - } - - const id = params.id; - if (!id) { - // Check if the id param is valid - this.setState({ isValidSteamId: false, loadingPlayerData: false }); - return; - } - - // Checks if the steam id is valid - const isValid = await this.validateSteamId(id); - if (!isValid) { - this.setState({ isValidSteamId: false, loadingPlayerData: false }); - return; - } - this.setState({ id: id, isValidSteamId: true }); - - // Check if the player wants to disable their stats (pp, global pos, etc) - if (params.showPlayerStats === "false" || params.playerstats === "false") { - this.setState({ showPlayerStats: false }); - } - - if (this.state.showPlayerStats == true || params.playerstats == "true") { - setTimeout(async () => { - await this.updateData(id); - }, 10); // 10ms - this.setState({ isPlayerInfoVisible: true }); - } - - let shouldConnectSocket = false; - - // Check if the player wants to show their current score information - if (params.showScoreInfo === "true" || params.scoreinfo === "true") { - this.setState({ showScore: true }); - shouldConnectSocket = true; - } - - if (params.shouldReplacePlayerInfoWithScore === "true") { - this.setState({ shouldReplacePlayerInfoWithScore: true }); - } - - // Check if the player wants to show the current song - if (params.showSongInfo === "true" || params.songinfo === "true") { - this.setState({ showSongInfo: true }); - shouldConnectSocket = true; - } - - if (shouldConnectSocket) { - if (this.state.isConnectedToSocket) return; - this.connectSocket(params.socketaddress); - } - } - - // Handle Errors - static getDerivedStateFromError(error) { - return this.setState({ hasError: true }); - } - componentDidCatch(error, errorInfo) { - console.log({ error, errorInfo }); - } - // --- - - // I'd love if HTTP Status just gave this data lmao - // HttpSiraStatus(https://github.com/denpadokei/HttpSiraStatus) does give this data. - isCurrentSongTimeProvided = false; - // we don't need to reset this to false because it is highly unlikely for a player to swap mods within a browser session - - /** - * Setup the timer for the song time - */ - setupTimer() { - setInterval(() => { - if (this.isCurrentSongTimeProvided) { - return; - } - if (!this.state.paused && this.state.beatSaverData !== undefined) { - this.setState({ currentSongTime: this.state.currentSongTime + 1 }); - } - }, 1000); - } - - /** - * Update the current song time - * - * @param {[]} data The song data - */ - handleCurrentSongTime(data) { - try { - const time = data.status.performance.currentSongTime; - if (time !== undefined && time != null) { - this.isCurrentSongTimeProvided = true; - this.setState({ currentSongTime: time }); - } - } catch (e) { - // do nothing - } - } - - /** - * Fetch and update the data from the respective platform - * - * @param {string} id The steam id of the player - * @returns - */ - async updateData(id) { - const data = await fetch( - Utils.getWebsiteApi(this.state.websiteType).ApiUrl.PlayerData.replace( - "%s", - id - ), - { - headers: { - "X-Requested-With": "BeatSaber Overlay", - }, - } - ); - try { - const json = await data.json(); - this.setState({ - loadingPlayerData: false, - id: id, - data: json, - }); - } catch (e) { - // Catch error and use last known data - console.error(e); - } - } - - /** - * Checks if the given steam id is valid or not - * - * @param {id} The Steam ID of the player to validate - */ - async validateSteamId(id) { - if (id.length !== 17) { - return false; - } - const data = await fetch(`/api/validateid?steamid=${id}`); - const json = await data.json(); - return json.message === "Valid"; - } - - /** - * Setup the HTTP Status connection - */ - connectSocket(socketAddress) { - socketAddress = - (socketAddress === undefined - ? "ws://localhost" - : `ws://${socketAddress}`) + ":6557/socket"; - if (this.state.isConnectedToSocket) return; - - if (this.state.isVisible) { - this.resetData(false); - } - - console.log(`Connecting to ${socketAddress}`); - const socket = new WebSocket(socketAddress); - socket.addEventListener("open", () => { - console.log(`Connected to ${socketAddress}`); - this.setState({ isConnectedToSocket: true }); - }); - socket.addEventListener("close", () => { - console.log( - "Attempting to re-connect to the HTTP Status socket in 60 seconds." - ); - this.resetData(false); - this.setState({ isConnectedToSocket: false }); - setTimeout(() => this.connectSocket(), 60_000); - }); - socket.addEventListener("message", (message) => { - const json = JSON.parse(message.data); - this.handleCurrentSongTime(json); - if (!this.handlers[json.event]) { - console.log("Unhandled message from HTTP Status. (" + json.event + ")"); - return; - } - this.handlers[json.event](json || []); - }); - this.setState({ socket: socket }); - } - - /** - * Set the current songs beat saver url in {@link #_beatSaverURL} - * - * @param {[]} songData - */ - async setBeatSaver(songData) { - console.log("Updating BeatSaver info"); - const data = await fetch( - this.#_beatSaverURL.replace("%s", songData.levelId) - ); - const json = await data.json(); - this.setState({ beatSaverData: json }); - - const { characteristic, levelId, difficulty } = songData; - let mapHash = levelId.replace("custom_level_", ""); - let mapStars = undefined; - if (this.state.websiteType === "BeatLeader") { - mapStars = await LeaderboardType.BeatLeader.getMapStarCount( - mapHash, - difficulty.replace("+", "Plus"), - characteristic - ); - } - if (this.state.websiteType === "ScoreSaber") { - mapStars = await LeaderboardType.ScoreSaber.getMapStarCount( - mapHash, - difficulty.replace("+", "Plus"), - characteristic - ); - } - this.setState({ mapStarCount: mapStars }); - } - - /** - * Cleanup the data and get ready for the next song - * - * @param {boolean} visible Whether to show info other than the player stats - */ - async resetData(visible, loadedDuringSong = false) { - if (this.state.showPlayerStats == true) { - setTimeout(async () => { - await this.updateData(this.state.id); - }, 1000); // 1 second - } - - if (visible && this.state.shouldReplacePlayerInfoWithScore) { - this.setState({ isPlayerInfoVisible: false }); - } else { - this.setState({ isPlayerInfoVisible: true }); - } - - this.cutData = []; - this.cutData.SaberA = { - count: [0, 0, 0], - totalScore: [0, 0, 0], - }; - this.cutData.SaberB = { - count: [0, 0, 0], - totalScore: [0, 0, 0], - }; - this.setState({ - SaberA: { - cutDistanceScore: 0.0, - averagePreSwing: 0.0, - averagePostSwing: 0.0, - }, - SaberB: { - cutDistanceScore: 0.0, - averagePreSwing: 0.0, - averagePostSwing: 0.0, - }, - songInfo: undefined, - beatSaverData: undefined, - currentSongTime: 0, - currentScore: 0, - percentage: "100.00%", - isVisible: visible, - loadedDuringSong: loadedDuringSong, - mapStarCount: undefined, - }); - } - - // The HTTP Status handlers - handlers = { - hello: (data) => { - console.log("Hello from HTTP Status!"); - if ( - data.status && - data.status.beatmap && - this.state.songData === undefined - ) { - console.log("Going into level during song, resetting data."); - this.resetData(true, true); - this.setState({ songData: data, paused: false }); - if (this.state.showScore || this.state.showSongInfo) { - this.setBeatSaver(data.status.beatmap); - } - } - }, - scoreChanged: (data) => { - const { status } = data; - const { score, relativeScore } = status.performance; - let finalScore = score; - if (finalScore == 0) { - finalScore = this.state.currentScore; - } - const percent = relativeScore * 100; - this.setState({ - currentScore: finalScore, - percentage: percent.toFixed(2) + "%", - }); - }, - noteFullyCut: (data) => { - const { noteCut } = data; - - let beforeCutScore = 0.0; - let afterCutScore = 0.0; - let cutDistanceScore = 0.0; - - const cutDataSaber = this.cutData[noteCut.saberType]; - cutDataSaber.count[0]++; - cutDataSaber.count[1]++; - cutDataSaber.count[2]++; - cutDataSaber.totalScore[0] += noteCut.beforeCutScore; - cutDataSaber.totalScore[1] += noteCut.afterCutScore; - cutDataSaber.totalScore[2] += noteCut.cutDistanceScore; - beforeCutScore = cutDataSaber.totalScore[0] / cutDataSaber.count[0]; - afterCutScore = cutDataSaber.totalScore[1] / cutDataSaber.count[1]; - cutDistanceScore = cutDataSaber.totalScore[2] / cutDataSaber.count[2]; - - const cutData = this.state[noteCut.saberType]; - cutData.averagePreSwing = beforeCutScore; - cutData.averagePostSwing = afterCutScore; - cutData.cutDistanceScore = cutDistanceScore; - this.setState({ [noteCut.saberType]: cutData }); - }, - songStart: (data) => { - console.log("Going into level, resetting data."); - this.resetData(true); - this.setState({ songData: data, paused: false }); - if (this.state.showScore || this.state.showSongInfo) { - this.setBeatSaver(data.status.beatmap); - } - }, - finished: () => { - this.resetData(false); - }, - softFail: () => { - this.setState({ failed: true }); - }, - pause: () => { - this.setState({ paused: true }); - }, - resume: () => { - this.setState({ paused: false }); - }, - menu: () => { - this.resetData(false); - }, - noteCut: () => {}, - noteMissed: () => {}, - noteSpawned: () => {}, - bombMissed: () => {}, - beatmapEvent: () => {}, - energyChanged: () => {}, - obstacleEnter: () => {}, - obstacleExit: () => {}, - }; - - render() { - const { - isValidSteamId, - data, - websiteType, - showPlayerStats, - loadingPlayerData, - isPlayerInfoVisible, - shouldReplacePlayerInfoWithScore, - id, - } = this.state; - - if (loadingPlayerData) { - return ; - } - - return ( - <> - -
- {!isValidSteamId ? ( -
-

Invalid player, please visit the main page.

- - Go Home - -
- ) : ( -
- {showPlayerStats && !loadingPlayerData && isPlayerInfoVisible ? ( - shouldReplacePlayerInfoWithScore ? ( - <> - ) : ( - - ) - ) : ( - <> - )} - {this.state.showScore && this.state.isVisible ? ( - - ) : ( - <> - )} - {this.state.showSongInfo && - this.state.beatSaverData !== undefined && - this.state.isVisible ? ( - - ) : ( - <> - )} -
- )} -
- - ); - } -}