Added an api
Fixed image loading with said api
This commit is contained in:
parent
78b92e9ec2
commit
18098707d1
@ -14,6 +14,10 @@ export default class ScoreStats extends Component {
|
||||
const data = this.props.data;
|
||||
|
||||
return <div className={'score-stats'}>
|
||||
<div className={'score-stats-info'}>
|
||||
<p>{data.percentage}</p>
|
||||
<p>{data.currentScore.toLocaleString()}</p>
|
||||
</div>
|
||||
<p className={'score-stats-average-cut'}>Average Cut</p>
|
||||
<div className={'score-stats-hands'}>
|
||||
<div className={'score-stats-left'}>
|
||||
@ -27,11 +31,6 @@ export default class ScoreStats extends Component {
|
||||
<p>{this.getAverage(data.rightHand.averageCut).toFixed(2)}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={'score-stats-info'}>
|
||||
<p>{data.percentage}</p>
|
||||
<p>{data.currentScore.toLocaleString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import {Component} from "react";
|
||||
import Image from 'next/image'
|
||||
import Config from "../config.json";
|
||||
|
||||
export default class SongInfo extends Component {
|
||||
|
||||
@ -34,7 +35,6 @@ export default class SongInfo extends Component {
|
||||
}
|
||||
|
||||
msToMinSeconds(millis) {
|
||||
console.log(millis)
|
||||
const minutes = Math.floor(millis / 60000);
|
||||
const seconds = Number(((millis % 60000) / 1000).toFixed(0));
|
||||
return seconds === 60 ? minutes + 1 + ":00" : minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
|
||||
@ -42,9 +42,9 @@ export default class SongInfo extends Component {
|
||||
|
||||
render() {
|
||||
const data = this.props.data.songData.status.beatmap;
|
||||
const beatSaverData = this.props.data.beatSaverData;
|
||||
const { id: bsr } = beatSaverData;
|
||||
const songArt = beatSaverData.versions[0].coverURL;
|
||||
const beatSaverData = this.props.data.beatSaverData.data;
|
||||
const songArt = beatSaverData.songArt;
|
||||
const bsr = beatSaverData.bsr;
|
||||
const {
|
||||
songName,
|
||||
songAuthorName,
|
||||
@ -53,7 +53,7 @@ export default class SongInfo extends Component {
|
||||
const songTimerPercentage = ((this.props.data.currentSongTime / 1000) / (data.length / 1000)) * 100000;
|
||||
|
||||
return <div className={'song-info-container'}>
|
||||
<Image src={songArt} width={150} height={150}/>
|
||||
<img src={songArt}/>
|
||||
<div className={'song-info'}>
|
||||
<p className={'song-info-song-name'}>{songName}</p>
|
||||
<p className={'song-info-song-author'}>{songAuthorName}</p>
|
||||
|
@ -3,8 +3,9 @@ module.exports = {
|
||||
images: {
|
||||
domains: [
|
||||
'cdn.scoresaber.com',
|
||||
'na.cdn.beatsaver.com',
|
||||
'eu.cdn.beatsaver.com'
|
||||
'bs-overlay.fascinated.cc',
|
||||
'localhost:3000',
|
||||
''
|
||||
],
|
||||
}
|
||||
}
|
||||
|
1111
package-lock.json
generated
1111
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,8 @@
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "17.0.2",
|
||||
"react-country-flag": "^3.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
"react-dom": "17.0.2",
|
||||
"sharp": "^0.30.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "8.9.0",
|
||||
|
31
pages/api/beatsaver/art/[hash].js
Normal file
31
pages/api/beatsaver/art/[hash].js
Normal file
@ -0,0 +1,31 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import sharp from 'sharp';
|
||||
|
||||
const cacheDir = process.cwd() + path.sep + "cache";
|
||||
if (!fs.existsSync(cacheDir)) {
|
||||
fs.mkdirSync(cacheDir);
|
||||
console.log("Created cache directory")
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const mapHash = req.query.hash.replace("custom_level_", "").toLowerCase();
|
||||
const ext = req.query.ext;
|
||||
|
||||
const imagePath = cacheDir + path.sep + mapHash + "." + ext;
|
||||
const exists = fs.existsSync(imagePath);
|
||||
console.log(`https://na.cdn.beatsaver.com/${mapHash}.${ext}`)
|
||||
if (!exists) {
|
||||
const data = await fetch(`https://na.cdn.beatsaver.com/${mapHash}.${ext}` );
|
||||
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("Song Cache - Added song \"" + mapHash + "\"")
|
||||
return;
|
||||
}
|
||||
const buffer = fs.readFileSync(imagePath);
|
||||
res.setHeader('Content-Type', 'image/jpg' + ext)
|
||||
res.send(buffer);
|
||||
}
|
15
pages/api/beatsaver/map.js
Normal file
15
pages/api/beatsaver/map.js
Normal file
@ -0,0 +1,15 @@
|
||||
import Utils from '../../../utils/utils'
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const mapHash = req.query.hash;
|
||||
|
||||
const mapData = await Utils.getMapData(mapHash.replace("custom_level_", ""));
|
||||
if (mapData === undefined) {
|
||||
return res.json({ error: true, message: "Unknown map" })
|
||||
}
|
||||
const data = {
|
||||
bsr: mapData.id,
|
||||
songArt: "http://" + req.headers.host + "/api/beatsaver/art/" + mapHash + "?ext=" + mapData.versions[0].coverURL.split("/")[3].split(".")[1]
|
||||
};
|
||||
res.json({ error: false, data: data })
|
||||
}
|
@ -8,11 +8,12 @@ import SongInfo from "../components/SongInfo";
|
||||
|
||||
// Why do u have to proxy requests... it's so dumb LOL
|
||||
const SCORESABER_API_URL = Config.proxy_url + "/https://scoresaber.com/api/player/%s/full";
|
||||
const BEATSAVER_API_URL = Config.proxy_url + "/https://api.beatsaver.com/maps/hash/%s";
|
||||
const GITHUB_URL = "https://github.com/RealFascinated/beatsaber-overlay";
|
||||
|
||||
export default class Home extends Component {
|
||||
|
||||
#_beatSaverURL = "";
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -58,6 +59,7 @@ export default class Home extends Component {
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
this.#_beatSaverURL = document.location.origin + "/api/beatsaver/map?hash=%s";
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
|
||||
@ -110,7 +112,7 @@ export default class Home extends Component {
|
||||
|
||||
connectSocket() {
|
||||
const socket = new WebSocket('ws://localhost:6557/socket');
|
||||
socket.addEventListener('error' || 'close', () => {
|
||||
socket.addEventListener('close', () => {
|
||||
console.log("Attempting to re-connect to the HTTP Status socket in 30 seconds.");
|
||||
setTimeout(() => this.connectSocket(), 30_000);
|
||||
});
|
||||
@ -127,9 +129,8 @@ export default class Home extends Component {
|
||||
|
||||
async setBeatSaver(songData) {
|
||||
console.log("Updating BeatSaver info")
|
||||
const data = await fetch(BEATSAVER_API_URL.replace("%s", songData.levelId.replace("custom_level_", "")));
|
||||
const data = await fetch(this.#_beatSaverURL.replace("%s", songData.levelId));
|
||||
const json = await data.json();
|
||||
console.log(json)
|
||||
this.setState({ beatSaverData: json })
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
||||
}
|
||||
|
||||
.player-country-icon {
|
||||
margin-top: -10px;
|
||||
margin-top: -11px;
|
||||
border-radius: 30%;
|
||||
}
|
||||
|
||||
@ -98,11 +98,7 @@
|
||||
}
|
||||
|
||||
.score-stats-info {
|
||||
position: fixed;
|
||||
bottom:0;
|
||||
right:0;
|
||||
margin-right: 10px;
|
||||
margin-bottom: -10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
17
utils/utils.js
Normal file
17
utils/utils.js
Normal file
@ -0,0 +1,17 @@
|
||||
import Config from '../config.json';
|
||||
|
||||
module.exports = {
|
||||
BEATSAVER_MAP_API: Config.proxy_url + "/https://api.beatsaver.com/maps/hash/%s",
|
||||
// todo: cache map data for 12 hrs
|
||||
async getMapData(hash) {
|
||||
const data = await fetch(this.BEATSAVER_MAP_API.replace("%s", hash), {
|
||||
headers: {
|
||||
"origin": "Fascinated Overlay"
|
||||
}
|
||||
});
|
||||
if (data.status === 404) {
|
||||
return undefined;
|
||||
}
|
||||
return await data.json();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user