Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions websites/S/Spotify/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "https://schemas.premid.app/metadata/1.16",
"apiVersion": 1,
"author": {
"name": "itsyashbtw",
"id": "568021861871517716"
},
"service": "Spotify",
"altnames": [
"Spotify Web"
],
"description": {
"en": "Spotify is a digital music, podcast, and video service that gives you access to millions of songs and other content from creators all over the world."
},
"url": "open.spotify.com",
"regExp": "^https?[:][/][/]open[.]spotify[.]com[/]",
"version": "1.0.0",
"logo": "https://cdn.rcd.gg/PreMiD/websites/S/Spotify%20Podcasts/assets/logo.png",
"thumbnail": "https://cdn.rcd.gg/PreMiD/websites/S/Spotify%20Podcasts/assets/thumbnail.png",
"color": "#1DB954",
"category": "music",
"tags": [
"music",
"streaming",
"audio"
],
"settings": [
{
"id": "lang",
"multiLanguage": true
},
{
"id": "privacy",
"title": "Privacy Mode",
"icon": "fad fa-user-secret",
"value": false
},
{
"id": "timestamps",
"title": "Show timestamps",
"icon": "fad fa-stopwatch",
"value": true
},
{
"id": "cover",
"title": "Show Cover Art",
"icon": "fad fa-images",
"value": true
},
{
"id": "buttons",
"title": "Show Buttons",
"icon": "fad fa-compress-arrows-alt",
"value": true
}
]
}
109 changes: 109 additions & 0 deletions websites/S/Spotify/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { ActivityType, Assets, getTimestamps,timestampFromFormat } from 'premid'

const presence = new Presence({
clientId: '1458014647193047042',
})

enum ActivityAssets {
Logo = 'https://cdn.rcd.gg/PreMiD/websites/S/Spotify%20Podcasts/assets/logo.png',
}

async function getStrings() {
return presence.getStrings({
play: 'general.playing',
pause: 'general.paused',
})
}

let strings: Awaited<ReturnType<typeof getStrings>>
let oldLang: string | null = null

presence.on('UpdateData', async () => {
const [newLang, privacy, timestamps, cover, buttons] = await Promise.all([
presence.getSetting<string>('lang').catch(() => 'en'),
presence.getSetting<boolean>('privacy'),
presence.getSetting<boolean>('timestamps'),
presence.getSetting<boolean>('cover'),
presence.getSetting<boolean>('buttons'),
])

if (oldLang !== newLang || !strings) {
oldLang = newLang
strings = await getStrings()
}

// Check if music is playing
const playPauseButton = document.querySelector('[data-testid=control-button-playpause]')
const isPlaying = playPauseButton?.getAttribute('aria-label')?.toLowerCase().includes('pause')

// Only show presence when music is playing
if (!isPlaying) {
presence.clearActivity()
return
}

// Get track info
const trackName = document.querySelector(
'[data-testid="context-item-link"], [data-testid="nowplaying-track-link"]',
)?.textContent

const artistName = document.querySelector(
'[data-testid="context-item-info-artist"], [data-testid="track-info-artists"]',
)?.textContent

if (!trackName) {
presence.clearActivity()
return
}

const presenceData: PresenceData = {
largeImageKey: ActivityAssets.Logo,
type: ActivityType.Listening,
details: trackName,
state: artistName || 'Unknown Artist',
smallImageKey: Assets.Play,
smallImageText: strings.play,
}

// Get timestamps
if (timestamps) {
const currentTime = document.querySelector('[data-testid="playback-position"]')?.textContent
const duration = document.querySelector('[data-testid="playback-duration"]')?.textContent

if (currentTime && duration) {
[presenceData.startTimestamp, presenceData.endTimestamp] = getTimestamps(
timestampFromFormat(currentTime),
timestampFromFormat(duration),
)
}
}

// Get cover art
if (cover) {
const albumCover = document.querySelector<HTMLAnchorElement>(
':is(a[data-testid=cover-art-link], a[data-testid=context-link])',
)
const coverImg = albumCover?.querySelector('img')?.src
if (coverImg) {
presenceData.largeImageKey = coverImg
presenceData.smallImageKey = ActivityAssets.Logo
}
}

// Add button
if (buttons) {
presenceData.buttons = [
{ label: 'Listen on Spotify', url: document.location.href },
]
}

// Apply privacy mode
if (privacy) {
presenceData.details = 'Listening to music'
delete presenceData.state
presenceData.largeImageKey = ActivityAssets.Logo
delete presenceData.smallImageKey
}

presence.setActivity(presenceData)
})
Loading