feat: add spotify status

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