1
0
Fork 0
forked from nin0/website
website/src/components/windows/mainWindow/Me.tsx
2025-04-16 13:32:59 -04:00

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