Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ejnshtein/57c23ea40adb54a9d19bc92d58b60e0a to your computer and use it in GitHub Desktop.

Select an option

Save ejnshtein/57c23ea40adb54a9d19bc92d58b60e0a to your computer and use it in GitHub Desktop.

Revisions

  1. @simonwep simonwep renamed this gist Jan 15, 2020. 1 changed file with 0 additions and 0 deletions.
  2. @simonwep simonwep revised this gist Jan 10, 2020. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions tm-spotify-ad-skipper.js
    Original file line number Diff line number Diff line change
    @@ -94,4 +94,15 @@
    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);
    }();
  3. @simonwep simonwep revised this gist Sep 5, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions tm-spotify-ad-skipper.js
    Original file line number Diff line number Diff line change
    @@ -6,8 +6,8 @@
    // @match https://*.spotify.com/*
    // @grant none
    // @run-at document-start
    // @downloadURL https://gist.github.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw/b08df5ba372fbeab156d93337e36f0070991f2b0/tm-spotify-ad-skipper.js
    // @updateURL https://gist.github.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw/b08df5ba372fbeab156d93337e36f0070991f2b0/tm-spotify-ad-skipper.js
    // @downloadURL https://gist.github.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw
    // @updateURL https://gist.github.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw
    // ==/UserScript==

    !async function () {
  4. @simonwep simonwep revised this gist Sep 5, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions tm-spotify-ad-skipper.js
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,8 @@
    // @match https://*.spotify.com/*
    // @grant none
    // @run-at document-start
    // @downloadURL https://gist.github.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw/b08df5ba372fbeab156d93337e36f0070991f2b0/tm-spotify-ad-skipper.js
    // @updateURL https://gist.github.com/Simonwep/24f8cdcd6d32d86e929004013bd660ae/raw/b08df5ba372fbeab156d93337e36f0070991f2b0/tm-spotify-ad-skipper.js
    // ==/UserScript==

    !async function () {
  5. @simonwep simonwep renamed this gist Jul 2, 2019. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  6. @simonwep simonwep revised this gist Apr 12, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions spotify-ad-skipper.js
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    // ==UserScript==
    // @name Spotify ad muter
    // @name Spotify ad skipper
    // @version 1.0
    // @namespace http://tampermonkey.net/
    // @description A small script which will mute spotify if ads getting played
    // @description Detects and skips ads on spotify
    // @match https://*.spotify.com/*
    // @grant none
    // @run-at document-start
  7. @simonwep simonwep revised this gist Jan 27, 2019. 1 changed file with 69 additions and 67 deletions.
    136 changes: 69 additions & 67 deletions spotify-ad-skipper.js
    Original file line number Diff line number Diff line change
    @@ -1,93 +1,95 @@
    // ==UserScript==
    // @name Spotify ad skipper
    // @name Spotify ad muter
    // @version 1.0
    // @namespace http://tampermonkey.net/
    // @description A small script which will help to skip audio ads on spotify
    // @description A small script which will mute spotify if ads getting played
    // @match https://*.spotify.com/*
    // @grant none
    // @run-at document-end
    // @run-at document-start
    // ==/UserScript==

    !async function () {

    function getLocationQueries() {
    if (document.location) {
    const raw = document.location.search.substring(1);
    const rawParts = raw.split(/&/g);
    const queries = {};

    for (let p of rawParts) {
    const name = decodeURIComponent(p.substring(0, p.indexOf('=')));
    queries[name] = decodeURIComponent(p.substring(name.length + 1, p.length));
    }

    return queries;
    }
    }

    function createLocationQuery(obj) {
    const keys = Object.keys(obj);
    let query = '?';

    for (let i = 0; i < keys.length; i++) {
    const name = encodeURIComponent(keys[i]);
    const value = encodeURIComponent(obj[name]);
    query += `${name}=${value}&`;
    }

    return query.substring(0, query.length - 1);
    }

    async function queryAsync(query) {
    return new Promise(resolve => {
    !function check() {
    const interval = setInterval(() => {
    const element = document.querySelector(query);
    if (element) {
    clearInterval(interval);
    return resolve(element);
    }
    setTimeout(check, 250);
    }();
    }, 250);
    });
    }

    async function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    /**
    * 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 queries = getLocationQueries();
    if (Boolean(queries.autoplay)) {
    queryAsync('button.spoticon-play-16').then(async b => {
    while (b.title === 'Play') {
    b.click();
    await sleep(2000);
    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;
    }
    });
    }

    // Wait a little bit
    setTimeout(() => {
    queryAsync('.now-playing-bar').then(element => {
    new MutationObserver(() => {
    const link = document.querySelector('.now-playing > a');
    console.log('Check for ad.', new Date().toString());
    return result;
    }
    });

    if (link) {
    console.log('Ad found, reload and autoplay.');
    queries.autoplay = true;
    let playInterval;
    new MutationObserver(() => {
    const link = document.querySelector('.now-playing > a');

    // Reload page
    const base = document.location.origin + document.location.pathname;
    const queryString = createLocationQuery(queries);
    if (link) {

    console.log('Open', base + queryString);
    window.open(base + queryString, '_self');
    }
    }).observe(element, {
    characterData: true,
    childList: true,
    attributes: true,
    subtree: true
    });
    });
    }, 1000);
    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
    });
    }();
  8. @simonwep simonwep revised this gist Oct 4, 2018. No changes.
  9. @simonwep simonwep created this gist Jul 13, 2018.
    93 changes: 93 additions & 0 deletions spotify-ad-skipper.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,93 @@
    // ==UserScript==
    // @name Spotify ad skipper
    // @version 1.0
    // @namespace http://tampermonkey.net/
    // @description A small script which will help to skip audio ads on spotify
    // @match https://*.spotify.com/*
    // @grant none
    // @run-at document-end
    // ==/UserScript==

    !async function () {

    function getLocationQueries() {
    if (document.location) {
    const raw = document.location.search.substring(1);
    const rawParts = raw.split(/&/g);
    const queries = {};

    for (let p of rawParts) {
    const name = decodeURIComponent(p.substring(0, p.indexOf('=')));
    queries[name] = decodeURIComponent(p.substring(name.length + 1, p.length));
    }

    return queries;
    }
    }

    function createLocationQuery(obj) {
    const keys = Object.keys(obj);
    let query = '?';

    for (let i = 0; i < keys.length; i++) {
    const name = encodeURIComponent(keys[i]);
    const value = encodeURIComponent(obj[name]);
    query += `${name}=${value}&`;
    }

    return query.substring(0, query.length - 1);
    }

    async function queryAsync(query) {
    return new Promise(resolve => {
    !function check() {
    const element = document.querySelector(query);
    if (element) {
    return resolve(element);
    }
    setTimeout(check, 250);
    }();
    });
    }

    async function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    }

    const queries = getLocationQueries();
    if (Boolean(queries.autoplay)) {
    queryAsync('button.spoticon-play-16').then(async b => {
    while (b.title === 'Play') {
    b.click();
    await sleep(2000);
    }
    });
    }

    // Wait a little bit
    setTimeout(() => {
    queryAsync('.now-playing-bar').then(element => {
    new MutationObserver(() => {
    const link = document.querySelector('.now-playing > a');
    console.log('Check for ad.', new Date().toString());

    if (link) {
    console.log('Ad found, reload and autoplay.');
    queries.autoplay = true;

    // Reload page
    const base = document.location.origin + document.location.pathname;
    const queryString = createLocationQuery(queries);

    console.log('Open', base + queryString);
    window.open(base + queryString, '_self');
    }
    }).observe(element, {
    characterData: true,
    childList: true,
    attributes: true,
    subtree: true
    });
    });
    }, 1000);
    }();