fix proxy

This commit is contained in:
Lee 2023-10-31 11:44:27 +00:00
parent 918da6f88b
commit 47a255e48a
7 changed files with 314 additions and 341 deletions

@ -5,17 +5,17 @@ import { BeatSaverMapData } from "../types/BeatSaverMapData";
import { getValue, setValue, valueExists } from "../utils/redisUtils";
const BEATSAVER_MAP_API =
env(VARS.HTTP_PROXY) + "/https://api.beatsaver.com/maps/hash/%s";
env(VARS.HTTP_PROXY) + "/https://api.beatsaver.com/maps/hash/%s";
const KEY = "BS_MAP_DATA_";
function getLatestMapArt(data: BeatSaverMapData) {
return data.versions[data.versions.length - 1].coverURL;
return data.versions[data.versions.length - 1].coverURL;
}
type MapData = {
bsr: string;
mapArt: string | undefined;
bsr: string;
mapArt: string | undefined;
};
/**
@ -25,34 +25,30 @@ type MapData = {
* @returns The map data
*/
export async function getMapData(hash: string): Promise<MapData | undefined> {
const mapHash = hash.replace("custom_level_", "").toLowerCase();
const mapHash = hash.replace("custom_level_", "").toLowerCase();
const key = `${KEY}${mapHash}`;
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
return JSON.parse(data);
}
const key = `${KEY}${mapHash}`;
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
return JSON.parse(data);
}
const before = Date.now();
const response = await axios.get(BEATSAVER_MAP_API.replace("%s", mapHash), {
headers: {
"X-Requested-With": "BeatSaber Overlay",
},
});
if (response.status === 404) {
return undefined;
}
const jsonResponse = response.data;
const json = {
bsr: jsonResponse.id,
mapArt: getLatestMapArt(jsonResponse),
};
await setValue(key, JSON.stringify(json), 86400 * 7); // Expire in a week
console.log(
`[Cache]: Cached BS Map Data for hash ${mapHash} in ${
Date.now() - before
}ms`
);
return json;
const before = Date.now();
const response = await axios.get(BEATSAVER_MAP_API.replace("%s", mapHash));
if (response.status === 404) {
return undefined;
}
const jsonResponse = response.data;
const json = {
bsr: jsonResponse.id,
mapArt: getLatestMapArt(jsonResponse),
};
await setValue(key, JSON.stringify(json), 86400 * 7); // Expire in a week
console.log(
`[Cache]: Cached BS Map Data for hash ${mapHash} in ${
Date.now() - before
}ms`
);
return json;
}

@ -2,13 +2,8 @@ import axios from "axios";
import LeaderboardType from "../../consts/LeaderboardType";
export async function getPlayerData(leaderboardType, playerId) {
const data = await axios.get(
LeaderboardType[leaderboardType].ApiUrl.PlayerData.replace("%s", playerId),
{
headers: {
"x-requested-with": "BeatSaber Overlay",
},
}
);
return data;
const data = await axios.get(
LeaderboardType[leaderboardType].ApiUrl.PlayerData.replace("%s", playerId)
);
return data;
}

@ -11,97 +11,92 @@ const KEY = "BL_MAP_DATA_";
* @returns
*/
export default async function handler(req, res) {
if (!req.query.hash || !req.query.difficulty || !req.query.characteristic) {
return res.status(404).json({
status: 404,
message: "Invalid request",
});
}
const mapHash = req.query.hash.replace("custom_level_", "").toLowerCase();
const difficulty = req.query.difficulty.replace(" ", "");
const characteristic = req.query.characteristic;
if (!req.query.hash || !req.query.difficulty || !req.query.characteristic) {
return res.status(404).json({
status: 404,
message: "Invalid request",
});
}
const mapHash = req.query.hash.replace("custom_level_", "").toLowerCase();
const difficulty = req.query.difficulty.replace(" ", "");
const characteristic = req.query.characteristic;
const key = `${KEY}${difficulty}-${characteristic}-${mapHash}`;
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
const json = JSON.parse(data);
res.setHeader("Cache-Status", "hit");
const key = `${KEY}${difficulty}-${characteristic}-${mapHash}`;
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
const json = JSON.parse(data);
res.setHeader("Cache-Status", "hit");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: json.stars,
modifiers: json.modifiers,
passRating: json.passRating,
accRating: json.accRating,
techRating: json.techRating,
});
}
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: json.stars,
modifiers: json.modifiers,
passRating: json.passRating,
accRating: json.accRating,
techRating: json.techRating,
});
}
const before = Date.now();
const reesponse = await axios.get(
WebsiteTypes.BeatLeader.ApiUrl.MapData.replace("%h", mapHash),
{
headers: {
"X-Requested-With": "BeatSaber Overlay",
},
}
);
if (reesponse.status === 404) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
const json = reesponse.data;
let starCount = undefined;
let modifiers = undefined;
let passRating = undefined;
let accRating = undefined;
let techRating = undefined;
const before = Date.now();
const reesponse = await axios.get(
WebsiteTypes.BeatLeader.ApiUrl.MapData.replace("%h", mapHash)
);
if (reesponse.status === 404) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
const json = reesponse.data;
let starCount = undefined;
let modifiers = undefined;
let passRating = undefined;
let accRating = undefined;
let techRating = undefined;
for (const diff of json.difficulties) {
if (
diff.difficultyName === difficulty &&
diff.modeName === characteristic
) {
starCount = diff.stars;
modifiers = diff.modifierValues;
passRating = diff.passRating;
accRating = diff.accRating;
techRating = diff.techRating;
}
}
if (starCount === undefined) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
await setValue(
key,
JSON.stringify({
stars: starCount,
modifiers: modifiers,
passRating: passRating,
accRating: accRating,
techRating: techRating,
})
);
console.log(
`[Cache]: Cached BL Star Count for hash ${mapHash} in ${
Date.now() - before
}ms`
);
res.setHeader("Cache-Status", "miss");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: starCount,
modifiers: modifiers,
passRating: passRating,
accRating: accRating,
techRating: techRating,
});
for (const diff of json.difficulties) {
if (
diff.difficultyName === difficulty &&
diff.modeName === characteristic
) {
starCount = diff.stars;
modifiers = diff.modifierValues;
passRating = diff.passRating;
accRating = diff.accRating;
techRating = diff.techRating;
}
}
if (starCount === undefined) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
await setValue(
key,
JSON.stringify({
stars: starCount,
modifiers: modifiers,
passRating: passRating,
accRating: accRating,
techRating: techRating,
})
);
console.log(
`[Cache]: Cached BL Star Count for hash ${mapHash} in ${
Date.now() - before
}ms`
);
res.setHeader("Cache-Status", "miss");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: starCount,
modifiers: modifiers,
passRating: passRating,
accRating: accRating,
techRating: techRating,
});
}

@ -12,65 +12,60 @@ const KEY = "SS_MAP_STAR_";
* @returns
*/
export default async function handler(req, res) {
if (!req.query.hash) {
return res.status(404).json({
status: 404,
message: "Invalid request",
});
}
const mapHash = req.query.hash.replace("custom_level_", "").toLowerCase();
const difficulty = req.query.difficulty.replace(" ", "");
const characteristic = req.query.characteristic;
if (!req.query.hash) {
return res.status(404).json({
status: 404,
message: "Invalid request",
});
}
const mapHash = req.query.hash.replace("custom_level_", "").toLowerCase();
const difficulty = req.query.difficulty.replace(" ", "");
const characteristic = req.query.characteristic;
const key = `${KEY}${difficulty}-${characteristic}-${mapHash}`;
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
res.setHeader("Cache-Status", "hit");
const key = `${KEY}${difficulty}-${characteristic}-${mapHash}`;
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
res.setHeader("Cache-Status", "hit");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: Number.parseFloat(data),
});
}
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: Number.parseFloat(data),
});
}
const before = Date.now();
const response = await axios.get(
WebsiteTypes.ScoreSaber.ApiUrl.MapData.replace("%h", mapHash).replace(
"%d",
diffToScoreSaberDiff(difficulty)
),
{
headers: {
"X-Requested-With": "BeatSaber Overlay",
},
}
);
if (response.status === 404) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
const json = response.data;
let starCount = json.stars;
if (starCount === undefined) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
await setValue(key, starCount);
console.log(
`[Cache]: Cached SS Star Count for hash ${mapHash} in ${
Date.now() - before
}ms`
);
res.setHeader("Cache-Status", "miss");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: starCount,
});
const before = Date.now();
const response = await axios.get(
WebsiteTypes.ScoreSaber.ApiUrl.MapData.replace("%h", mapHash).replace(
"%d",
diffToScoreSaberDiff(difficulty)
)
);
if (response.status === 404) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
const json = response.data;
let starCount = json.stars;
if (starCount === undefined) {
return res.status(404).json({
status: 404,
message: "Unknown Map Hash",
});
}
await setValue(key, starCount);
console.log(
`[Cache]: Cached SS Star Count for hash ${mapHash} in ${
Date.now() - before
}ms`
);
res.setHeader("Cache-Status", "miss");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: starCount,
});
}

@ -4,52 +4,48 @@ import Utils from "../utils/utils";
import { useSettingsStore } from "./overlaySettingsStore";
interface PlayerDataState {
isLoading: boolean;
id: string;
pp: number;
avatar: string;
globalPos: number;
countryRank: number;
country: string;
updatePlayerData: () => void;
isLoading: boolean;
id: string;
pp: number;
avatar: string;
globalPos: number;
countryRank: number;
country: string;
updatePlayerData: () => void;
}
export const usePlayerDataStore = create<PlayerDataState>()((set) => ({
isLoading: true,
id: "",
pp: 0,
avatar: "",
globalPos: 0,
countryRank: 0,
country: "",
isLoading: true,
id: "",
pp: 0,
avatar: "",
globalPos: 0,
countryRank: 0,
country: "",
updatePlayerData: async () => {
const leaderboardType = useSettingsStore.getState().leaderboardType;
const playerId = useSettingsStore.getState().id;
updatePlayerData: async () => {
const leaderboardType = useSettingsStore.getState().leaderboardType;
const playerId = useSettingsStore.getState().id;
const apiUrl = Utils.getWebsiteApi(
leaderboardType
).ApiUrl.PlayerData.replace("%s", playerId);
const response = await axios.get(apiUrl, {
headers: {
"x-requested-with": "BeatSaber Overlay",
},
});
if (response.status !== 200) {
return;
}
const data = response.data;
const apiUrl = Utils.getWebsiteApi(
leaderboardType
).ApiUrl.PlayerData.replace("%s", playerId);
const response = await axios.get(apiUrl);
if (response.status !== 200) {
return;
}
const data = response.data;
console.log("Updated player data");
console.log("Updated player data");
set(() => ({
id: playerId,
isLoading: false,
pp: data.pp,
avatar: data.avatar || data.profilePicture,
globalPos: data.rank,
countryRank: data.countryRank,
country: data.country,
}));
},
set(() => ({
id: playerId,
isLoading: false,
pp: data.pp,
avatar: data.avatar || data.profilePicture,
globalPos: data.rank,
countryRank: data.countryRank,
country: data.country,
}));
},
}));

@ -5,134 +5,130 @@ import { getScoreSaberPP } from "../curve/ScoreSaberCurve";
import { useSongDataStore } from "../store/songDataStore";
export default class Utils {
/**
* Returns the information for the given website type.
*
* @param {string} website
* @returns The website type's information.
*/
static getWebsiteApi(website) {
return LeaderboardType[website];
}
/**
* Returns the information for the given website type.
*
* @param {string} website
* @returns The website type's information.
*/
static getWebsiteApi(website) {
return LeaderboardType[website];
}
static openInNewTab(url) {
window.open(url, "_blank");
}
static openInNewTab(url) {
window.open(url, "_blank");
}
static async isLeaderboardValid(url, steamId) {
const response = await axios.get(url.replace("%s", steamId), {
headers: {
"X-Requested-With": "BeatSaber Overlay",
},
});
if (response.status === 429) {
return true; // Just assume it's true is we are rate limited
}
const json = response.data;
return !!json.pp;
}
static async isLeaderboardValid(url, steamId) {
const response = await axios.get(url.replace("%s", steamId));
if (response.status === 429) {
return true; // Just assume it's true is we are rate limited
}
const json = response.data;
return !!json.pp;
}
static calculatePP(stars, acc, type) {
if (stars <= 0) {
return undefined;
}
if (type === "BeatLeader") {
const leaderboardData =
useSongDataStore.getState().mapLeaderboardData.beatLeader;
static calculatePP(stars, acc, type) {
if (stars <= 0) {
return undefined;
}
if (type === "BeatLeader") {
const leaderboardData =
useSongDataStore.getState().mapLeaderboardData.beatLeader;
return getBeatLeaderPP(
acc,
leaderboardData.accRating,
leaderboardData.passRating,
leaderboardData.techRating
);
}
if (type === "ScoreSaber") {
return getScoreSaberPP(acc, stars);
}
return undefined;
}
return getBeatLeaderPP(
acc,
leaderboardData.accRating,
leaderboardData.passRating,
leaderboardData.techRating
);
}
if (type === "ScoreSaber") {
return getScoreSaberPP(acc, stars);
}
return undefined;
}
static calculateModifierBonus() {
const songMods = useSongDataStore.getState().songModifiers;
const modifierMulipliers =
useSongDataStore.getState().mapLeaderboardData.beatLeader.modifiers;
let bonus = 1;
static calculateModifierBonus() {
const songMods = useSongDataStore.getState().songModifiers;
const modifierMulipliers =
useSongDataStore.getState().mapLeaderboardData.beatLeader.modifiers;
let bonus = 1;
// No Fail
if (
songMods.noFail == true &&
modifierMulipliers.nf < 0 &&
useSongDataStore.getState().failed
) {
bonus -= modifierMulipliers.nf;
}
// No Fail
if (
songMods.noFail == true &&
modifierMulipliers.nf < 0 &&
useSongDataStore.getState().failed
) {
bonus -= modifierMulipliers.nf;
}
// Speed Modifiers
if (songMods.songSpeed != "Normal") {
if (songMods.songSpeed == "SuperSlow" && modifierMulipliers.ss > 0) {
bonus -= modifierMulipliers.ss;
}
if (songMods.songSpeed == "Faster" && modifierMulipliers.fs > 0) {
bonus += modifierMulipliers.fs;
}
if (songMods.songSpeed == "SuperFast" && modifierMulipliers.sf > 0) {
bonus += modifierMulipliers.sf;
}
}
// Speed Modifiers
if (songMods.songSpeed != "Normal") {
if (songMods.songSpeed == "SuperSlow" && modifierMulipliers.ss > 0) {
bonus -= modifierMulipliers.ss;
}
if (songMods.songSpeed == "Faster" && modifierMulipliers.fs > 0) {
bonus += modifierMulipliers.fs;
}
if (songMods.songSpeed == "SuperFast" && modifierMulipliers.sf > 0) {
bonus += modifierMulipliers.sf;
}
}
// Disappearing Arrows
if (songMods.disappearingArrows == true && modifierMulipliers.da > 0) {
bonus += modifierMulipliers.da;
}
// Disappearing Arrows
if (songMods.disappearingArrows == true && modifierMulipliers.da > 0) {
bonus += modifierMulipliers.da;
}
// Ghost Notes
if (songMods.ghostNotes == true && modifierMulipliers.gn > 0) {
toAdd += modifierMulipliers.gn;
}
// Ghost Notes
if (songMods.ghostNotes == true && modifierMulipliers.gn > 0) {
toAdd += modifierMulipliers.gn;
}
// No Arrows
if (songMods.noArrows == true && modifierMulipliers.na < 0) {
bonus -= modifierMulipliers.na;
}
// No Arrows
if (songMods.noArrows == true && modifierMulipliers.na < 0) {
bonus -= modifierMulipliers.na;
}
// No Bombs
if (songMods.noBombs == true && modifierMulipliers.nb < 0) {
bonus -= modifierMulipliers.nb;
}
// No Bombs
if (songMods.noBombs == true && modifierMulipliers.nb < 0) {
bonus -= modifierMulipliers.nb;
}
// No Obstacles
if (songMods.obstacles == false && modifierMulipliers.no < 0) {
bonus -= modifierMulipliers.no;
}
// No Obstacles
if (songMods.obstacles == false && modifierMulipliers.no < 0) {
bonus -= modifierMulipliers.no;
}
return bonus;
}
return bonus;
}
static base64ToArrayBuffer(base64) {
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
}
static base64ToArrayBuffer(base64) {
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
}
static stringToBoolean = (stringValue) => {
switch (stringValue?.toLowerCase()?.trim()) {
case "true":
case "yes":
case "1":
return true;
static stringToBoolean = (stringValue) => {
switch (stringValue?.toLowerCase()?.trim()) {
case "true":
case "yes":
case "1":
return true;
case "false":
case "no":
case "0":
case null:
case undefined:
return false;
case "false":
case "no":
case "0":
case null:
case undefined:
return false;
default:
return JSON.parse(stringValue);
}
};
default:
return JSON.parse(stringValue);
}
};
static capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
static capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
}