Greasy Fork is available in English.

跟踪链接净化(B站, 百度)

净化B站跟踪链接(推荐视频),百度<相关搜索、热搜>链接净化

Tính đến 24-02-2023. Xem phiên bản mới nhất.

// ==UserScript==
// @name         跟踪链接净化(B站, 百度)
// @name:zh-TW   跟蹤鏈接凈化(B站, 百度)
// @name:en      Clean Tracking URLs (Bilibili, Baidu)
// @namespace    https://greasyfork.org/en/scripts/456881
// @version      0.4.3
// @description  净化B站跟踪链接(推荐视频),百度<相关搜索、热搜>链接净化
// @description:zh-tw 凈化B站鏈接跟蹤(推薦視頻),百度<相關搜索、熱搜>鏈接凈化
// @description:en Clean Bilibili Tracking URLs (Recommended Videos), Baidu <Related Search><Hot Search> URLs.
// @author       cilxe
// @match        *://www.bilibili.com/*
// @match        *://search.bilibili.com/*
// @match        *://space.bilibili.com/*
// @match        *://live.bilibili.com/*
// @match        *://passport.bilibili.com/*
// @match        *://account.bilibili.com/*
// @match        *://message.bilibili.com/*
// @match        *://member.bilibili.com/*
// @match        *://t.bilibili.com/*
// @match        *://app.bilibili.com/*
// @match        *://www.baidu.com/s*
// @icon         https://www.bilibili.com/favicon.ico
// @run-at       document-body
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @license      MIT
// ==/UserScript==

(() => {
  const TIME_DELAY = 3000;
  // bilibili index strings
  const INDEX_STRING_B1 = 'spm_id_from';
  const INDEX_STRING_B2 = 'vd_source';
  const INDEX_STRING_B3 = 'from_spmid';
  const INDEX_STRING_B4 = 'csource'; // bilibili courses (m.bilibili.com)
  const INDEX_STRING_B5 = 'live_from'; // live.bilibili.com/*
  const INDEX_STRING_B6 = 'sourceFrom';
  // baidu index strings
  const INDEX_STRING_BD1 = 'rsf';
  const INDEX_STRING_BD2 = 'rsv_pq';

  // If <true> block [Lucky Draw (The Selection)] popups at live.bilibili.com.
  const BlockLivePopups = true;

  // Bilibili Restore history state session stack
  function restoreState(indexStr) {
    const URL = window.location.href;
    const VideoIndex = URL.indexOf(indexStr);
    const CleanURL = URL.substring(0, VideoIndex - 1);
    window.history.replaceState({}, 'Restore', CleanURL);
  }
  function resetBiliMetadData() {
    const metas = document.getElementsByTagName('meta');
    for (let i = 0; i < metas.length; i += 1) {
      if (metas[i].name === 'spm_prefix') {
        metas[i].content = '000.0000';
      }
    }
  }
  // remove bilibili Ads
  function removeBiliAds() {
    function run() {
      let index = 0;
      do {
        // Card-Ads
        const cardAds = document.getElementsByTagName('a');
        for (let i = 0; i < cardAds.length; i += 1) {
          if (cardAds[i].hostname.includes('cm.bilibili.com')) {
            cardAds[i].remove();
          }
        }
        index += 1;
      } while (index < 2);
    }
    run();
  }
  // // clean <a> links
  function cleanBiliLinks() {
    const links = document.getElementsByTagName('a');
    for (let i = 0; i < links.length; i += 1) {
      const url = links[i].href;
      const RESULT_1 = url.includes(INDEX_STRING_B1);
      const RESULT_2 = url.includes(INDEX_STRING_B3);
      const RESULT_3 = url.includes(INDEX_STRING_B4);
      const RESULT_4 = url.includes(INDEX_STRING_B5);
      const RESULT_5 = url.includes(INDEX_STRING_B6);
      switch (true) {
        case RESULT_1:
          links[i].href = url.substring(0, url.indexOf(INDEX_STRING_B1) - 1);
          break;
        case RESULT_2:
          links[i].href = url.substring(0, url.indexOf(INDEX_STRING_B3) - 1);
          break;
        case RESULT_3:
          links[i].href = url.substring(0, url.indexOf(INDEX_STRING_B4) - 1);
          break;
        case RESULT_4:
          links[i].href = url.substring(0, url.indexOf(INDEX_STRING_B5) - 1);
          break;
        case RESULT_5:
          links[i].href = url.substring(0, url.indexOf(INDEX_STRING_B6) - 1);
          break;
        default:
          break;
      }
    }
  }
  // block clicking events (link, button, li)
  function blockClickEvents() {
    // link events
    function blockLinkEvents() {
      const links = document.getElementsByTagName('a');
      for (let i = 0; i < links.length; i += 1) {
        if (links[i].getAttribute('data-video-time') === null) {
          if (!links[i].classList.contains('normal')) {
            links[i].addEventListener('click', (e) => {
              e.stopPropagation();
            }, true);
          }
        }
      }
    }
    blockLinkEvents();
    // button events
    const buttons = document.getElementsByTagName('button');
    for (let i = 0; i < buttons.length; i += 1) {
      buttons[i].addEventListener('click', () => {
        blockLinkEvents();
        removeBiliAds();
        setTimeout(() => { blockLinkEvents(); removeBiliAds(); }, 500);
        setTimeout(() => { blockLinkEvents(); removeBiliAds(); }, 1000);
      });
    }
  }
  // clean top menu events
  function cleanBLTopMenu() {
    setTimeout(() => {
      const topEntries = document.getElementsByClassName('v-popover-wrap'); // li
      for (let i = 0; i < topEntries.length; i += 1) {
        topEntries[i].addEventListener('mouseover', () => {
          blockClickEvents();
        }, true);
        const entryLinks = topEntries[i].getElementsByTagName('a');
        for (let index = 0; index < entryLinks.length; index += 1) {
          entryLinks[index].addEventListener('click', (e) => {
            e.stopPropagation();
          }, true);
        }
      }
      const locItems = document.getElementsByClassName('loc-moveclip');
      for (let i = 0; i < locItems.length; i += 1) {
        locItems[i].addEventListener('click', (e) => {
          e.stopPropagation();
        }, true);
      }
      const rightItems = document.getElementsByClassName('right-entry__outside'); // div
      for (let i = 0; i < rightItems.length; i += 1) {
        rightItems[i].addEventListener('click', (e) => {
          e.stopPropagation();
        }, true);
      }
      // 收藏 - 稍后再看
      const favTabs = document.getElementsByClassName('tab-item'); // div
      for (let i = 0; i < favTabs.length; i += 1) {
        favTabs[i].addEventListener('click', () => {
          setTimeout(() => { blockClickEvents(); }, 800);
        }, true);
      }
    }, TIME_DELAY);
  }
  // www.bilibili.com/*, ww.bilibili.com/v/popular/*
  function cleanBMainURL() {
    restoreState(INDEX_STRING_B1);
    restoreState(INDEX_STRING_B2);
    function onFresh() {
      // www.bilibili.com/v/popular/
      function blockPopEvents() {
        // block default events
        const videoCards = document.getElementsByClassName('video-card__content'); // div
        for (let i = 0; i < videoCards.length; i += 1) {
          videoCards[i].addEventListener('click', (e) => {
            e.stopPropagation();
          });
        }
      }
      if (window.location.href.includes('www.bilibili.com/v/popular')) {
        blockPopEvents();
        // block navibar items clicking events
        const naviItems = document.getElementsByClassName('nav-tabs__item'); // div
        for (let i = 0; i < naviItems.length; i += 1) {
          naviItems[i].addEventListener('click', () => {
            setTimeout(() => { blockPopEvents(); blockClickEvents(); }, 700);
            setTimeout(() => { blockPopEvents(); }, 1200);
          });
        }
        // block traking link events after rank-tab clicked
        const tagUL = document.getElementsByClassName('rank-tab')[0]; // li
        if (tagUL != null) {
          const tagLIs = tagUL.getElementsByTagName('li');
          for (let i = 0; i < tagLIs.length; i += 1) {
            tagLIs[i].addEventListener('click', () => {
              setTimeout(() => { blockClickEvents(); }, 700);
            });
          }
        }
      }
    }
    onFresh();
    cleanBiliLinks();
    removeBiliAds();
    blockClickEvents();
    // Loop execution while scrolling
    window.onscroll = () => {
      let topScroll = 0;
      // Scroll range
      const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
      if (scrolls - topScroll > 120) {
        cleanBiliLinks();
        removeBiliAds();
        blockClickEvents();
        onFresh();
        topScroll = scrolls;
      }
    };
  }
  // bilibili search events
  function blockBSearchItemEvents() {
    function blockSearchEvents() {
      // input suggested items
      const suggestItems = document.getElementsByClassName('suggest-item');
      for (let i = 0; i < suggestItems.length; i += 1) {
        suggestItems[i].addEventListener('click', () => {
          blockClickEvents();
          setTimeout(() => { blockClickEvents(); }, 600);
        });
      }
      // search trending items
      const topSearchs = document.getElementsByClassName('trending-item');
      for (let i = 0; i < topSearchs.length; i += 1) {
        topSearchs[i].addEventListener('click', () => {
          setTimeout(() => { blockClickEvents(); }, 600);
        });
      }
      // search history items
      const historyItems = document.getElementsByClassName('history-item');
      for (let i = 0; i < historyItems.length; i += 1) {
        historyItems[i].addEventListener('click', () => {
          setTimeout(() => { blockClickEvents(); }, 600);
        });
      }
    }
    // search input area
    const searchInputs = document.getElementsByClassName('search-input-el');
    searchInputs[0].addEventListener('click', () => {
      blockSearchEvents();
    });
    // clear icon
    const clearIcon = document.getElementsByClassName('clear-icon')[0];
    clearIcon.addEventListener('click', () => {
      setTimeout(() => { blockSearchEvents(); }, 600);
    });
  }
  // search.bilibili.com/*
  function cleanBSearch() {
    restoreState(INDEX_STRING_B1);
    blockClickEvents();
    blockBSearchItemEvents();
    // vui_tabs--nav-item
    const lines = document.getElementsByTagName('li');
    for (let i = 0; i < lines.length; i += 1) {
      lines[i].addEventListener('click', () => {
        blockClickEvents();
        setTimeout(() => { blockClickEvents(); }, 700);
      });
    }
    // paging button clicking event
    const pageButtons = document.getElementsByClassName('vui_pagenation--btn'); // div
    for (let i = 0; i < pageButtons.length; i += 1) {
      pageButtons[i].addEventListener('click', () => {
        blockClickEvents();
        setTimeout(() => { blockClickEvents(); }, 700);
        restoreState(INDEX_STRING_B1);
      });
    }
    setTimeout(() => { blockClickEvents(); }, 700);
    // loop execution while scrolling
    window.onscroll = () => {
      let topScroll = 0;
      const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
      if (scrolls - topScroll > 120) {
        cleanBiliLinks();
        blockClickEvents();
        removeBiliAds();
        topScroll = scrolls;
      }
    };
  }
  // www.bilibili.com/video/*
  function cleanBVideoURL() {
    // Restore State session
    restoreState(INDEX_STRING_B1);
    restoreState(INDEX_STRING_B2);
    cleanBiliLinks();
    blockClickEvents();
    const unfoldVideo = document.getElementsByClassName('rec-footer');
    unfoldVideo[0].addEventListener('click', () => {
      cleanBiliLinks();
      blockClickEvents();
      restoreState(INDEX_STRING_B1);
    });
    // loop execution while scrolling
    window.onscroll = () => {
      let topScroll = 0;
      const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
      if (scrolls - topScroll > 120) {
        cleanBiliLinks();
        blockClickEvents();
        removeBiliAds();
        topScroll = scrolls;
      }
    };
    // video episodes/collections tracking state after clicked
    const episodes = document.getElementsByClassName('video-episode-card'); // div
    for (let i = 0; i < episodes.length; i += 1) {
      episodes[i].addEventListener('click', () => {
        cleanBiliLinks();
        removeBiliAds();
        setTimeout(() => {
          restoreState(INDEX_STRING_B1); restoreState(INDEX_STRING_B2); blockClickEvents();
        }, 1500);
      });
    }
    setTimeout(() => {
      cleanBiliLinks();
      blockClickEvents();
    }, TIME_DELAY);
  }
  // space.bilibili.com/*
  function cleanBSpaceURL() {
    cleanBiliLinks(); // clean <a> links
    blockClickEvents(); // block <a> links clicking events
    function run() {
    // paging    class = 'be-pager'
      const lines = document.getElementsByTagName('li'); // li
      for (let i = 0; i < lines.length; i += 1) {
        lines[i].addEventListener('click', () => {
          blockClickEvents();
          setTimeout(() => { blockClickEvents(); }, 700);
        });
      }
      // side navigation bar click events   class = 'text'
      const links = document.getElementsByTagName('a'); // a
      for (let i = 0; i < links.length; i += 1) {
        links[i].addEventListener('click', () => {
          blockClickEvents();
          setTimeout(() => { blockClickEvents(); }, 700);
        });
      }
      // navigation inputs (sorting)    class = 'be-tab-input'
      const inputs = document.getElementsByTagName('input');
      for (let i = 0; i < inputs.length; i += 1) {
        inputs[i].addEventListener('click', () => {
          blockClickEvents();
          setTimeout(() => { blockClickEvents(); }, 700);
        });
      }
    }
    run();
    window.onscroll = () => {
      let topScroll = 0;
      const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
      if (scrolls - topScroll > 120) {
        run();
        blockClickEvents();
        cleanBiliLinks();
        topScroll = scrolls;
      }
    };
  }
  // live.bilibili.com/*
  const livePopupBlock = (selection) => {
    const iframes = document.getElementsByTagName('iframe');
    for (let i = 0; i < iframes.length; i += 1) {
      if (iframes[i].src.includes('live-lottery')) {
        // document.getElementsByTagName('iframe')[2].style.visibility = 'hidden';
        // document.getElementsByTagName('iframe')[2].style.opacity = 0;
        // iframes[i].style.display = 'none';
        if (selection === true) {
          iframes[i].style.visibility = 'hidden';
        } else {
          iframes[i].style.visibility = '';
        }
      }
    }
  };

  // Baidu related search, Hot search URL cleaning
  function cleanBaiduURL() {
    // all <a> links
    function cleanLinks() {
      // <a> class = "c-color-link"
      const links = document.getElementsByTagName('a');
      for (let i = 0; i < links.length; i += 1) {
        if (links[i].href.includes(INDEX_STRING_BD1)) {
          const index = links[i].href.indexOf(INDEX_STRING_BD1);
          links[i].href = links[i].href.substring(0, index - 1);
        }
        if (links[i].href.includes(INDEX_STRING_BD2)) {
          const index = links[i].href.indexOf(INDEX_STRING_BD2);
          links[i].href = links[i].href.substring(0, index - 1);
        }
      }
    }
    // bottom of html paging block
    function clearPages() {
      const pageLinks = document.getElementById('page').getElementsByTagName('div')[0].getElementsByTagName('a');
      for (let i = 0; i < pageLinks.length; i += 1) {
        if (pageLinks[i].href.includes(INDEX_STRING_BD2)) {
          const index = pageLinks[i].href.indexOf(INDEX_STRING_BD2);
          pageLinks[i].href = pageLinks[i].href.substring(0, index - 1);
        }
      }
    }
    cleanLinks();
    window.onscroll = () => {
      let topScroll = 0;
      const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
      if (scrolls - topScroll > 120) {
        cleanLinks();
        clearPages();
        topScroll = scrolls;
      }
    };
  }

  // Handle different sites
  window.onload = () => {
    const realLocation = window.location;
    const isBilibili = realLocation.hostname.includes('bilibili.com');
    const isBMain = realLocation.hostname.includes('www.bilibili.com');
    const isBVideo = realLocation.href.includes('www.bilibili.com/video');
    const isBSearch = realLocation.hostname.includes('search.bilibili.com');
    const isBSpace = realLocation.hostname.includes('space.bilibili.com');
    const isBLive = realLocation.hostname.includes('live.bilibili.com');
    const isBiliAccount = realLocation.hostname.includes('passport.bilibili.com') || realLocation.hostname.includes('account.bilibili.com');
    const isBMessage = realLocation.hostname.includes('message.bilibili.com');
    const isBMember = realLocation.hostname.includes('member.bilibili.com');
    const isBTrends = realLocation.hostname.includes('t.bilibili.com');
    const isBApp = realLocation.hostname.includes('app.bilibili.com');

    const isBaidu = realLocation.hostname.includes('baidu.com');

    // bilibili
    if (isBilibili) {
      resetBiliMetadData();
      removeBiliAds();
      cleanBLTopMenu();
      // Restore history state session stack
      if (realLocation.href.includes(INDEX_STRING_B1)) {
        restoreState(INDEX_STRING_B1);
      } else if (realLocation.href.includes(INDEX_STRING_B2)) {
        restoreState(INDEX_STRING_B2);
      }
      if (isBMain) {
        if (isBVideo) {
          setTimeout(() => { cleanBVideoURL(); }, 500);
        } else {
          setTimeout(() => { cleanBMainURL(); }, 500);
        }
      } else if (isBSearch) {
        cleanBSearch();
      } else if (isBSpace) {
        setTimeout(() => { cleanBSpaceURL(); }, 500);
      } else if (isBLive) {
        const liveIntervalId = setInterval(livePopupBlock(BlockLivePopups), 1000);
        setTimeout(() => { clearInterval(liveIntervalId); }, TIME_DELAY + 1000 * 300);
      } else if (isBiliAccount || isBMessage || isBMember || isBTrends || isBApp) {
        cleanBiliLinks();
        resetBiliMetadData();
        blockClickEvents();
      }
    } else if (isBaidu) { // Baidu <Related search> <Hot search>
      cleanBaiduURL();
      setTimeout(() => { cleanBaiduURL(); }, 1000);
    }
  };
})();

/*
# Changelog
v0.4.3 2023.02.23  
- Block more tracking events. [Bilibili]
- Clean more links.[Bilibili]
- Restore link jump events at comment area. [Bilibili]
- Script optimisation. [Bilibili]

v0.4.2.1 2023.02.22  
- Restore `<a>` link click-events on precise time jump at comment area.[www.bilibili.com/video]

v0.4.2 2023.02.07  
- Optimised events at the search-input-block. [Bilibili]
- Bug fixes. [search.bilibili.com, www.bilibili.com]

v0.4.1.2 2023.01.28  
- Bug fixes and performance optimisation. [Bilibili]

v0.4.1.1 2023.01.25  
- Expanded the effective pages of the script. [Bilibili]

v0.4.1.0 2023.01.23  
- Performance optimisation and bug fixes.
- Code reduction.

v0.4.0.1 2023.01.21  
- Clean other untracked links. [space.bilibili.com]
- Several bugs fixes. [bilibili.com]

v0.4.0 2023.01.20  
- Clean Bilibili Video page collections clicking event URL state changes. [www.bilibili.com/video/]
- Clean Bilibili Search tracking events. [search.bilibili.com]
- Clean other tracking events (top-menu clicking). [Bilibili]

v0.3.8.3 2023.01.20  
- Fixed tracking event after video sorting navigation bar items clicked. [space.bilibili.com]

v0.3.8.2 2023.01.19  
- Fixed navibar items click events [www.bilibili.com/v/popular].

v0.3.8.1 2023.01.13  
- Clean more links of Baidu.com

v0.3.8 2023.01.06  
- Block Card-Ads for Bilibili. (And now blocked banner-ads & card-ads for Bilibili)
- Block [Lucky Draw (The Selection)] popup at [live.bilibili.com]. Disabled by default.
- (SET [{BlockLivePopups} = true] to enable it.)
- The script may add menus to unlock custom setting.

v0.3.7.1 2023.01.02  
- Fixed [space.bilibili.com] effects after paged, navi-bar clicked or menu-item clicked.
- Added support to clean tracking url at [search.bilibili.com].

v0.3.7 2023-01-02  
- Naming optimisation.
- Script handling optimisation. (Bilibili)
- Added support to block part of Bilibili Ads.

v0.3.6 2022.12.28  
- Optimise Baidu related search URL, paging URL processing method.

v0.3.5 2022.12.27  
- Script logic optimisation.

*/