Skip to content

Instantly share code, notes, and snippets.

@Nate-Wilkins
Last active October 15, 2023 03:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nate-Wilkins/683cde98ea9bcbce7050ce25bafb0183 to your computer and use it in GitHub Desktop.
Save Nate-Wilkins/683cde98ea9bcbce7050ce25bafb0183 to your computer and use it in GitHub Desktop.
spotify_ad_muter.userscript
// ==UserScript==
// @name CodeNull - Spotify Ad Muter
// @author nate-wilkins@code-null.com
// @version 4.0
// @namespace http://tampermonkey.net/
// @description Detects and blocks ads on Spotify. Automatically mute Spotify ads. Turn sound on again after the ad.
// @match https://*.spotify.com/*
// @grant none
// @run-at document-start
// @icon https://www.google.com/s2/favicons?sz=64&domain=spotify.com
// @downloadURL https://gist.github.com/Nate-Wilkins/683cde98ea9bcbce7050ce25bafb0183/raw
// @updateURL https://gist.github.com/Nate-Wilkins/683cde98ea9bcbce7050ce25bafb0183/raw
// ==/UserScript==
document.addEventListener('DOMContentLoaded', async () => {
const selectorDivNowPlayingBar = '[data-testid=now-playing-bar]';
const selectorButtonVolumeMute = '*[aria-label~=Mute]';
const selectorButtonVolumeUnmute = '*[aria-label~=Unmute]';
const selectorDivAdvertisement = '*[aria-label~=Advertisement]';
const $divNowPlayingBar = () => document.querySelector(selectorDivNowPlayingBar);
const $buttonVolumeMute = () => document.querySelector(selectorButtonVolumeMute);
const $buttonVolumeUnmute = () => document.querySelector(selectorButtonVolumeUnmute);
const $divAdvertisement = () => document.querySelector(selectorDivAdvertisement);
const waitFor = (callbackCondition, timeCheck = 100, timeOut = 1000) => {
let timePassed = 0;
let idInterval = null;
return new Promise((resolve, reject) => {
idInterval = setInterval(() => {
timePassed += timeCheck;
if (callbackCondition()) {
clearInterval(idInterval);
resolve();
} else {
if (timePassed >= timeOut) {
reject(new Error("Timed out waiting for condition."));
}
}
}, timeCheck);
});
};
await waitFor($divNowPlayingBar);
let playInterval;
new MutationObserver(async () => {
if ($divAdvertisement() && $buttonVolumeMute()) {
$buttonVolumeMute().click();
await waitFor(() => !$divAdvertisement(), 500, 10 * 60 * 1000);
$buttonVolumeUnmute().click();
}
}).observe($divNowPlayingBar(), {
characterData: true,
childList: true,
attributes: true,
subtree: true
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment