From 9f8c9a3ba08a1cfdc055ed28de4daf13dafc93f0 Mon Sep 17 00:00:00 2001 From: Liam <67254223+RealFascinated@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:44:21 +0100 Subject: [PATCH] Add avatar cache and change avatar url in the overlay --- pages/api/steamavatar.js | 35 ++++++++++++++++++++++ pages/api/validateid.js | 48 ++----------------------------- pages/index.js | 2 +- pages/overlay.js | 3 +- src/caches/SongArtCacheDir.js | 3 ++ src/caches/SteamAvatarCacheDir.js | 10 +++++++ src/utils/utils.js | 47 ++++++++++++++++++++++++++++++ 7 files changed, 101 insertions(+), 47 deletions(-) create mode 100644 pages/api/steamavatar.js create mode 100644 src/caches/SteamAvatarCacheDir.js diff --git a/pages/api/steamavatar.js b/pages/api/steamavatar.js new file mode 100644 index 0000000..7643085 --- /dev/null +++ b/pages/api/steamavatar.js @@ -0,0 +1,35 @@ +import fs from "fs"; +import fetch from "node-fetch"; +import path from "path"; +import sharp from "sharp"; +import cacheDir from "../../src/caches/SteamAvatarCacheDir"; +import Utils from "../../src/utils/utils"; + +export default async function handler(req, res) { + const steamId = req.query.steamid; + const isValid = await Utils.isValidSteamId(steamId); + if (isValid == true) { + return res.json({ + status: "OK", + message: `Invalid steam id`, + }); + } + + const imagePath = cacheDir + path.sep + steamId + ".jpg"; + const exists = fs.existsSync(imagePath); + if (!exists) { + const data = await fetch( + `https://cdn.scoresaber.com/avatars/${steamId}.jpg` + ); + let buffer = await data.buffer(); + buffer = await sharp(buffer).resize(150, 150).toBuffer(); + fs.writeFileSync(imagePath, buffer); + res.setHeader("Content-Type", "image/" + ext); + res.send(buffer); + console.log('Steam Avatar Cache - Added avatar "' + mapHash + '"'); + return; + } + const buffer = fs.readFileSync(imagePath); + res.setHeader("Content-Type", "image/jpg"); + res.send(buffer); +} diff --git a/pages/api/validateid.js b/pages/api/validateid.js index 073e3e6..af9d166 100644 --- a/pages/api/validateid.js +++ b/pages/api/validateid.js @@ -1,12 +1,5 @@ -import SteamIdCache from "../../src/caches/SteamIdCache"; -import WebsiteTypes from "../../src/consts/WebsiteType"; +import Utils from "../../src/utils/utils"; -const TO_CHECK = [ - WebsiteTypes.ScoreSaber.ApiUrl, - WebsiteTypes.BeatLeader.ApiUrl, -]; - -// TODO: Cache the result export default async function handler(req, res) { const steamId = req.query.steamid; if (!steamId) { @@ -16,44 +9,9 @@ export default async function handler(req, res) { }); } - if (SteamIdCache.has(steamId)) { - return res.json({ - status: "OK", - message: SteamIdCache.get(steamId) ? `Invalid` : "Valid", - }); - } - - let invalid = false; - for (const url of TO_CHECK) { - const isValid = await checkLeaderboard(url, steamId); - - if (isValid) { - break; - } - if (!isValid) { - invalid = true; - break; - } - } - - SteamIdCache.set(steamId, invalid); + const isValid = await Utils.isValidSteamId(steamId); return res.json({ status: "OK", - message: invalid ? `Invalid` : "Valid", + message: isValid ? `Invalid` : "Valid", }); } - -async function checkLeaderboard(url, steamId) { - console.log(url.replace("%s", steamId)); - const data = await fetch(url.replace("%s", steamId), { - headers: { - "X-Requested-With": "BeatSaber Overlay", - }, - }); - if (data.status === 429) { - return true; // Just assume it's true is we are rate limited - } - const json = await data.json(); - - return !!json.pp; -} diff --git a/pages/index.js b/pages/index.js index 83283e2..520ec2f 100644 --- a/pages/index.js +++ b/pages/index.js @@ -136,7 +136,7 @@ export default class Home extends Component { if (json.message === "Valid") { this.setState({ - avatarUrl: `https://cdn.scoresaber.com/avatars/${steamId}.jpg`, + avatarUrl: `/api/steamavatar?steamid=${steamId}`, }); } else { this.setState({ avatarUrl: undefined }); diff --git a/pages/overlay.js b/pages/overlay.js index 89860e6..a0a6166 100644 --- a/pages/overlay.js +++ b/pages/overlay.js @@ -371,6 +371,7 @@ export default class Overlay extends Component { websiteType, showPlayerStats, loadingPlayerData, + id } = this.state; if (this.state.textColor !== undefined) { @@ -400,7 +401,7 @@ export default class Overlay extends Component { country={data.country} countryRank={data.countryRank.toLocaleString()} websiteType={websiteType} - avatar={data.profilePicture || data.avatar} + avatar={`/api/steamavatar?steamid=${id}`} /> ) : ( <> diff --git a/src/caches/SongArtCacheDir.js b/src/caches/SongArtCacheDir.js index 36c813f..c0858a6 100644 --- a/src/caches/SongArtCacheDir.js +++ b/src/caches/SongArtCacheDir.js @@ -1,3 +1,6 @@ +import fs from "fs"; +import path from "path"; + const cacheDir = process.cwd() + path.sep + "cache"; if (!fs.existsSync(cacheDir)) { fs.mkdirSync(cacheDir); diff --git a/src/caches/SteamAvatarCacheDir.js b/src/caches/SteamAvatarCacheDir.js new file mode 100644 index 0000000..e013598 --- /dev/null +++ b/src/caches/SteamAvatarCacheDir.js @@ -0,0 +1,10 @@ +import fs from "fs"; +import path from "path"; + +const cacheDir = process.cwd() + path.sep + "cache"; +if (!fs.existsSync(cacheDir)) { + fs.mkdirSync(cacheDir); + console.log("Created avatar cache directory"); +} + +module.exports = cacheDir; diff --git a/src/utils/utils.js b/src/utils/utils.js index ccde4ea..5920e62 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,5 +1,11 @@ +import SteamIdCache from "../../src/caches/SteamIdCache"; import WebsiteTypes from "../consts/WebsiteType"; +const TO_CHECK = [ + WebsiteTypes.ScoreSaber.ApiUrl, + WebsiteTypes.BeatLeader.ApiUrl, +]; + export default class Utils { constructor() {} @@ -16,4 +22,45 @@ export default class Utils { static openInNewTab(url) { window.open(url, "_blank"); } + + static async isValidSteamId(steamId) { + if (!steamId) { + return false; + } + + if (SteamIdCache.has(steamId)) { + return SteamIdCache.get(steamId); + } + + let invalid = false; + for (const url of TO_CHECK) { + const isValid = await Utils.checkLeaderboard(url, steamId); + + if (isValid) { + break; + } + if (!isValid) { + invalid = true; + break; + } + } + + SteamIdCache.set(steamId, invalid); + return invalid; + } + + static async checkLeaderboard(url, steamId) { + console.log(url.replace("%s", steamId)); + const data = await fetch(url.replace("%s", steamId), { + headers: { + "X-Requested-With": "BeatSaber Overlay", + }, + }); + if (data.status === 429) { + return true; // Just assume it's true is we are rate limited + } + const json = await data.json(); + + return !!json.pp; + } }