Last active
August 10, 2024 14:30
-
-
Save simonwep/24f8cdcd6d32d86e929004013bd660ae to your computer and use it in GitHub Desktop.
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
// ==UserScript== | |
// @name Spotify ad skipper | |
// @version 1.0 | |
// @namespace http://tampermonkey.net/ | |
// @description Detects and skips ads on spotify | |
// @match https://*.spotify.com/* | |
// @grant none | |
// @run-at document-start | |
// @downloadURL https://gist.githubusercontent.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw | |
// @updateURL https://gist.githubusercontent.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw | |
// ==/UserScript== | |
!async function () { | |
async function queryAsync(query) { | |
return new Promise(resolve => { | |
const interval = setInterval(() => { | |
const element = document.querySelector(query); | |
if (element) { | |
clearInterval(interval); | |
return resolve(element); | |
} | |
}, 250); | |
}); | |
} | |
/** | |
* Inject a middleware function in a object or instance | |
* @param ctx Object or instance | |
* @param fn Function name | |
* @param middleware Middleware function | |
* @param transform Transform function result | |
*/ | |
function inject({ctx, fn, middleware, transform}) { | |
const original = ctx[fn]; | |
ctx[fn] = function () { | |
if (!middleware || middleware.call(this, ...arguments) !== false) { | |
const result = original.call(this, ...arguments); | |
return transform ? transform.call(this, result, ...arguments) : result; | |
} | |
}; | |
} | |
const nowPlayingBar = await queryAsync('.now-playing-bar'); | |
const playButton = await queryAsync('button[title=Play], button[title=Pause]'); | |
let audio; | |
inject({ | |
ctx: document, | |
fn: 'createElement', | |
transform(result, type) { | |
if (type === 'audio') { | |
audio = result; | |
} | |
return result; | |
} | |
}); | |
let playInterval; | |
new MutationObserver(() => { | |
const link = document.querySelector('.now-playing > a'); | |
if (link) { | |
if (!audio) { | |
return console.error('Audio-element not found!'); | |
} | |
if (!playButton) { | |
return console.error('Play-button not found!'); | |
} | |
// console.log('Ad found', audio, playButton, nowPlayingBar); | |
audio.src = ''; | |
playButton.click(); | |
if (!playInterval) { | |
playInterval = setInterval(() => { | |
if (!document.querySelector('.now-playing > a') && playButton.title === 'Pause') { | |
clearInterval(playInterval); | |
playInterval = null; | |
} else { | |
playButton.click(); | |
} | |
}, 500); | |
} | |
} | |
}).observe(nowPlayingBar, { | |
characterData: true, | |
childList: true, | |
attributes: true, | |
subtree: true | |
}); | |
// Hide upgrade-button and captcha-errors, we don't what to see that. | |
const style = document.createElement('style'); | |
style.innerHTML = ` | |
[aria-label="Upgrade to Premium"], | |
body > div:not(#main) { | |
display: none !important; | |
} | |
`; | |
document.body.appendChild(style); | |
}(); |
Works perfectly! I don't have much BAT but here's a tip @simonwep
Great work, thankyou.
Why don't you publish this on Greasy Fork?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This handy
inject
function, is that part of a library somewhere?