diff --git a/pages/api/beatsaver/art/[hash].js b/pages/api/beatsaver/art/[hash].js
deleted file mode 100644
index c2512ac..0000000
--- a/pages/api/beatsaver/art/[hash].js
+++ /dev/null
@@ -1,55 +0,0 @@
-import fetch from "node-fetch";
-import sharp from "sharp";
-import {
- getValue,
- setValue,
- valueExists,
-} from "../../../../src/utils/redisUtils";
-
-const KEY = "BS_MAP_ART_";
-
-/**
- *
- * @param {Request} req
- * @param {Response} res
- * @returns
- */
-export default async function handler(req, res) {
- const mapHash = req.query.hash.replace("custom_level_", "").toLowerCase();
- const ext = req.query.ext || "jpg";
-
- const exists = await valueExists(`${KEY}${mapHash}`.replace(" ", ""));
- if (exists) {
- const data = await getValue(`${KEY}${mapHash}`);
- const buffer = Buffer.from(data, "base64");
- res.writeHead(200, {
- "Content-Type": "image/" + ext,
- "Content-Length": buffer.length,
- "Cache-Status": "hit",
- });
- return res.end(buffer);
- }
-
- const before = Date.now();
- const data = await fetch(`https://eu.cdn.beatsaver.com/${mapHash}.${ext}`);
- if (data.status === 404) {
- return res.status(404).json({
- status: 404,
- message: "Unknown Map Hash",
- });
- }
-
- let buffer = await data.buffer(); // Change to arrayBuffer at some point to make it shush
- buffer = await sharp(buffer).resize(400, 400).toBuffer();
- const bytes = buffer.toString("base64");
-
- await setValue(`${KEY}${mapHash}`.replace(" ", ""), bytes);
- console.log(
- `[Cache]: Cached BS Song Art for hash ${mapHash} in ${
- Date.now() - before
- }ms`
- );
- res.setHeader("Cache-Status", "miss");
- res.setHeader("Content-Type", "image/" + ext);
- res.status(200).send(buffer);
-}
diff --git a/pages/api/beatsaver/map.js b/pages/api/beatsaver/map.js
index 04185c4..e8813ac 100644
--- a/pages/api/beatsaver/map.js
+++ b/pages/api/beatsaver/map.js
@@ -11,12 +11,5 @@ export default async function handler(req, res) {
message: "Unknown Map Hash",
});
}
- const data = {
- // The maps data from the provided map hash
- bsr: mapData.id,
- songArt: `http://${req.headers.host}/api/beatsaver/art/${mapHash}?ext=${
- mapData.versions[0].coverURL.split("/")[3].split(".")[1]
- }`,
- };
- res.status(200).json({ error: false, data: data });
+ res.status(200).json({ status: "OK", data: mapData });
}
diff --git a/src/components/SongInfo.js b/src/components/SongInfo.js
index 4207903..557fbae 100644
--- a/src/components/SongInfo.js
+++ b/src/components/SongInfo.js
@@ -56,12 +56,11 @@ export default class SongInfo extends Component {
render() {
const data = this.props.data.songData.status.beatmap;
const beatSaverData = this.props.data.beatSaverData.data;
- const songArt = beatSaverData.songArt;
+ const mapArt = beatSaverData.mapArt;
const bsr = beatSaverData.bsr;
const { songName, songAuthorName, difficulty } = data;
- // what in the fuck is this?? LMFAO
const songTimerPercentage =
- (this.props.data.currentSongTime / 1000 / (data.length / 1000)) * 100000;
+ (this.props.data.currentSongTime / data.length) * 100;
return (
@@ -69,7 +68,7 @@ export default class SongInfo extends Component {
width={150}
height={150}
alt="Song artwork"
- src={songArt}
+ src={mapArt}
loading="lazy"
placeholder="blur"
blurDataURL="https://cdn.fascinated.cc/IkQFyodbZv.jpg?raw=true"
diff --git a/src/helpers/beatSaverHelpers.js b/src/helpers/beatSaverHelpers.ts
similarity index 62%
rename from src/helpers/beatSaverHelpers.js
rename to src/helpers/beatSaverHelpers.ts
index 2a83d26..853a0d0 100644
--- a/src/helpers/beatSaverHelpers.js
+++ b/src/helpers/beatSaverHelpers.ts
@@ -1,3 +1,4 @@
+import { BeatSaverMapData } from "../types/BeatSaverMapData";
import { getValue, setValue, valueExists } from "../utils/redisUtils";
const BEATSAVER_MAP_API =
@@ -6,13 +7,28 @@ const BEATSAVER_MAP_API =
const KEY = "BS_MAP_DATA_";
+function getLatestMapArt(data: BeatSaverMapData) {
+ console.log(data);
+ let url: string | undefined = undefined;
+ for (const version of data.versions) {
+ url = version.coverURL;
+ }
+ console.log(url);
+ return url;
+}
+
+type MapData = {
+ bsr: string;
+ mapArt: string | undefined;
+};
+
/**
* Gets a specified maps data from BeatSaver
*
* @param {string} hash
* @returns The map data
*/
-export async function getMapData(hash) {
+export async function getMapData(hash): Promise {
const mapHash = hash.replace("custom_level_", "").toLowerCase();
const key = `${KEY}${mapHash}`;
@@ -31,7 +47,11 @@ export async function getMapData(hash) {
if (data.status === 404) {
return undefined;
}
- const json = await data.json();
+ const jsonResponse = await data.json();
+ const json = {
+ bsr: jsonResponse.id,
+ mapArt: getLatestMapArt(jsonResponse),
+ };
await setValue(key, JSON.stringify(json));
console.log(
`[Cache]: Cached BS Map Data for hash ${mapHash} in ${
diff --git a/src/types/BeatSaverMapData.ts b/src/types/BeatSaverMapData.ts
new file mode 100644
index 0000000..26e7f1f
--- /dev/null
+++ b/src/types/BeatSaverMapData.ts
@@ -0,0 +1,91 @@
+export type BeatSaverMapData = {
+ id: string;
+ name: string;
+ description: string;
+ uploader: {
+ id: string;
+ name: string;
+ hash: string;
+ avatar: string;
+ type: string;
+ admin: boolean;
+ curator: boolean;
+ verifiedMapper: boolean;
+ };
+ metadata: {
+ bpm: number;
+ duration: number;
+ songName: string;
+ songSubName: string;
+ songAuthorName: string;
+ levelAuthorName: string;
+ };
+ stats: {
+ plays: number;
+ downloads: number;
+ upvotes: number;
+ downvotes: number;
+ score: number;
+ };
+ uploaded: string;
+ automapper: boolean;
+ ranked: boolean;
+ qualified: boolean;
+ versions: Array;
+ curator: Curator;
+ curatedAt: string;
+ createdAt: string;
+ updatedAt: string;
+ lastPublishedAt: string;
+ tags: Array;
+};
+
+export type Version = {
+ hash: string;
+ state: string;
+ createdAt: string;
+ sageScore: number;
+ diffs: Array;
+ downloadURL: string;
+ coverURL: string;
+ previewURL: string;
+};
+
+export type Difficulty = {
+ njs: number;
+ offset: number;
+ notes: number;
+ bombs: number;
+ obstacles: number;
+ nps: number;
+ length: number;
+ characteristic: string;
+ difficulty: DifficultyType;
+ events: number;
+ chroma: boolean;
+ me: boolean;
+ ne: boolean;
+ cinema: boolean;
+ seconds: number;
+ paritySummary: ParitySummary;
+ stars: number;
+ maxScore: number;
+};
+
+export type DifficultyType = ["Easy", "Normal", "Hard", "Expert", "ExpertPlus"];
+
+export type ParitySummary = {
+ errors: number;
+ warns: number;
+ resets: number;
+};
+
+export type Curator = {
+ id: number;
+ name: string;
+ hash: string;
+ avatar: string;
+ type: string;
+ admin: boolean;
+ curator: boolean;
+};