// See https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript function uuidv4() { return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); } function onNewSong(song) { browser.runtime.sendMessage(JSON.stringify({ type: 'new-song', song: song })); } function onUpdateSong(song) { browser.runtime.sendMessage(JSON.stringify({ type: 'update-song', song: song })); } function onAdvertisement() { browser.runtime.sendMessage(JSON.stringify({ type: 'advertisement' })); } function onHeartbeat() { browser.runtime.sendMessage(JSON.stringify({ type: 'heartbeat' })); } let song = { name: '', artists: [] }; // Initial Song Data function getNameElement() { return document.querySelector('.Root__now-playing-bar .now-playing-bar-container div.track-info__name span a'); } function getArtistElements() { return document.querySelectorAll('.Root__now-playing-bar .now-playing-bar-container div.track-info__artists span a'); } function getAlbumArtElement() { return document.querySelector('.Root__now-playing-bar .now-playing-bar-container .cover-art .cover-art-image'); } // After album is loaded function getDurationElement() { return document.querySelector('.Root__now-playing-bar .now-playing-bar .playback-bar .playback-bar__progress-time:last-child'); } function getAlbumNameElement() { return document.querySelector('.TrackListHeader .mo-info-name'); } function getAlbumArtFullElement() { return document.querySelector('.TrackListHeader .cover-art .cover-art-image'); } function checkSong() { let nameElement = getNameElement(); let artistsElement = getArtistElements(); let albumArtElement = getAlbumArtElement(); let name = null; let artists = []; let albumArtLink = null; name = nameElement ? nameElement.innerText : 'Unknown Name'; if ( name == 'Advertisement' || document.title.toLowerCase().indexOf('advertisement') != -1 || document.title.toLowerCase().indexOf('spotify') != -1 ) { console.log('advertisement'); onAdvertisement(); return; } for (let i = 0; i < artistsElement.length; ++i) { let artistElement = artistsElement[i]; artists.push(artistElement.innerText); } let albumArtLinkStyle = albumArtElement.getAttribute('style'); albumArtLink = albumArtLinkStyle.substring('background-image: url("'.length, albumArtLinkStyle.length - '");'.length); if (name != song.name || artists.join(', ') != song.artists.join(', ')) { // new song song = { guid: uuidv4(), name: name, artists: artists, album: { name: 'Unknown Album', art: albumArtLink } }; console.log('new song', song); onNewSong(song); // Click the album link nameElement.click(); setTimeout(() => { let durationElement = getDurationElement(); let albumNameElement = getAlbumNameElement(); let albumArtFullElement = getAlbumArtFullElement(); let duration = durationElement ? durationElement.innerText : null; if (duration) { let s = duration.split(':'); duration = parseInt(s[0]) * 60 + parseInt(s[1]); } let albumName = albumNameElement ? albumNameElement.getAttribute('title') : 'Unknown Album'; let albumArtFullLinkStyle = albumArtFullElement.getAttribute('style'); let albumArtFullLink = albumArtLinkStyle.substring('background-image: url("'.length, albumArtFullLinkStyle.length - 3); song.duration = duration; song.album.name = albumName; song.album.artFull = albumArtFullLink; onUpdateSong(song); }, 5000); // give 5 seconds to load } } console.log('Spotify Song Data Sender Extension Running'); // Send heartbeats every 3 seconds as soon as the content script is loaded setInterval(() => { onHeartbeat(); }, 3000); onHeartbeat(); // Check for new songs every 300 ms setInterval(() => { checkSong(); }, 300);