Add avatar cache and change avatar url in the overlay

This commit is contained in:
Liam 2022-10-19 17:44:21 +01:00
parent 2af984d395
commit 9f8c9a3ba0
7 changed files with 101 additions and 47 deletions

35
pages/api/steamavatar.js Normal file

@ -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);
}

@ -1,12 +1,5 @@
import SteamIdCache from "../../src/caches/SteamIdCache"; import Utils from "../../src/utils/utils";
import WebsiteTypes from "../../src/consts/WebsiteType";
const TO_CHECK = [
WebsiteTypes.ScoreSaber.ApiUrl,
WebsiteTypes.BeatLeader.ApiUrl,
];
// TODO: Cache the result
export default async function handler(req, res) { export default async function handler(req, res) {
const steamId = req.query.steamid; const steamId = req.query.steamid;
if (!steamId) { if (!steamId) {
@ -16,44 +9,9 @@ export default async function handler(req, res) {
}); });
} }
if (SteamIdCache.has(steamId)) { const isValid = await Utils.isValidSteamId(steamId);
return res.json({ return res.json({
status: "OK", status: "OK",
message: SteamIdCache.get(steamId) ? `Invalid` : "Valid", message: isValid ? `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);
return res.json({
status: "OK",
message: invalid ? `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;
}

@ -136,7 +136,7 @@ export default class Home extends Component {
if (json.message === "Valid") { if (json.message === "Valid") {
this.setState({ this.setState({
avatarUrl: `https://cdn.scoresaber.com/avatars/${steamId}.jpg`, avatarUrl: `/api/steamavatar?steamid=${steamId}`,
}); });
} else { } else {
this.setState({ avatarUrl: undefined }); this.setState({ avatarUrl: undefined });

@ -371,6 +371,7 @@ export default class Overlay extends Component {
websiteType, websiteType,
showPlayerStats, showPlayerStats,
loadingPlayerData, loadingPlayerData,
id
} = this.state; } = this.state;
if (this.state.textColor !== undefined) { if (this.state.textColor !== undefined) {
@ -400,7 +401,7 @@ export default class Overlay extends Component {
country={data.country} country={data.country}
countryRank={data.countryRank.toLocaleString()} countryRank={data.countryRank.toLocaleString()}
websiteType={websiteType} websiteType={websiteType}
avatar={data.profilePicture || data.avatar} avatar={`/api/steamavatar?steamid=${id}`}
/> />
) : ( ) : (
<></> <></>

@ -1,3 +1,6 @@
import fs from "fs";
import path from "path";
const cacheDir = process.cwd() + path.sep + "cache"; const cacheDir = process.cwd() + path.sep + "cache";
if (!fs.existsSync(cacheDir)) { if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir); fs.mkdirSync(cacheDir);

@ -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;

@ -1,5 +1,11 @@
import SteamIdCache from "../../src/caches/SteamIdCache";
import WebsiteTypes from "../consts/WebsiteType"; import WebsiteTypes from "../consts/WebsiteType";
const TO_CHECK = [
WebsiteTypes.ScoreSaber.ApiUrl,
WebsiteTypes.BeatLeader.ApiUrl,
];
export default class Utils { export default class Utils {
constructor() {} constructor() {}
@ -16,4 +22,45 @@ export default class Utils {
static openInNewTab(url) { static openInNewTab(url) {
window.open(url, "_blank"); 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;
}
} }