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;
|
const data = this.props.data;
|
||||||
|
|
||||||
return <div className={'score-stats'}>
|
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>
|
<p className={'score-stats-average-cut'}>Average Cut</p>
|
||||||
<div className={'score-stats-hands'}>
|
<div className={'score-stats-hands'}>
|
||||||
<div className={'score-stats-left'}>
|
<div className={'score-stats-left'}>
|
||||||
@ -27,11 +31,6 @@ export default class ScoreStats extends Component {
|
|||||||
<p>{this.getAverage(data.rightHand.averageCut).toFixed(2)}</p>
|
<p>{this.getAverage(data.rightHand.averageCut).toFixed(2)}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'score-stats-info'}>
|
|
||||||
<p>{data.percentage}</p>
|
|
||||||
<p>{data.currentScore.toLocaleString()}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import {Component} from "react";
|
import {Component} from "react";
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
|
import Config from "../config.json";
|
||||||
|
|
||||||
export default class SongInfo extends Component {
|
export default class SongInfo extends Component {
|
||||||
|
|
||||||
@ -34,7 +35,6 @@ export default class SongInfo extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msToMinSeconds(millis) {
|
msToMinSeconds(millis) {
|
||||||
console.log(millis)
|
|
||||||
const minutes = Math.floor(millis / 60000);
|
const minutes = Math.floor(millis / 60000);
|
||||||
const seconds = Number(((millis % 60000) / 1000).toFixed(0));
|
const seconds = Number(((millis % 60000) / 1000).toFixed(0));
|
||||||
return seconds === 60 ? minutes + 1 + ":00" : minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
|
return seconds === 60 ? minutes + 1 + ":00" : minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
|
||||||
@ -42,9 +42,9 @@ export default class SongInfo extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const data = this.props.data.songData.status.beatmap;
|
const data = this.props.data.songData.status.beatmap;
|
||||||
const beatSaverData = this.props.data.beatSaverData;
|
const beatSaverData = this.props.data.beatSaverData.data;
|
||||||
const { id: bsr } = beatSaverData;
|
const songArt = beatSaverData.songArt;
|
||||||
const songArt = beatSaverData.versions[0].coverURL;
|
const bsr = beatSaverData.bsr;
|
||||||
const {
|
const {
|
||||||
songName,
|
songName,
|
||||||
songAuthorName,
|
songAuthorName,
|
||||||
@ -53,7 +53,7 @@ export default class SongInfo extends Component {
|
|||||||
const songTimerPercentage = ((this.props.data.currentSongTime / 1000) / (data.length / 1000)) * 100000;
|
const songTimerPercentage = ((this.props.data.currentSongTime / 1000) / (data.length / 1000)) * 100000;
|
||||||
|
|
||||||
return <div className={'song-info-container'}>
|
return <div className={'song-info-container'}>
|
||||||
<Image src={songArt} width={150} height={150}/>
|
<img src={songArt}/>
|
||||||
<div className={'song-info'}>
|
<div className={'song-info'}>
|
||||||
<p className={'song-info-song-name'}>{songName}</p>
|
<p className={'song-info-song-name'}>{songName}</p>
|
||||||
<p className={'song-info-song-author'}>{songAuthorName}</p>
|
<p className={'song-info-song-author'}>{songAuthorName}</p>
|
||||||
|
@ -3,8 +3,9 @@ module.exports = {
|
|||||||
images: {
|
images: {
|
||||||
domains: [
|
domains: [
|
||||||
'cdn.scoresaber.com',
|
'cdn.scoresaber.com',
|
||||||
'na.cdn.beatsaver.com',
|
'bs-overlay.fascinated.cc',
|
||||||
'eu.cdn.beatsaver.com'
|
'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",
|
"prop-types": "^15.8.1",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-country-flag": "^3.0.2",
|
"react-country-flag": "^3.0.2",
|
||||||
"react-dom": "17.0.2"
|
"react-dom": "17.0.2",
|
||||||
|
"sharp": "^0.30.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "8.9.0",
|
"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
|
// 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 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";
|
const GITHUB_URL = "https://github.com/RealFascinated/beatsaber-overlay";
|
||||||
|
|
||||||
export default class Home extends Component {
|
export default class Home extends Component {
|
||||||
|
|
||||||
|
#_beatSaverURL = "";
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ export default class Home extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
|
this.#_beatSaverURL = document.location.origin + "/api/beatsaver/map?hash=%s";
|
||||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||||
const params = Object.fromEntries(urlSearchParams.entries());
|
const params = Object.fromEntries(urlSearchParams.entries());
|
||||||
|
|
||||||
@ -110,7 +112,7 @@ export default class Home extends Component {
|
|||||||
|
|
||||||
connectSocket() {
|
connectSocket() {
|
||||||
const socket = new WebSocket('ws://localhost:6557/socket');
|
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.");
|
console.log("Attempting to re-connect to the HTTP Status socket in 30 seconds.");
|
||||||
setTimeout(() => this.connectSocket(), 30_000);
|
setTimeout(() => this.connectSocket(), 30_000);
|
||||||
});
|
});
|
||||||
@ -127,9 +129,8 @@ export default class Home extends Component {
|
|||||||
|
|
||||||
async setBeatSaver(songData) {
|
async setBeatSaver(songData) {
|
||||||
console.log("Updating BeatSaver info")
|
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();
|
const json = await data.json();
|
||||||
console.log(json)
|
|
||||||
this.setState({ beatSaverData: json })
|
this.setState({ beatSaverData: json })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.player-country-icon {
|
.player-country-icon {
|
||||||
margin-top: -10px;
|
margin-top: -11px;
|
||||||
border-radius: 30%;
|
border-radius: 30%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,11 +98,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.score-stats-info {
|
.score-stats-info {
|
||||||
position: fixed;
|
|
||||||
bottom:0;
|
|
||||||
right:0;
|
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-bottom: -10px;
|
|
||||||
text-align: right;
|
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