2024-04-25 06:11:06 +00:00
|
|
|
// ==UserScript==
|
|
|
|
// @name ScoreSaber Utils
|
|
|
|
// @namespace https://ssu.fascinated.cc
|
|
|
|
// @version 1.0.0
|
|
|
|
// @description Useful additions to ScoreSaber!
|
|
|
|
// @author Fascinated
|
|
|
|
// @match https://scoresaber.com/*
|
|
|
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=scoresaber.com
|
|
|
|
// @license MIT
|
|
|
|
// @updateURL https://git.fascinated.cc/Fascinated/ScoreSaberUtils-Backend/raw/branch/master/scoresaber-utils.user.js
|
|
|
|
// @downloadURL https://git.fascinated.cc/Fascinated/ScoreSaberUtils-Backend/raw/branch/master/scoresaber-utils.user.js
|
2024-04-25 06:34:22 +00:00
|
|
|
// @run-at document-end
|
2024-04-25 06:11:06 +00:00
|
|
|
// ==/UserScript==
|
|
|
|
|
2024-04-25 06:34:22 +00:00
|
|
|
let loaded = false;
|
|
|
|
|
2024-04-25 06:11:06 +00:00
|
|
|
/**
|
|
|
|
* Fetches the player from ScoreSaber Utils.
|
|
|
|
*
|
|
|
|
* @param {string} id the player's ID
|
|
|
|
* @returns the player's data
|
|
|
|
*/
|
|
|
|
async function fetchPlayer(id) {
|
|
|
|
const response = await fetch(`https://ssu.fascinated.cc/account/${id}`);
|
|
|
|
return await response.json();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles the player page logic.
|
|
|
|
*/
|
|
|
|
async function playerPage() {
|
2024-04-25 06:34:22 +00:00
|
|
|
console.log("Player page loaded!");
|
2024-04-25 06:11:06 +00:00
|
|
|
const id = window.location.pathname.split("/")[2];
|
|
|
|
const player = await fetchPlayer(id);
|
|
|
|
|
|
|
|
addStat(
|
|
|
|
"+1 PP",
|
|
|
|
player.rawPerGlobalPerformancePoints.toFixed(2) + "pp",
|
|
|
|
"The amount of pp to increase the global pp by 1pp"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts a stat into the player's stats.
|
|
|
|
*
|
|
|
|
* @param {string} stat The stat name
|
|
|
|
* @param {string} value The stat value
|
|
|
|
* @param {string} hoverText The hover text
|
|
|
|
*/
|
|
|
|
function addStat(stat, value, hoverText) {
|
|
|
|
const statsElement = document.getElementsByClassName("stats-container")[0];
|
|
|
|
const svelteClass = statsElement.getAttribute("class").split(" ")[1];
|
|
|
|
|
|
|
|
const statElement = document.createElement("div");
|
|
|
|
statElement.className = `stat-item ${svelteClass}`;
|
|
|
|
statElement.innerHTML = `
|
|
|
|
<span class="stat-title ${svelteClass}">${stat}</span>
|
|
|
|
<span class="stat-spacer ${svelteClass}"></span>
|
|
|
|
<span class="stat-content ${svelteClass} has-hover" title="${hoverText}">${value}</span>
|
|
|
|
`;
|
|
|
|
statsElement.appendChild(statElement);
|
|
|
|
}
|
|
|
|
|
2024-04-25 06:34:22 +00:00
|
|
|
function sleep(ms) {
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
}
|
|
|
|
|
|
|
|
async function load() {
|
2024-04-25 06:11:06 +00:00
|
|
|
"use strict";
|
2024-04-25 06:34:22 +00:00
|
|
|
if (loaded) return;
|
2024-04-25 06:11:06 +00:00
|
|
|
|
|
|
|
const path = window.location.pathname;
|
|
|
|
const isPlayerPage = path.startsWith("/u/");
|
|
|
|
|
|
|
|
if (isPlayerPage) {
|
2024-04-25 06:34:22 +00:00
|
|
|
// Wait for the stats container to load
|
|
|
|
while (document.getElementsByClassName("stats-container").length === 0) {
|
|
|
|
await sleep(250);
|
|
|
|
}
|
|
|
|
|
2024-04-25 06:11:06 +00:00
|
|
|
playerPage();
|
|
|
|
}
|
2024-04-25 06:34:22 +00:00
|
|
|
|
|
|
|
loaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
load();
|