Last active
February 3, 2023 18:35
-
-
Save jotafeldmann/963f485805543184b643761c3c3fbdac to your computer and use it in GitHub Desktop.
Music Player Notification: add desktop tracks transitions notifications for Spotify and Youtube Music web player.
This file contains 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
/* | |
# Music Player Notification | |
Notifications for tracks transitions | |
- Author: Jorge Feldmann (https://github.com/jotafeldmann) | |
- Last update: see the gist update date | |
- Feel free to manipulate and add more music players notifications | |
## Instructions: | |
1. Go to the sources URL (check the code) | |
2. Then paste the following code in the console | |
3. Finally, play any playlist or song and watch notifications about the music | |
## Development | |
- https://gist.github.com/jotafeldmann/963f485805543184b643761c3c3fbdac | |
- Using `let` so you can change the code and just paste it again | |
- No plans for any browser plugin: lots of trouble, for this dummy stuff | |
- Use and change this code by your own | |
- No guarantees | |
*/ | |
let MusicSourceFactory = ({ | |
url, | |
domNodeClassNameToObserve, | |
getTrackName, | |
getArtistName, | |
getAlbumCoverUrl | |
} = {}) => ({ | |
[url]: { | |
domNodeClassNameToObserve, | |
getTrackName, | |
getArtistName, | |
getAlbumCoverUrl, | |
} | |
}) | |
let musicSourcesConfig = { | |
... MusicSourceFactory({ | |
url: 'music.youtube.com', | |
domNodeClassNameToObserve: '.title.style-scope.ytmusic-player-bar', | |
getTrackName: () => document.querySelector('.title.style-scope.ytmusic-player-bar').textContent, | |
getArtistName: () => document.querySelector('.yt-simple-endpoint.style-scope.yt-formatted-string').textContent, | |
getAlbumCoverUrl: () => document.querySelector('.image.style-scope.ytmusic-player-bar').src | |
}), | |
... MusicSourceFactory({ | |
url: 'open.spotify.com', | |
domNodeClassNameToObserve: 'div[data-testid="now-playing-widget"]', | |
getTrackName: () => document.querySelector('div[data-testid="now-playing-widget"]').innerText.split('\n')[0], | |
getArtistName: () => document.querySelector('div[data-testid="now-playing-widget"]').innerText.split('\n')[1], | |
getAlbumCoverUrl: () => document.querySelector('div[data-testid="now-playing-widget"]').children[0].querySelector('img').src, | |
}) | |
} | |
let MusicPlayerNotification = (() => { | |
const observerNodeConfig = { attributes: true, childList: true, subtree: true, characterData: true } | |
let domNodeClassNameToObserve, getTrackName, getArtistName, getAlbumCoverUrl, observer | |
const bounceError = fn => { | |
try { | |
return fn() | |
} catch (err) { | |
console.error(err) | |
return '' | |
} | |
} | |
const emitTrackChanges = () => (new Notification(bounceError(getTrackName), { | |
body: bounceError(getArtistName), | |
icon: bounceError(getAlbumCoverUrl), | |
silent: true | |
})).onclick = () => window.focus() | |
const stopObserver = () => observer.disconnect() | |
const testNotifications = async () => Notification | |
.requestPermission() | |
.then(() => new Notification('Testing notification, if you can see this, its ready')) | |
.catch(err => { console.error (err); throw new Error(err) }) | |
const initMusicNotifications = () => { | |
const domNodeToObserve = document.querySelector(domNodeClassNameToObserve) | |
observer = new MutationObserver(emitTrackChanges) | |
stopObserver() | |
observer.observe(domNodeToObserve, observerNodeConfig) | |
} | |
const start = async (config) => { | |
await testNotifications() | |
domNodeClassNameToObserve = config.domNodeClassNameToObserve | |
getTrackName = config.getTrackName | |
getArtistName = config.getArtistName | |
getAlbumCoverUrl = config.getAlbumCoverUrl | |
initMusicNotifications() | |
} | |
return { | |
start, | |
stop: () => stopObserver() | |
} | |
})() | |
let init = () => { | |
let extraTimeForDOMLoad = 2000 | |
let getMusicSource = (currentUrl = '', urlSources = ['']) => urlSources.filter(s => currentUrl.indexOf(s) > -1)[0] | |
let source = getMusicSource(document.URL, Object.keys(musicSourcesConfig)) | |
let config = musicSourcesConfig[source] | |
if (!config) { let msg = 'Cant detect music source'; alert(msg); throw new Error(msg)} | |
let checkAndPlay = () => (document.readyState === 'complete' ? setTimeout(() => MusicPlayerNotification.start(config), extraTimeForDOMLoad) : null) | |
checkAndPlay() || document.addEventListener('readystatechange', checkAndPlay) | |
} | |
init() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice trick, dude!