better spotify card

This commit is contained in:
nin0 2025-04-16 13:32:49 -04:00
parent 74f2fd5ec3
commit e439cde473
Signed by: nin0
SSH key fingerprint: SHA256:NOoDnFVvZNFvqfXCIhzr6oCTDImZAbTTuyAysZ8Ufk8
4 changed files with 92 additions and 11 deletions

View file

@ -19,6 +19,7 @@
"@types/react": "^19.0.10", "@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4", "@types/react-dom": "^19.0.4",
"astro": "^5.5.2", "astro": "^5.5.2",
"color.js": "^1.2.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },

8
pnpm-lock.yaml generated
View file

@ -35,6 +35,9 @@ importers:
astro: astro:
specifier: ^5.5.2 specifier: ^5.5.2
version: 5.5.2(rollup@4.34.9)(typescript@5.8.2) version: 5.5.2(rollup@4.34.9)(typescript@5.8.2)
color.js:
specifier: ^1.2.0
version: 1.2.0
react: react:
specifier: ^19.0.0 specifier: ^19.0.0
version: 19.0.0 version: 19.0.0
@ -954,6 +957,9 @@ packages:
color-string@1.9.1: color-string@1.9.1:
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
color.js@1.2.0:
resolution: {integrity: sha512-0ajlNgWWOR7EK9N6l2h0YKsZPzMCLQG5bheCoTGpGfhkR8tB5eQNItdua1oFHDTeq9JKgSzQJqo+Gp3V/xW+Lw==}
color@4.2.3: color@4.2.3:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'} engines: {node: '>=12.5.0'}
@ -2965,6 +2971,8 @@ snapshots:
simple-swizzle: 0.2.2 simple-swizzle: 0.2.2
optional: true optional: true
color.js@1.2.0: {}
color@4.2.3: color@4.2.3:
dependencies: dependencies:
color-convert: 2.0.1 color-convert: 2.0.1

View file

@ -2,6 +2,11 @@ import "@css/me.css";
import { initLanyard } from "@js/lanyard/lanyard"; import { initLanyard } from "@js/lanyard/lanyard";
import { type LanyardPresence } from "../../../js/lanyard/types"; import { type LanyardPresence } from "../../../js/lanyard/types";
import { useEffect, useState } from "react"; 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() { export default function Me() {
// me-e-eeeee // me-e-eeeee
@ -12,8 +17,10 @@ export default function Me() {
artist: string; artist: string;
album: string; album: string;
albumArt: string; albumArt: string;
mainColor: string;
loved: boolean; loved: boolean;
streak: number; streak: number;
spotifyURL?: string;
} }
| undefined | undefined
>(); >();
@ -26,7 +33,7 @@ export default function Me() {
async function getLastFmTracks() { async function getLastFmTracks() {
const params = new URLSearchParams({ const params = new URLSearchParams({
method: "user.getrecenttracks", method: "user.getrecenttracks",
api_key: "3c5623fa1abbd11c49f53ca18e992ead", api_key,
user: "nin0dev", user: "nin0dev",
limit: "50", limit: "50",
format: "json", format: "json",
@ -47,11 +54,35 @@ export default function Me() {
}) })
) { ) {
const currentlyPlayingTrack = res.recenttracks.track[0]; 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({ setCurrentlyPlaying({
title: currentlyPlayingTrack.name, title: currentlyPlayingTrack.name,
artist: currentlyPlayingTrack.artist.name, artist: currentlyPlayingTrack.artist.name,
album: currentlyPlayingTrack.album["#text"], album: currentlyPlayingTrack.album["#text"],
albumArt: currentlyPlayingTrack.image[1]["#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", loved: currentlyPlayingTrack.loved === "1",
streak: (() => { streak: (() => {
let current = 0; let current = 0;
@ -60,7 +91,8 @@ export default function Me() {
current++; current++;
else return current; else return current;
} }
})() })(),
spotifyURL:
}); });
} else { } else {
setCurrentlyPlaying(undefined); setCurrentlyPlaying(undefined);
@ -93,8 +125,22 @@ export default function Me() {
</div> </div>
{currentlyPlaying && ( {currentlyPlaying && (
<div className="spotify-card"> <div
<h3>Listening to</h3> className="spotify-card"
style={{
borderColor: lightenColor(
currentlyPlaying.mainColor,
90
)
}}
>
<h3
style={{
color: lightenColor(currentlyPlaying.mainColor, 90)
}}
>
Listening to
</h3>
<div <div
className="spotify-card-background" className="spotify-card-background"
style={{ style={{
@ -118,15 +164,40 @@ export default function Me() {
}} }}
/> />
<div> <div>
<p style={{ margin: "0", fontWeight: "600" }}> <p
style={{
margin: "0",
fontWeight: "600",
color: lightenColor(
currentlyPlaying.mainColor,
90
)
}}
>
{currentlyPlaying.title} {currentlyPlaying.title}
</p> </p>
<p style={{ margin: "0" }}> <p
<span className="prefix">by </span> style={{
margin: "0",
color: lightenColor(
currentlyPlaying.mainColor,
85
)
}}
className="secondary-meta"
>
{currentlyPlaying.artist} {currentlyPlaying.artist}
</p> </p>
<p style={{ margin: "0" }}> <p
<span className="prefix">on </span> style={{
margin: "0",
color: lightenColor(
currentlyPlaying.mainColor,
85
)
}}
className="secondary-meta"
>
{currentlyPlaying.album} {currentlyPlaying.album}
</p> </p>
</div> </div>

View file

@ -21,8 +21,9 @@
h3 { h3 {
margin: 13px 0; margin: 13px 0;
} }
.prefix { .secondary-meta {
color: #a6adc8 !important; color: #a6adc8;
font-size: 0.85rem;
} }
.spotify-card-background { .spotify-card-background {
position: absolute; position: absolute;