feat: add spotify status

This commit is contained in:
2026-05-30 19:49:43 -03:00
parent 9a2d73a6cb
commit cc7ab4ad9f
+70 -23
View File
@@ -17,10 +17,22 @@ interface LanyardData {
active_on_discord_embedded: boolean;
active_on_discord_vr: boolean;
listening_to_spotify: boolean;
spotify: null | Record<string, any>;
spotify: SpotifyData | null;
kv: Record<string, string>;
}
interface SpotifyData {
album: string;
album_art_url: string;
artist: string;
song: string;
track_id: string;
timestamps: {
start: number;
end: number;
};
}
interface DiscordUser {
id: string;
username: string;
@@ -31,9 +43,26 @@ interface DiscordUser {
bot: boolean;
public_flags: number;
avatar_decoration_data: null | any;
collectibles?: Record<string, any>;
display_name_styles?: Record<string, any>;
primary_guild?: Record<string, any>;
collectibles?: {
nameplate?: {
asset: string;
expires_at: string | null;
label: string;
palette: string;
sku_id: string;
};
};
display_name_styles?: {
colors: any[];
effect_id: number;
font_id: number;
};
primary_guild?: {
badge: null | any;
identity_enabled: boolean;
identity_guild_id: null | string;
tag: null | string;
};
}
interface DiscordActivity {
@@ -62,6 +91,11 @@ interface DiscordActivity {
application_id?: string;
flags?: number;
platform?: string;
sync_id?: string;
content_classification?: {
data: null | any;
loaded: boolean;
};
}
function resolveDiscordAsset(image: string | undefined): string {
@@ -113,15 +147,13 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
fetchRichPresence();
const interval = setInterval(fetchRichPresence, 30000);
return () => clearInterval(interval);
}, []);
}, [userId]);
if (loading) {
if (loading)
return <p style={{ fontSize: '0.75rem', fontStyle: 'italic', color: 'var(--text-dim)' }}>loading status...</p>;
}
if (!presence) {
if (!presence)
return <p style={{ fontSize: '0.75rem', fontStyle: 'italic', color: 'var(--text-dim)' }}>offline</p>;
}
const customActivity = presence.activities.find(act => act.id === "custom");
const customStatusText = customActivity
@@ -132,9 +164,28 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
.filter(act => act.type === 0)
.sort((a, b) => (b.assets ? 1 : 0) - (a.assets ? 1 : 0))[0] as DiscordActivity | undefined;
const gameImage = gameActivity?.assets
? resolveDiscordAsset(gameActivity.assets.small_image || gameActivity.assets.large_image)
: "";
const isListeningToSpotify = presence.listening_to_spotify && presence.spotify;
let primaryActivity = null;
let activityText = "";
let activityImage = "";
if (gameActivity) {
primaryActivity = gameActivity;
activityText = `playing: ${gameActivity.name.toLowerCase()}`;
if (gameActivity.details)
activityText += `${gameActivity.details}`;
activityImage = gameActivity.assets
? resolveDiscordAsset(gameActivity.assets.small_image || gameActivity.assets.large_image)
: "";
}
else if (isListeningToSpotify && presence.spotify) {
primaryActivity = { name: "Spotify" } as DiscordActivity;
activityText = `listening to: ${presence.spotify.song}${presence.spotify.artist}`;
activityImage = presence.spotify.album_art_url || "";
}
return (
<div className="discord-status-compact">
@@ -149,14 +200,10 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
<div className="status-details">
<span className="status-text">
{gameActivity ? (
<>
playing: <em>{gameActivity.name.toLowerCase()}</em>
</>
{primaryActivity ? (
<>{activityText}</>
) : (
<>
currently: <em>{STATUS_LABELS[presence.discord_status]}</em>
</>
<>currently: <em>{STATUS_LABELS[presence.discord_status]}</em></>
)}
</span>
@@ -167,13 +214,13 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
)}
</div>
{gameImage && gameActivity && (
{activityImage && primaryActivity && (
<img
src={gameImage}
alt={gameActivity.name}
src={activityImage}
alt={primaryActivity.name}
className="game-icon"
/>
)}
</div>
);
}
}