// ==UserScript==
// @name 跟踪链接净化(B站, 百度,CSDN)
// @name:zh-TW 跟蹤鏈接凈化(B站, 百度,CSDN))
// @name:en Clean Tracking URLs (Bilibili, Baidu, CSDN)
// @namespace https://greasyfork.org/en/scripts/456881
// @version 0.4.6-2023.03.11
// @description 净化B站,百度(未加密的)和 CSDN 链接
// @description:zh-tw 凈化B站,百度(未加密的)和 CSDN 鏈接
// @description:en Clean Bilibili, Baidu (Unencrypted), CSDN Tracking URLs.
// @author cilxe
// @match *://*.bilibili.com/*
// @exclude *://*.bilibili.com/api/*
// @exclude *://api.bilibili.com/*
// @exclude *://api.*.bilibili.com/*
// @exclude *://bbq.bilibili.com/*
// @match *://*.baidu.com/*
// @match *://*.douyin.com/search/*
// @match *://*.csdn.net/*
// @icon https://www.bilibili.com/favicon.ico
// @run-at document-start
// @license MIT
// ==/UserScript==
(() => {
const DELAY_TIME = { fast: 600, normal: 1000, slow: 3000 };
// Sites with its tracking or other params
const Indexes = {
bilibili: ['spm_id_from', 'spm_id', 'vd_source', 'from_spmid', 'csource',
'sourceFrom', 'hotRank', 'live_from', 'from', 'launch_id', 'msource', 'popular_rank',
'session_id', 'business', 'sort_field', 'broadcast_type', 'is_room_feed',
'is_live_full_webview', 'is_live_webview', 'refer_from', 'vt', 't'],
baidu: ['rsv_idx', 'hisfilter', 'rsf', 'rsv_pq', 'rsv_t', 'qid', 'rsv_dl', 'sa', 'rqid', // www.baoidu.com/*
'oq', 'gpc', 'usm', 'tfflag', 'ie', 'bs', 'rqlang', 'tn', 'sc_us', 'wfr', 'for', 'from',
'topic_pn', 'rsp', 'rs_src', 'f', 'rsv_page', 'dyTabStr', 'tn', 'ct', 'lm', 'site',
'sites', 'fr', 'cl', 'bsst', 'lid', 'rsv_spt', 'rsv_bp', 'src', 'sfrom', 'utm_source',
'utm_medium', 'refer', 'zp_fr', 'channel', 'p_from', 'n_type', 'eqid',
'uname', 'uid', 'client_type', 'task', 'locate', 'page', 'type', 'is_new_user', // tieba.baidu.com/*
'frwh', 'obj_id', 'url ', 'fid', 'fname', 'tid', '_t', 'topic_name', 'frs',
],
douyin: ['rsv_idx', 'hisfilter', 'source', 'aid', 'enter_from', 'focus_method', 'gid'],
csdn: ['spm', 'source', 'utm_source', 'ops_request_misc', 'request_id', 'biz_id', 'utm_medium', 'utm_term'],
};
const sites = [Indexes.bilibili, Indexes.baidu, Indexes.douyin, Indexes.csdn];
let topScroll = 0; // onscroll events
// If <true> block [Lucky Draw (The Selection)] popups at live.bilibili.com.
const BlockLivePopups = true;
// Restore history state, remove redundant params
function restoreState(site) {
const OLD_URL = window.location.href;
const url = new URL(OLD_URL);
const params = url.searchParams;
site.forEach((k) => { if (params.has(k)) { params.delete(k); } });
const NEW_URL = url.toString();
window.history.replaceState({}, 'Restore', NEW_URL);
}
// clean <a> links
function cleanLinks(site) {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].href !== '') {
const url = new URL(links[i].href);
const params = url.searchParams;
site.forEach((k) => { if (params.has(k)) { params.delete(k); } });
links[i].href = url.toString();
}
}
}
// ====================================== Bilibili ======================================
// Remove Bilibili metadata
function removeBiliMetadData() {
const metas = document.getElementsByTagName('meta');
for (let i = 0; i < metas.length; i += 1) {
if (metas[i].name === 'spm_prefix') {
metas[i].remove();
}
}
}
// Remove Bilibili Card Ads
function removeBiliAds() {
let index = 0;
do {
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);
}
// block clicking events (link, button, li)
function blockClickEvents() {
function blockLinkEvents() {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].getAttribute('data-video-time') === null) {
const isLinkJump = links[i].classList.contains('jump-link');
const isLinkJumpVideo = links[i].classList.contains('video-time') || links[i].classList.contains('video');
if (!(isLinkJump && isLinkJumpVideo)) {
links[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
}
}
}
blockLinkEvents();
const buttons = document.getElementsByTagName('button');
for (let i = 0; i < buttons.length; i += 1) {
buttons[i].addEventListener('click', () => {
blockLinkEvents();
removeBiliAds();
setTimeout(() => { blockLinkEvents(); removeBiliAds(); }, DELAY_TIME.fast);
setTimeout(() => { blockLinkEvents(); removeBiliAds(); }, DELAY_TIME.normal);
});
}
}
// Loop execution when mouse moving
function bilibiliListenMoving() {
document.onmousemove = (e) => {
if (e.clientY < 170) {
cleanLinks(sites[0]);
blockClickEvents();
}
};
}
// Loop execution when mouse moving
function biliListenScrolling() {
window.onscroll = () => {
// Current position
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 150) {
cleanLinks(sites[0]);
removeBiliAds();
blockClickEvents();
topScroll = scrolls;
}
};
}
// clean top menu events
function cleanBLTopMenu() {
bilibiliListenMoving();
const biliHeader = document.getElementById('biliMainHeader');
biliHeader.onmousemove = (e) => {
console.log(e.clientY);
cleanLinks(sites[0]);
blockClickEvents();
};
}
// www.bilibili.com/*, ww.bilibili.com/v/popular/*
function cleanBMainURL() {
cleanLinks(sites[0]);
bilibiliListenMoving();
removeBiliAds();
biliListenScrolling();
}
// 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(); }, DELAY_TIME.fast);
});
}
// search trending items
const topSearchs = document.getElementsByClassName('trending-item');
for (let i = 0; i < topSearchs.length; i += 1) {
topSearchs[i].addEventListener('click', () => {
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
// search history items
const historyItems = document.getElementsByClassName('history-item');
for (let i = 0; i < historyItems.length; i += 1) {
historyItems[i].addEventListener('click', () => {
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
}
// 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(); }, DELAY_TIME.fast);
});
}
// search.bilibili.com/*
function cleanBSearch() {
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(); }, DELAY_TIME.fast + 100);
});
}
// 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(); }, DELAY_TIME.fast + 100);
restoreState(sites[0]);
});
}
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast + 100);
window.onscroll = () => {
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
restoreState(sites[0]);
cleanLinks(sites[0]);
blockClickEvents();
removeBiliAds();
topScroll = scrolls;
}
};
}
// www.bilibili.com/video/*
function cleanBVideoURL() {
cleanLinks(sites[0]);
blockClickEvents();
const unfoldVideo = document.getElementsByClassName('rec-footer');
unfoldVideo[0].addEventListener('click', () => {
cleanLinks(sites[0]);
blockClickEvents();
restoreState(sites[0]);
});
window.onscroll = () => {
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
restoreState(sites[0]);
cleanLinks(sites[0]);
blockClickEvents();
removeBiliAds();
topScroll = scrolls;
}
};
// video episodes/collections tracking state after clicked
const episodes = document.getElementsByClassName('rec-footer'); // div
for (let i = 0; i < episodes.length; i += 1) {
episodes[i].addEventListener('click', () => {
cleanLinks(sites[0]);
removeBiliAds();
setTimeout(() => {
restoreState(sites[0]); blockClickEvents();
}, 1000);
}, true);
}
setTimeout(() => {
restoreState(sites[0]);
cleanLinks(sites[0]);
blockClickEvents();
}, DELAY_TIME.slow);
}
// space.bilibili.com/*
function cleanBSpaceURL() {
cleanLinks(sites[0]);
blockClickEvents();
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(); }, DELAY_TIME.fast);
});
}
// 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(); }, DELAY_TIME.fast);
});
}
// 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(); }, DELAY_TIME.fast);
});
}
}
run();
window.onscroll = () => {
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanLinks(sites[0]);
run();
blockClickEvents();
topScroll = scrolls;
}
};
}
// live.bilibili.coom popups
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 = '';
}
}
}
};
// live.bilibili.com/*
function cleanBLive() {
cleanLinks(sites[0]);
blockClickEvents();
const navis = document.getElementsByClassName('tabs__tag-item');
for (let i = 0; i < navis.length; i += 1) {
navis[i].addEventListener('click', () => {
setTimeout(() => { cleanLinks(sites[0]); }, 100);
setTimeout(() => { cleanLinks(sites[0]); }, DELAY_TIME.normal);
});
}
const tabItems = document.getElementsByClassName('tab-item');
for (let i = 0; i < tabItems.length; i += 1) {
tabItems[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { cleanLinks(sites[0]); }, DELAY_TIME.fast);
});
}
window.onscroll = () => {
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanLinks(sites[0]);
topScroll = scrolls;
}
};
const liveIntervalId = setInterval(livePopupBlock(BlockLivePopups), DELAY_TIME.normal);
setTimeout(() => { clearInterval(liveIntervalId); }, DELAY_TIME.slow + 1000 * 300);
}
// ====================================== Baidu ======================================
function cleanBDLinks(site) {
cleanLinks(sites[1]);
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].href !== '') {
const link = links[i].href;
if (link.hostname.includes('zhidao.baidu.com') && link.pathname === '/q') { link.pathname = '/search'; }
links[i].href = link.replace('from=', '');
}
}
// area
const areas = document.getElementsByTagName('area');
if (areas.length === 1) {
const areaURL = new URL(areas[0].href);
const params = areaURL.searchParams;
site.forEach((k) => { if (params.has(k)) { params.delete(k); } });
areas[0].href = areaURL.toString();
}
}
function blockBDTrackingEvents() {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
links[i].addEventListener('click', () => {
setTimeout(() => { cleanBDLinks(sites[1]); }, DELAY_TIME.fast - 200);
}, true);
}
}
// Baidu related search, Hot search URL cleaning
function cleanBaiduURL() {
cleanBDLinks(sites[1]);
blockBDTrackingEvents();
window.onscroll = () => {
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 200) {
cleanBDLinks(sites[1]);
topScroll = scrolls;
}
};
}
// csdn.net
function cleanCSDN() {
restoreState(sites[3]);
cleanLinks(sites[3]);
// CSDN.net tracking events
function blockCSDNEvents() {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
links[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
}
document.onmousemove = (e) => {
if (e.clientY < 170 || e.clientY > 450) {
cleanLinks(sites[3]);
blockCSDNEvents();
}
};
window.onscroll = () => {
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 150) {
cleanLinks(sites[3]);
blockCSDNEvents();
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 isBaidu = realLocation.hostname.includes('baidu.com');
const isDouyin = realLocation.hostname.includes('douyin.com');
const isCSDN = realLocation.hostname.includes('csdn.net');
switch (true) {
case isBilibili: // Bilibili
restoreState(sites[0]);
removeBiliMetadData();
removeBiliAds();
cleanBLTopMenu();
switch (isBilibili) {
case isBmain:
if (isBvideo) {
setTimeout(() => { cleanBVideoURL(); }, DELAY_TIME.fast);
} else {
setTimeout(() => { cleanBMainURL(); }, DELAY_TIME.fast);
}
break;
case isBsearch:
cleanBSearch();
break;
case isBspace:
setTimeout(() => { cleanBSpaceURL(); }, DELAY_TIME.fast);
break;
case isBlive:
cleanBLive();
setTimeout(() => { cleanLinks(sites[0]); }, DELAY_TIME.normal + 200);
setTimeout(() => { cleanLinks(sites[0]); }, DELAY_TIME.slow);
break;
default: // passport account message member t app manga show link
cleanLinks();
biliListenScrolling();
break;
}
break;
case isBaidu:
restoreState(sites[1]);
setTimeout(() => { cleanBaiduURL(); }, DELAY_TIME.normal);
break;
case isDouyin:
restoreState(sites[2]);
break;
case isCSDN:
cleanCSDN();
break;
default:
break;
}
};
})();
/*
# Changelog
v0.4.6-2023.03.11
- Clean more baidu links. [Baidu]
- Clean CSDN URLs. [csdn.net]
- Script optimisation and bug fixes.
- Code reduction.
v0.4.5 2023.03.09
- Clean more URL under Baidu.com, replace search URL state. [Baidu]
- Script optimisation and bug fixes. [bilibili]
- Code reduction.
v0.4.4 2023.03.05
- Restore history state at live.bilibili.com. [Bilibili]
- Clean Bilibili Manga & Show links. [manga/show.bilibili.com]
- Clean redundant params at douyin.com search page. [Douyin]
- Code reduction.
v0.4.3.1 2023.03.01
- Clean more links at live.bilibili.com. [Bilibili]
- Script optimisation.
v0.4.3 2023.02.24
- 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.
v0.3.4 2022.12.23
- Code optimisation. Fixed script's effect range. [Bilibili]
v0.3.3 2022.12.23
- Added site support:Clean Baidu <Related Search> URLs.
- Script optimisations. [space.bilibili.com]
v0.3.2 2022.12.22
- Restore pushstate session (address bar url display, replace history). [Bilibili]
- Minor optimisations. [Bilibili]
v0.3.1 2022.12.22
- Optimized the effective range. [Bilibili]
v0.3 2022.12.22
- Added Bilibili Home page, Popular/Rank page, now it can takeeffect on most pages. [Bilibili]
v0.2 2022.12.21
- Added missing tags. [Bilibili]
v0.1 2022.12.20
- Initial release.
*/