YAAS (YouTube Ads Auto Skip)

Automatically closes the banner ad or clicks the "Skip ad" button.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name           YAAS (YouTube Ads Auto Skip)
// @description    Automatically closes the banner ad or clicks the "Skip ad" button.
// @name:uk        YAAS (Автоматичний пропуск реклами на YouTube).
// @description:uk Автоматично закриває рекламний банер чи клікає по кнопці "Пропустити рекламу".
// @version        3.0.5
// @namespace      https://greatest.deepsurf.us/uk/users/741855
// @author         boboha
// @match          *://*.youtube.com/*
// ==/UserScript==

(function() {
    'use strict';

    let skiped = true,
        video_speed = 1,
        player,
        video;
    const SEC = 1000,
          TO = 0 * SEC,
          TO_SUBSCIBED_VIDEO = 10 * SEC,
          TO_SUBSCIBED_BANNER = 5 * SEC,
          AD_SPEED = 6,
          log = (...msg) => { console.log('[YAAS]', ...msg) },
          isSubscribed = () => document.querySelector('#subscribe-button [subscribed]') ? true : false,
          skipVideo = (btn) => {
              skiped = false;
              btn.addEventListener('click', setSkiped, false);
              setTimeout(() => {
                  skip(btn);
              }, isSubscribed() ? TO_SUBSCIBED_VIDEO : TO);
          },
          setSkiped = () => { skiped = true; log('Video skiped!') },
          skip = (btn) => {
              if (btn.nodeType === 1 && getComputedStyle(btn).display === 'inline-block') {
                  btn.click();
              } else {
                  setTimeout(() => {
                      !skiped && skip(btn);
                  }, 100);
              }
          },
          closeBanner = (btn) => {
              btn.addEventListener('click', setClosed, false);
              setTimeout(() => {
                  btn.click();
              }, isSubscribed() ? TO_SUBSCIBED_BANNER : TO);
          },
          setClosed = () => { log('Banner closed!') },
          observer = new MutationObserver(mutations => {
                  for (const mutation of mutations) {
                      try {
                          if (mutation.target.className === 'video-ads ytp-ad-module') {
                              if (mutation.addedNodes.length) {
                                  // Video loading
                                  if (mutation.addedNodes[0].className === 'ytp-ad-player-overlay') {
                                      if (!video.muted) video.muted = true;
                                      if (video.playbackRate != AD_SPEED) video.playbackRate = AD_SPEED;
                                      log('Video is loaded...', '(', Math.round(video.duration), 's )');
                                  }
                                  // Banner loading
                                  else if (mutation.addedNodes[0].className === 'ytp-ad-overlay-slot') {
                                      log('Banner is loaded...');
                                      // Banner closing
                                      const close_button = mutation.addedNodes[0].querySelector('.ytp-ad-overlay-close-container > .ytp-ad-overlay-close-button');
                                      close_button && closeBanner(close_button);
                                  }
                                  // Pre ad countdown start
                                  else if (mutation.addedNodes[0].className === 'ytp-ad-message-overlay') {
                                      video_speed = video.playbackRate;
                                  }
                                  // Interstitial ad countdown
                                  else if (mutation.addedNodes[0].className === 'ytp-ad-action-interstitial') {
                                      if (!isSubscribed()) {
                                          const btn = mutation.target.querySelector('.ytp-ad-text.ytp-ad-skip-button-text');
                                          btn && btn.click();
                                          log('Interstitial ad skiped!');
                                      }
                                  }
                                  // else {}
                              } else if (mutation.removedNodes.length) {
                                  if (mutation.removedNodes[0].id.startsWith('player-overlay')) {
                                      video.muted=false;
                                      video.playbackRate = video_speed;
                                      log('Video ended');
                                  }
                                  // Pre ad countdown end
                                  else if (mutation.removedNodes[0].className === 'ytp-ad-message-overlay') {
                                      video.muted = true;
                                      video.playbackRate = AD_SPEED;
                                  }
                              }
                          }

                          // Video skiping
                          if (mutation.target.className === 'ytp-ad-skip-button-slot') {
                              const skip_button = mutation.target.querySelector('.ytp-ad-skip-button-container > .ytp-ad-skip-button');
                              skip_button && skipVideo(skip_button);
                          }
                      } catch (e) {
                          console.groupCollapsed(e.message, mutation.target);
                          log(mutation);
                          console.groupEnd();
                      }
                  }
          }),
          initPlayer = () => {
              if (player) {
                  log('Init Player');
              } else {
                  player = document.querySelector('#movie_player');
                  initPlayer();
              }
          },
          toggleObserver = () => {
              if (location.pathname === '/watch') {
                  if (player) {
                      if (!video) {
                          video = document.querySelector('video.html5-main-video');
                          observer.observe(player, {childList: true, attributes: true, subtree: true});
                          log('Observer start');
                      }
                  } else {
                      initPlayer();
                      toggleObserver();
                  }
              } else {
                  if (player) {
                      observer.disconnect();
                      player = null;
                      video = null;
                      log('Observer stop');
                  } else {
                    initPlayer();
                  }
              }
          };

    window.addEventListener('yt-navigate-start', toggleObserver);
    toggleObserver();

})();