Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: skip ads that automatically end after a fixed time #2

Merged
merged 1 commit into from
Apr 8, 2022

Conversation

Naccl
Copy link
Contributor

@Naccl Naccl commented Apr 7, 2022

可能是那些长广告跳过次数太多了,现在我只会遇到这种「会在固定时间后自动结束」的广告了,不知脚本是否还在更新

与其它广告有些不同,这种没法点击隐藏的 skip,思路如下图

image-20220407202941871

加了一个函数,直接调用即可跳过这类

但是不知道该怎么在现有的代码中调用(有些看不懂...),我目前是另起了一个脚本......

@ChenZihan-sudo
Copy link
Owner

感谢!这个固定时间跳过广告之前就有做好,但是因为我做的跳过因为加入到调用管理器后就需要手动关掉卡片才可以,后来直接摆烂。稍后我会在执行管理器里添加此方法,并测试可用性后,合并到分支并在greasyfor中注明你为副作者。

@ChenZihan-sudo ChenZihan-sudo merged commit 3eeee74 into ChenZihan-sudo:main Apr 8, 2022
@Naccl
Copy link
Contributor Author

Naccl commented Apr 8, 2022

附上我当前使用的供参考~

// ==UserScript==
// @name         YouTube AD Blocker
// @namespace    https://github.com/Naccl/Youtube-AD-blocker
// @version      1.0
// @description  Skip ads that automatically end after a fixed time.
// @author       Naccl
// @match        *.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// ==/UserScript==

let timer = setInterval(() => {
  check();
}, 500);

function check() {
  console.log('[YouTube AD Blocker] IN LOOP.');
  let detectAd;
  const ad = document.getElementsByClassName('ytp-ad-preview-text');
  if (ad.length) {
    detectAd = ad[0].innerHTML.constructor == String;
  }

  if (detectAd && !document.getElementsByClassName('ytp-ad-skip-button').length) {
    console.log('[YouTube AD Blocker] REMOVE AD.');
    clearInterval(timer);
    skipFixedAD();
  }
}

function skipFixedAD() {
  //open the feedback iframe
  document.getElementsByClassName('ytp-ad-clickable')[0].click();
  const observerInit = { childList: true, subtree: true };

  //In the first time, wo should detect the iframe element.
  //After the first time, the iframe element will always exist.
  const iframeObserver = new MutationObserver(() => {
    const iframe = document.getElementById('iframe');
    if (iframe) {
      iframeObserver.disconnect();

      function iframeLoaded() {
        iframe.removeEventListener('load', iframeLoaded, true);

        //get feedback iframe document
        const iframeDocument = iframe.contentWindow.document;
        //click feedback button to open the confirm dialog (the element id or class are random, so we need XPath)
        document.evaluate('/html/body/c-wiz/div/div/div[2]/div[2]/div/div[1]/div[1]/div/div[2]/div[2]/div/button', iframeDocument).iterateNext().click();

        const iframeBody = document.evaluate('/html/body', iframeDocument).iterateNext();
        const okBtnObserver = new MutationObserver(() => {
          //get ok button after dialog created
          const okBtn = document.evaluate('/html/body/div[2]/div/div[2]/span/div/div/div[2]/div[2]/button', iframeDocument).iterateNext();
          if (okBtn) {
            okBtnObserver.disconnect();
            okBtn.click();

            //There may be delay and we need to detect the ok tips.
            //But ComputedStyle has not change event, MutationObserver can't do it.
            let okTipsTimer = setInterval(() => {
              //If the feedback is done, it will change from 'none' to 'flex'.
              const finishedTipsDisplay = getComputedStyle(document.evaluate('/html/body/c-wiz/div/div/div[2]/div[1]', iframeDocument).iterateNext(), null).display;
              if (finishedTipsDisplay !== 'none') {
                clearInterval(okTipsTimer);
                //Finished, close the iframe, the video will continue automatically.
                document.evaluate('/html/body/c-wiz/div/div/div[1]/div[2]/div/button', iframeDocument).iterateNext().click();
                //reset timer
                timer = setInterval(() => {
                  check();
                }, 500);
              }
            }, 50);
          }
        });
        okBtnObserver.observe(iframeBody, observerInit);
      }
      //listen for the iframe element load event
      iframe.addEventListener('load', iframeLoaded, true);
    }
  });
  iframeObserver.observe(document, observerInit);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants