From 651da6ce72c2f06b533614f53f8a15fc93b6e0bd Mon Sep 17 00:00:00 2001 From: joerkig <44418429+joerkig@users.noreply.github.com> Date: Mon, 3 Mar 2025 21:21:42 +0100 Subject: [PATCH] feat(Suno): add activity (#9362) --- websites/S/Suno/metadata.json | 32 +++++++ websites/S/Suno/presence.ts | 159 ++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 websites/S/Suno/metadata.json create mode 100644 websites/S/Suno/presence.ts diff --git a/websites/S/Suno/metadata.json b/websites/S/Suno/metadata.json new file mode 100644 index 000000000000..a2b7d7fa52e5 --- /dev/null +++ b/websites/S/Suno/metadata.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://schemas.premid.app/metadata/1.13", + "apiVersion": 1, + "author": { + "id": "205984221859151873", + "name": "joerkig" + }, + "service": "Suno", + "description": { + "en": "Suno is building a future where anyone can make great music." + }, + "url": "suno.com", + "version": "1.0.0", + "logo": "https://i.imgur.com/hhoRf5s.png", + "thumbnail": "https://cdn1.suno.ai/preview.jpg", + "color": "#0e0808", + "category": "music", + "tags": [ + "ai", + "generation", + "music", + "songs" + ], + "settings": [ + { + "id": "browsing", + "title": "Show Browsing", + "icon": "fad fa-compass", + "value": false + } + ] +} diff --git a/websites/S/Suno/presence.ts b/websites/S/Suno/presence.ts new file mode 100644 index 000000000000..dca7ef857732 --- /dev/null +++ b/websites/S/Suno/presence.ts @@ -0,0 +1,159 @@ +import { ActivityType, Assets, getTimestampsFromMedia } from 'premid' + +const presence = new Presence({ + clientId: '1345681912458641469', +}) +const browsingTimestamp = Math.floor(Date.now() / 1000) + +enum ActivityAssets { + Logo = 'https://i.imgur.com/hhoRf5s.png', + Loading = 'https://i.imgur.com/BmD5TZZ.gif', +} + +presence.on('UpdateData', async () => { + const presenceData: PresenceData = { + largeImageKey: ActivityAssets.Logo, + startTimestamp: browsingTimestamp, + type: ActivityType.Listening, + } + const { href, pathname } = document.location + const pathArray = pathname.split('/') + const browsing = await presence.getSetting('browsing') + const playState = JSON.parse(localStorage.getItem('play-state') ?? '{}') + const song = document.querySelector('audio') + + if (browsing) { + presenceData.details = 'Browsing Suno' + + switch (pathArray[1]) { + case '': { + presenceData.details = 'Viewing Home' + break + } + case 'me': { + presenceData.details = 'Viewing their library' + presenceData.state = document.querySelector(`[role='tab'][tabindex='0']`)?.textContent + break + } + case 'explore': { + presenceData.details = 'Exploring Suno' + if (song && !song.paused) { + presenceData.state = document.querySelector('.musicPlayerHeader span')?.textContent + presenceData.details = document.querySelector('.musicPlayerTitle a')?.textContent; + [presenceData.startTimestamp, presenceData.endTimestamp] = getTimestampsFromMedia(song) + } + break + } + case 'create': { + presenceData.details = 'Viewing their Workspace' + break + } + case 'search': { + presenceData.details = `Searching ${document.querySelector(`[role='tab'][tabindex='0']`)?.textContent?.toLowerCase()}` + break + } + case 'song': { + presenceData.details = document.querySelector('input[disabled]')?.value + presenceData.state = document.querySelectorAll(`a[href^='/@']`)[1]?.textContent + presenceData.largeImageText = document.querySelector(`[role='tab'][aria-selected='true'] span`)?.textContent + presenceData.largeImageKey = document.querySelector(`img[src*='${pathArray[2]}']`)?.src ?? ActivityAssets.Logo + presenceData.buttons = [ + { + label: 'View Song', + url: href, + }, + { + label: 'View Creator', + url: document.querySelector(`a[href^='/@']`), + }, + ] + break + } + case 'playlist': { + presenceData.details = 'Viewing a playlist' + presenceData.state = document.querySelector('h1')?.textContent + presenceData.largeImageText = document.querySelectorAll(`a[href^='/@']`)[1]?.textContent + presenceData.largeImageKey = document.querySelector('#main-container img')?.src ?? ActivityAssets.Logo + presenceData.buttons = [ + { + label: 'View Playlist', + url: href, + }, + { + label: 'View Creator', + url: document.querySelector(`a[href^='/@']`), + }, + ] + break + } + case 'persona': { + presenceData.details = 'Viewing a persona' + presenceData.state = document.querySelector('h1')?.textContent + presenceData.largeImageText = document.querySelector(`a[href^='/@']`)?.textContent + presenceData.largeImageKey = document.querySelector('#main-container img')?.src ?? ActivityAssets.Logo + presenceData.buttons = [ + { + label: 'View Persona', + url: href, + }, + { + label: 'View Creator', + url: document.querySelector(`#main-container a[href^='/@']`)?.href ?? href, + }, + ] + break + } + default: { + if (pathArray[1]?.startsWith('@')) { + presenceData.details = 'Viewing a profile' + presenceData.state = document.querySelector(`h1`)?.textContent + presenceData.largeImageText = document.querySelector('#main-container button.text-lg.text-foreground-primary')?.textContent + presenceData.largeImageKey = document.querySelector('img.rounded-full')?.src ?? ActivityAssets.Logo + presenceData.buttons = [ + { + label: 'View Page', + url: href, + }, + ] + } + } + } + } + + if (navigator.mediaSession.metadata && song && !song.paused && song) { + const artwork = navigator.mediaSession.metadata?.artwork?.[0]?.src + const songUrl = document.querySelector(`a[aria-label*='Playbar: Title']`)?.href + const creatorUrl = document.querySelector(`a[aria-label*='Playbar: Artist']`)?.href + presenceData.details = navigator.mediaSession.metadata.title + presenceData.state = document.querySelector(`a[aria-label*='Playbar: Artist'] span`)?.textContent + presenceData.largeImageKey = artwork ? `${artwork}?width=256` : ActivityAssets.Logo + presenceData.largeImageText = `${navigator.mediaSession.metadata.artist.replace('Suno - ', '').slice(0, 125)}${navigator.mediaSession.metadata.artist.length > 125 ? '...' : ''}` + presenceData.smallImageKey = song.duration === Infinity + ? ActivityAssets.Loading + : playState.repeat + ? Assets.RepeatOne + : Assets.Play + presenceData.smallImageText = song.duration === Infinity + ? 'Generating' + : playState.repeat + ? 'Repeat One' + : 'Playing'; + [presenceData.startTimestamp, presenceData.endTimestamp] = getTimestampsFromMedia(song) + if (songUrl && creatorUrl) { + presenceData.buttons = [ + { + label: 'View Song', + url: songUrl, + }, + { + label: 'View Creator', + url: creatorUrl, + }, + ] + } + } + + if (presenceData.details) + presence.setActivity(presenceData) + else presence.clearActivity() +})