forked from nin0/website
242 lines
5.2 KiB
TypeScript
242 lines
5.2 KiB
TypeScript
import "@css/me.css";
|
|
import { initLanyard } from "@js/lanyard/lanyard";
|
|
import { type LanyardPresence } from "../../../js/lanyard/types";
|
|
import { useEffect, useState } from "react";
|
|
import { average } from "color.js";
|
|
|
|
const lightenColor = (color: string, percent: number) =>
|
|
`hsl(from ${color} h s ${percent.toString()}%)`;
|
|
const api_key = "3c5623fa1abbd11c49f53ca18e992ead";
|
|
|
|
export default function Me() {
|
|
// me-e-eeeee
|
|
const [presence, setPresence] = useState<LanyardPresence | undefined>();
|
|
const [currentlyPlaying, setCurrentlyPlaying] = useState<
|
|
| {
|
|
title: string;
|
|
artist: string;
|
|
album: string;
|
|
albumArt: string;
|
|
mainColor: string;
|
|
loved: boolean;
|
|
streak: number;
|
|
spotifyURL?: string;
|
|
}
|
|
| undefined
|
|
>();
|
|
|
|
useEffect(() => {
|
|
initLanyard(presence => {
|
|
setPresence(presence);
|
|
});
|
|
|
|
async function getLastFmTracks() {
|
|
const params = new URLSearchParams({
|
|
method: "user.getrecenttracks",
|
|
api_key,
|
|
user: "nin0dev",
|
|
limit: "50",
|
|
format: "json",
|
|
extended: "true"
|
|
});
|
|
|
|
const res = await (
|
|
await fetch(`https://ws.audioscrobbler.com/2.0/?${params}`)
|
|
).json();
|
|
|
|
if (
|
|
res.recenttracks.track.some(t => {
|
|
try {
|
|
return t["@attr"].nowplaying === "true";
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
})
|
|
) {
|
|
const currentlyPlayingTrack = res.recenttracks.track[0];
|
|
|
|
const trackExtra = (
|
|
await (
|
|
await fetch(
|
|
`https://ws.audioscrobbler.com/2.0/?${new URLSearchParams(
|
|
{
|
|
method: "track.getinfo",
|
|
api_key,
|
|
format: "json",
|
|
track: currentlyPlayingTrack.name,
|
|
artist: currentlyPlayingTrack.artist.name
|
|
}
|
|
)}`
|
|
)
|
|
).json()
|
|
).track;
|
|
|
|
setCurrentlyPlaying({
|
|
title: currentlyPlayingTrack.name,
|
|
artist: currentlyPlayingTrack.artist.name,
|
|
album: currentlyPlayingTrack.album["#text"],
|
|
albumArt: currentlyPlayingTrack.image[1]["#text"],
|
|
// @ts-ignore this library is poorly typed
|
|
mainColor: await average(
|
|
currentlyPlayingTrack.image[1]["#text"],
|
|
{
|
|
format: "hex"
|
|
}
|
|
),
|
|
loved: currentlyPlayingTrack.loved === "1",
|
|
streak: (() => {
|
|
let current = 0;
|
|
for (const track of res.recenttracks.track) {
|
|
if (track.name === currentlyPlayingTrack.name)
|
|
current++;
|
|
else return current;
|
|
}
|
|
})()
|
|
});
|
|
} else {
|
|
setCurrentlyPlaying(undefined);
|
|
}
|
|
}
|
|
|
|
getLastFmTracks();
|
|
setInterval(getLastFmTracks, 10000);
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<div className="me-container">
|
|
<img
|
|
src="logo.png"
|
|
alt="the nin0 logo"
|
|
style={{
|
|
borderColor: presence
|
|
? ["online", "idle"].includes(
|
|
presence.discord_status
|
|
)
|
|
? "#a6e3a1"
|
|
: "#6c7086"
|
|
: "#6c7086"
|
|
}}
|
|
/>
|
|
<h3>
|
|
nin0 <span style={{ fontSize: "0.9rem" }}>(he/him)</span>
|
|
</h3>
|
|
</div>
|
|
|
|
{currentlyPlaying && (
|
|
<div
|
|
className="spotify-card"
|
|
style={{
|
|
borderColor: lightenColor(
|
|
currentlyPlaying.mainColor,
|
|
90
|
|
)
|
|
}}
|
|
>
|
|
<h3
|
|
style={{
|
|
color: lightenColor(currentlyPlaying.mainColor, 90)
|
|
}}
|
|
>
|
|
Listening to
|
|
</h3>
|
|
<div
|
|
className="spotify-card-background"
|
|
style={{
|
|
backgroundImage: `url(${currentlyPlaying.albumArt})`
|
|
}}
|
|
></div>
|
|
<div
|
|
className="spotify-card-content"
|
|
style={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
marginBottom: "10px"
|
|
}}
|
|
>
|
|
<img
|
|
src={currentlyPlaying.albumArt}
|
|
style={{
|
|
marginRight: "10px",
|
|
width: "50px",
|
|
borderRadius: "5px"
|
|
}}
|
|
/>
|
|
<div>
|
|
<p
|
|
style={{
|
|
margin: "0",
|
|
fontWeight: "600",
|
|
color: lightenColor(
|
|
currentlyPlaying.mainColor,
|
|
90
|
|
)
|
|
}}
|
|
>
|
|
{currentlyPlaying.title}
|
|
</p>
|
|
<p
|
|
style={{
|
|
margin: "0",
|
|
color: lightenColor(
|
|
currentlyPlaying.mainColor,
|
|
85
|
|
)
|
|
}}
|
|
className="secondary-meta"
|
|
>
|
|
{currentlyPlaying.artist}
|
|
</p>
|
|
<p
|
|
style={{
|
|
margin: "0",
|
|
color: lightenColor(
|
|
currentlyPlaying.mainColor,
|
|
85
|
|
)
|
|
}}
|
|
className="secondary-meta"
|
|
>
|
|
{currentlyPlaying.album}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<p style={{ fontSize: "0.9rem" }} className="emoji">
|
|
{(() => {
|
|
const flags: {
|
|
color: string;
|
|
data: string;
|
|
}[] = [];
|
|
if (currentlyPlaying.loved)
|
|
flags.push({
|
|
color: "#f38ba8",
|
|
data: "💞 Loved track"
|
|
});
|
|
if (currentlyPlaying.streak > 1) {
|
|
flags.push({
|
|
color: "#f9e2af",
|
|
data: `⚡ Played ${currentlyPlaying.streak} times in a row`
|
|
});
|
|
}
|
|
return flags.map(flag => (
|
|
<span
|
|
style={{ color: flag.color }}
|
|
className="emoji"
|
|
key={flag.color}
|
|
>
|
|
{flag.data}{" "}
|
|
{flags.indexOf(flag) !==
|
|
flags.length - 1 && (
|
|
<span style={{ color: "white" }}>
|
|
{" "}•{" "}
|
|
</span>
|
|
)}
|
|
</span>
|
|
));
|
|
})()}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|