Last active
January 24, 2026 00:15
-
-
Save lexisother/ba15b9f0a8182934a288e9f583e85047 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name mediasession fixer | |
| // @version 2026-01-22 | |
| // @description fixes my everlasting "missing artist metadata" issue in spotify | |
| // @author Alyxia | |
| // @match https://open.spotify.com/* | |
| // @icon https://www.google.com/s2/favicons?sz=64&domain=spotify.com | |
| // @grant none | |
| // ==/UserScript== | |
| const __FIXER__ = window.__FIXER__ = {}; | |
| const FULL_SELECTOR = 'ul[aria-label="Now playing"] [data-encore-id="listRowSubtitle"] > * > :has([href])'; | |
| const NOW_PLAYING_SELECTOR = 'ul[aria-label="Now playing"]'; | |
| const ARTIST_TEXT_SELECTOR = '[data-encore-id="listRowSubtitle"] > * > :has([href])'; | |
| (async function() { | |
| 'use strict'; | |
| console.log('fixer: init'); | |
| while (!(__FIXER__.target = document.querySelector(NOW_PLAYING_SELECTOR))) { | |
| console.log('fixer: waiting'); | |
| await new Promise(resolve => setTimeout(resolve, 100)); | |
| } | |
| console.log('fixer: done'); | |
| // target = document.querySelector('ul[aria-label="Now playing"]'); | |
| __FIXER__.observer = new MutationObserver((list) => { | |
| // console.log('handling\n', list); | |
| for (const rec of list) { | |
| if (rec.type === 'childList') { | |
| if ( | |
| // This is the previous track being removed | |
| !!(Array.from(rec.removedNodes).length) || | |
| // This is a record for the addition of the new track before the old one was removed. | |
| // The addedNodes entry here is not fully initialized | |
| !!rec.previousSibling | |
| ) continue; | |
| // This is the play/pause button being switched out in the now playing cover art | |
| else if (!!(Array.from(rec.target.classList.values().filter(v => v.match('-button__'))).length)) { | |
| console.log('fixer: handling presumed play/pause'); | |
| if (!(__FIXER__.currentArtist = document.querySelector(FULL_SELECTOR))) { | |
| console.log('fixer: play/pause triggered but no current artist found?') | |
| } | |
| if (__FIXER__.currentArtist.innerText && !navigator.mediaSession.metadata.artist) { | |
| navigator.mediaSession.metadata.artist = __FIXER__.currentArtist.innerText; | |
| console.log('fixer: MEDIASESSION SET!', navigator.mediaSession.metadata); | |
| } | |
| return; | |
| } | |
| else { | |
| console.log('fixer: handling presumed new song'); | |
| if (!(__FIXER__.newTrack = Array.from(rec.addedNodes)[0])) { | |
| console.warn('fixer: new track started but no track node?') | |
| } | |
| let artistEl = __FIXER__.newTrack.querySelector('[data-encore-id="listRowSubtitle"] > * > :has([href])'); | |
| console.log('fixer: artistEl found', artistEl); | |
| if (artistEl.innerText) { | |
| navigator.mediaSession.metadata.artist = artistEl.innerText; | |
| console.log('fixer: MEDIASESSION SET!', navigator.mediaSession.metadata); | |
| } | |
| return; | |
| } | |
| } | |
| } | |
| console.log('\n\n') | |
| }); | |
| __FIXER__.observer.observe(__FIXER__.target, { childList: true, subtree: true }); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment